Oskar Oskar - 1 month ago 10
Javascript Question

Meteor & locks in publication

Scenario: I want to display an item to the user, then lock it, so that no one else can see it, and once the user is done with it, display the next item.

The problem is that the query in the publication has to check for the lock. So as soon as you change the lock, the cursor updates and the item changes.

How could this be solved?

Edit:
Sample code in publication, which would not work:

var item = Items.find({
locked: false
}, {
limit: 1
});

var itemObj = item.fetch()[0];
Items.update(itemObj._id, {$set: {locked: true}});
return item;

Answer

One solution would be to first query the database, update it, then send the cursor on the document:

Meteor.publish('somePub', function() {
  var itemId = Items.findOne({locked : false})._id;

  Items.update(itemId, {$set: {locked: true}});

  return Items.find(itemId);
});

Step-by-step:

  • findOne returns a document, not a cursor. No need to fetch()[0] then. We only need its _id;
  • The update is the same as yours;
  • We send the cursor, aiming for a single document because we provided an ID as parameter.

Note that you will need to stop the subscription and re-run it each time you want to select a new item. If you do that with template subscriptions, you could simply reload the template, causing the subscription to be stopped then re-ran (for example, by clicking a "Next" button).