Skip to content

Commit f02dad8

Browse files
authored
Merge pull request #645 from share/local-presence-destroy-race
🐛 Fix `Presence.destroy()` race condition
2 parents 91cae28 + b975ab1 commit f02dad8

File tree

2 files changed

+29
-1
lines changed

2 files changed

+29
-1
lines changed

lib/client/presence/presence.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@ Presence.prototype.destroy = function(callback) {
6161
[
6262
function(next) {
6363
async.each(localIds, function(presenceId, next) {
64-
presence.localPresences[presenceId].destroy(next);
64+
var localPresence = presence.localPresences[presenceId];
65+
if (!localPresence) return next();
66+
localPresence.destroy(next);
6567
}, next);
6668
},
6769
function(next) {

test/client/presence/presence.js

+26
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,32 @@ describe('Presence', function() {
146146
], errorHandler(done));
147147
});
148148

149+
it('does not throw if LocalPresence destroys before Presence', function(done) {
150+
var localPresence1 = presence1.create('presence-1');
151+
152+
async.series([
153+
presence1.subscribe.bind(presence1),
154+
function(next) {
155+
// Middleware that ensures the presence update replies before the
156+
// unsubscribe, so the local presence is destroyed first
157+
var replies = [];
158+
backend.use('reply', function(message, cb) {
159+
if (!replies) return cb();
160+
if (message.reply.a !== 'p') return replies.push(cb);
161+
var _replies = replies;
162+
replies = null;
163+
cb();
164+
_replies.forEach(function(reply) {
165+
reply();
166+
});
167+
});
168+
169+
presence1.destroy(next);
170+
localPresence1.destroy(errorHandler(done));
171+
}
172+
], done);
173+
});
174+
149175
it('throws if trying to create local presence when wanting destroy', function(done) {
150176
presence2.destroy(errorHandler(done));
151177
expect(function() {

0 commit comments

Comments
 (0)