Skip to content

Commit 01a31b4

Browse files
committed
End pending method when connection drops
1 parent 5ea8b5c commit 01a31b4

File tree

2 files changed

+105
-7
lines changed

2 files changed

+105
-7
lines changed

lib/ddp-client.js

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,16 @@ var DDPClient = function(opts) {
4848
self._nextId = 0;
4949
self._callbacks = {};
5050
self._updatedCallbacks = {};
51+
self._pendingMethods = {};
5152
self._observers = {};
5253
};
5354

55+
56+
DDPClient.ERRORS = {
57+
DISCONNECTED: new Error("DDPClient: Disconnected from DDP server")
58+
};
59+
60+
5461
/**
5562
* Inherits from EventEmitter
5663
*/
@@ -80,6 +87,7 @@ DDPClient.prototype._prepareHandlers = function() {
8087

8188
self.socket.on("close", function(event) {
8289
self.emit("socket-close", event.code, event.reason);
90+
self._endPendingMethodCalls();
8391
self._recoverNetworkError();
8492
});
8593

@@ -320,6 +328,24 @@ DDPClient.prototype.connect = function(connected) {
320328
}
321329
};
322330

331+
DDPClient.prototype._endPendingMethodCalls = function() {
332+
var self = this;
333+
var ids = _.keys(self._pendingMethods);
334+
self._pendingMethods = {};
335+
336+
ids.forEach(function (id) {
337+
if(self._callbacks[id]) {
338+
self._callbacks[id](DDPClient.ERRORS.DISCONNECTED);
339+
delete self._callbacks[id];
340+
}
341+
342+
if(self._updatedCallbacks[id]) {
343+
self._updatedCallbacks[id]();
344+
delete self._updatedCallbacks[id];
345+
}
346+
});
347+
};
348+
323349
DDPClient.prototype._makeSockJSConnection = function() {
324350
var self = this;
325351

@@ -389,13 +415,23 @@ DDPClient.prototype.call = function(name, params, callback, updatedCallback) {
389415
var self = this;
390416
var id = self._getNextId();
391417

392-
if (callback) {
393-
self._callbacks[id] = callback;
394-
}
418+
self._callbacks[id] = function () {
419+
delete self._pendingMethods[id];
395420

396-
if (updatedCallback) {
397-
self._updatedCallbacks[id] = updatedCallback;
398-
}
421+
if (callback) {
422+
callback.apply(this, arguments);
423+
}
424+
};
425+
426+
self._updatedCallbacks[id] = function () {
427+
delete self._pendingMethods[id];
428+
429+
if (updatedCallback) {
430+
updatedCallback.apply(this, arguments);
431+
}
432+
};
433+
434+
self._pendingMethods[id] = true;
399435

400436
self._send({
401437
msg : "method",

test/ddp-client.js

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,68 @@ describe('Automatic reconnection', function() {
134134
done();
135135
}, 15);
136136
});
137+
138+
it('should save currently running method calls', function() {
139+
var ddpclient = new DDPClient();
140+
ddpclient._getNextId = sinon.stub().returns('_test');
141+
ddpclient._send = Function.prototype;
142+
143+
ddpclient.connect();
144+
ddpclient.call();
145+
146+
assert("_test" in ddpclient._pendingMethods)
147+
});
148+
149+
it('should remove id when callback is called', function() {
150+
var ddpclient = new DDPClient();
151+
ddpclient._getNextId = sinon.stub().returns('_test');
152+
ddpclient._send = Function.prototype;
153+
154+
ddpclient.connect();
155+
ddpclient.call();
156+
157+
assert("_test" in ddpclient._pendingMethods)
158+
159+
ddpclient._callbacks._test();
160+
assert(!("_test" in ddpclient._pendingMethods))
161+
});
162+
163+
it('should remove id when updated-callback is called', function() {
164+
var ddpclient = new DDPClient();
165+
ddpclient._getNextId = sinon.stub().returns('_test');
166+
ddpclient._send = Function.prototype;
167+
168+
ddpclient.connect();
169+
ddpclient.call();
170+
171+
assert("_test" in ddpclient._pendingMethods)
172+
173+
ddpclient._updatedCallbacks._test();
174+
assert(!("_test" in ddpclient._pendingMethods))
175+
});
176+
177+
it('should end method calls which could not be completed', function() {
178+
var ddpclient = new DDPClient();
179+
var callback = sinon.spy();
180+
var updatedCallback = sinon.spy();
181+
182+
ddpclient._pendingMethods = { _test: true };
183+
ddpclient._callbacks = { _test: callback };
184+
ddpclient._updatedCallbacks = { _test: updatedCallback };
185+
186+
ddpclient.connect();
187+
ddpclient.socket.emit('close', {});
188+
189+
assert(callback.calledOnce);
190+
assert(callback.calledWithExactly(DDPClient.ERRORS.DISCONNECTED));
191+
192+
assert(updatedCallback.calledOnce);
193+
194+
// callbacks should be removed after calling them
195+
assert(!("_test" in ddpclient._callbacks));
196+
assert(!("_test" in ddpclient._updatedCallbacks));
197+
assert(!("_test" in ddpclient._pendingMethods));
198+
});
137199
});
138200

139201

@@ -408,4 +470,4 @@ function WithRequestGet(getFn, fn) {
408470
fn();
409471

410472
request.get = originalGet;
411-
}
473+
}

0 commit comments

Comments
 (0)