The issue
I’m encountering an issue that pops up semi-frequently on some of our production Meteor app servers where method invocations queue up but never run, despite successful ping/pong DDP messages (and subscriptions) sending.
What I know so far
It’s extremely difficult to debug since it’s a minified production bundle, but here’s what I’ve found:
Opening Chrome console and calling methods works as expected (I receive onResultReceived
callback and normal asynchronous callback). For example:
Meteor.apply('someMethod', [], {
onResultReceived: function() {
console.log('results received');
}
}, function(e, r) {
console.log(e);
console.log(r);
});
Properly logs:
results received
null
someresult
If I check my DDP connection’s outstanding method blocks (Meteor.connection._outstandingMethodBlocks
), it properly returns an empty array.
Where it breaks
The issue begins though, once I try to call a login method. To narrow down the issue, I call the Meteor login
method by using apply, like so:
var loginArgs = [{
user: {email: 'user@site.com'},
password: Accounts._hashPassword('secretpassword')
}];
var options = {};
options.onResultReceived = function() { console.log(arguments); };
Meteor.apply('login', loginArgs, options, function (err, result) {
console.log('--')
console.log(err);
console.log('--')
console.log(result);
});
Once this is run, the onResultReceived
fires and returns properly with my userId, token and tokenExpires. The websocket message is visible in my devtools network tab. But for some reason, the callback is never fired.
If I check Meteor.connection._outstandingMethodBlocks
at this point, there’s still an object in it from my login
method call, but the method block methods
array is empty.
If I inspect Meteor.connection._methodInvokers
, I can still see the MethodInvoker there with the following properties:
This completely breaks the client-side app and prevents any future Meteor methods from being invoked, despite the fact that I can still receive downstream messages from websockets (e.g. subscription data).
Conclusions so far
The only conclusion I can draw so far is that the invoker._dataVisible
is never set to true
, which means that the callback is never invoked. See the “_maybeInvokeCallback” function check for _dataIsVisible boolean.
Additional notes
I can force the callback to eventually run by:
- Calling
Meteor.connection._stream.reconnect({_force: true});
or - Copying the websocket message from my chrome network tab that has the “msg: result” and pasing it into
Meteor.connection._livedata_connected(msg)
as themsg
parameter
My question
What would prevent calling the RPC login
from ever invoking a callback? How can I further get to the bottom of this?