@robfallows Thanks for the article link. I had read that, but reading it again helped. I think I’ve narrowed down the issue.
Here’s the problem: I have a Meteor Method that calls a server function that does an asynchronous database update. So if I have absolutely no async/await
code, repeated calls to the Meteor Method would naturally block each other except for the fact that I am doing an asynchronous database update that returns immediately. So the Meteor Method doesn’t block the database update. I need to block each Meteor Method call until that database update resolves. So what I did was wrap the database update in a Promise
- which works (I’ve swapped out the database update code with a setTimeout
which illustrates the same issue):
Meteor.methods({
selfBlockingMethod: async function(order) {
console.log("selfBlockingMethod:", order, "was called...");
// Call server function that runs a Promise-wrapped asynchronous function
await _promiseWrappedSetTimeout();
console.log("selfBlockingMethod:", order, "has finished...");
}
});
var _promiseWrappedSetTimeout = function() {
return new Promise(function(resolve, reject) {
Meteor.setTimeout(function() {
console.log("_promiseWrappedSetTimeout: timeout is up!...");
resolve(true);
}, 3000);
});
}
On the client console, if I run Meteor.call("selfBlockingMethod", 1)
, I get the following expected output on the server:
selfBlockingMethod: 1 was called...
_promiseWrappedSetTimeout: timeout is up! (three seconds later)
selfBlockingMethod: 1 has finished...
Seems like it worked right? It does for one call. The problem is if I fire this off in the console:
Meteor.call("selfBlockingMethod", 1);
Meteor.call("selfBlockingMethod", 2);
Meteor.call("selfBlockingMethod", 3);
Because the Meteor Method is set to async
, I get this which is not what I want:
selfBlockingMethod: 1 was called...
selfBlockingMethod: 2 was called...
selfBlockingMethod: 3 was called...
_promiseWrappedSetTimeout: timeout is up! (same time 3 secs later)
_promiseWrappedSetTimeout: timeout is up! (same time 3 secs later)
_promiseWrappedSetTimeout: timeout is up! (same time 3 secs later)
selfBlockingMethod: 1 has finished...
selfBlockingMethod: 2 has finished...
selfBlockingMethod: 3 has finished...
I need the Meteor Method to keep self-blocking like a normal Meteor Method. So I tried removing the async
off the Meteor Method and putting it on a wrapper function defined within the method:
Meteor.methods({
selfBlockingMethod: function(order) {
console.log("selfBlockingMethod:", order, "was called...");
// Create a wrapper function that's async
let _wrapperFunction = async function() {
if(Meteor.isServer)
// Call server function that runs a Promise-wrapped asynchronous function
await _promiseWrappedSetTimeout();
}
}
// Call the wrapper function
_wrapperFunction();
console.log("selfBlockingMethod:", order, "has finished...");
}
});
However, this doesn’t work. The Meteor Method finishes instantly and doesn’t await
the setTimeout
to complete like before.
selfBlockingMethod: 1 was called...
selfBlockingMethod: 1 has finished...
_promiseWrappedSetTimeout: timeout is up! (three seconds later)
How can this be achieved!? I feel like I’ve tried everything. I’m probably not doing something right.