Skip to content

Commit 1c96205

Browse files
authored
fix: LiveQuerySubscription.unsubscribe resolves promise before unsubscribing completes (#1727)
1 parent 6899c0f commit 1c96205

File tree

4 files changed

+29
-40
lines changed

4 files changed

+29
-40
lines changed

src/LiveQueryClient.js

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -224,19 +224,20 @@ class LiveQueryClient extends EventEmitter {
224224
* After calling unsubscribe you'll stop receiving events from the subscription object.
225225
*
226226
* @param {object} subscription - subscription you would like to unsubscribe from.
227+
* @returns {Promise | undefined}
227228
*/
228-
unsubscribe(subscription: Object) {
229+
unsubscribe(subscription: Object): ?Promise {
229230
if (!subscription) {
230231
return;
231232
}
232-
233-
this.subscriptions.delete(subscription.id);
234233
const unsubscribeRequest = {
235234
op: OP_TYPES.UNSUBSCRIBE,
236235
requestId: subscription.id,
237236
};
238-
this.connectPromise.then(() => {
239-
this.socket.send(JSON.stringify(unsubscribeRequest));
237+
return this.connectPromise.then(() => {
238+
return this.socket.send(JSON.stringify(unsubscribeRequest));
239+
}).then(() => {
240+
return subscription.unsubscribePromise;
240241
});
241242
}
242243

@@ -400,9 +401,14 @@ class LiveQueryClient extends EventEmitter {
400401
}
401402
break;
402403
}
403-
case OP_EVENTS.UNSUBSCRIBED:
404-
// We have already deleted subscription in unsubscribe(), do nothing here
404+
case OP_EVENTS.UNSUBSCRIBED: {
405+
if (subscription) {
406+
this.subscriptions.delete(data.requestId);
407+
subscription.subscribed = false;
408+
subscription.unsubscribePromise.resolve();
409+
}
405410
break;
411+
}
406412
default: {
407413
// create, update, enter, leave, delete cases
408414
if (!subscription) {

src/LiveQuerySubscription.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ class Subscription extends EventEmitter {
9999
this.query = query;
100100
this.sessionToken = sessionToken;
101101
this.subscribePromise = resolvingPromise();
102+
this.unsubscribePromise = resolvingPromise();
102103
this.subscribed = false;
103104

104105
// adding listener so process does not crash
@@ -115,8 +116,8 @@ class Subscription extends EventEmitter {
115116
return CoreManager.getLiveQueryController()
116117
.getDefaultLiveQueryClient()
117118
.then(liveQueryClient => {
118-
liveQueryClient.unsubscribe(this);
119119
this.emit('close');
120+
return liveQueryClient.unsubscribe(this);
120121
});
121122
}
122123
}

src/__tests__/LiveQueryClient-test.js

Lines changed: 12 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -72,34 +72,6 @@ describe('LiveQueryClient', () => {
7272
liveQueryClient.open();
7373
});
7474

75-
it('can unsubscribe', async () => {
76-
const liveQueryClient = new LiveQueryClient({
77-
applicationId: 'applicationId',
78-
serverURL: 'ws://test',
79-
javascriptKey: 'javascriptKey',
80-
masterKey: 'masterKey',
81-
sessionToken: 'sessionToken',
82-
});
83-
liveQueryClient.socket = {
84-
send: jest.fn(),
85-
};
86-
const subscription = {
87-
id: 1,
88-
};
89-
liveQueryClient.subscriptions.set(1, subscription);
90-
91-
liveQueryClient.unsubscribe(subscription);
92-
liveQueryClient.connectPromise.resolve();
93-
expect(liveQueryClient.subscriptions.size).toBe(0);
94-
await liveQueryClient.connectPromise;
95-
const messageStr = liveQueryClient.socket.send.mock.calls[0][0];
96-
const message = JSON.parse(messageStr);
97-
expect(message).toEqual({
98-
op: 'unsubscribe',
99-
requestId: 1,
100-
});
101-
});
102-
10375
it('can handle open / close states', () => {
10476
const liveQueryClient = new LiveQueryClient({
10577
applicationId: 'applicationId',
@@ -284,6 +256,7 @@ describe('LiveQueryClient', () => {
284256
});
285257
const subscription = new events.EventEmitter();
286258
subscription.subscribePromise = resolvingPromise();
259+
subscription.unsubscribePromise = resolvingPromise();
287260

288261
liveQueryClient.subscriptions.set(1, subscription);
289262
const data = {
@@ -295,7 +268,7 @@ describe('LiveQueryClient', () => {
295268
data: JSON.stringify(data),
296269
};
297270
liveQueryClient._handleWebSocketMessage(event);
298-
expect(liveQueryClient.subscriptions.size).toBe(1);
271+
expect(liveQueryClient.subscriptions.size).toBe(0);
299272
});
300273

301274
it('can handle WebSocket error response message', async () => {
@@ -871,19 +844,28 @@ describe('LiveQueryClient', () => {
871844
};
872845
const subscription = {
873846
id: 1,
847+
unsubscribePromise: resolvingPromise(),
874848
};
875849
liveQueryClient.subscriptions.set(1, subscription);
876850

877851
liveQueryClient.unsubscribe(subscription);
878852
liveQueryClient.connectPromise.resolve();
879-
expect(liveQueryClient.subscriptions.size).toBe(0);
853+
expect(liveQueryClient.subscriptions.size).toBe(1);
880854
await liveQueryClient.connectPromise;
881855
const messageStr = liveQueryClient.socket.send.mock.calls[0][0];
882856
const message = JSON.parse(messageStr);
883857
expect(message).toEqual({
884858
op: 'unsubscribe',
885859
requestId: 1,
886860
});
861+
const event = {
862+
data: JSON.stringify({
863+
op: 'unsubscribed',
864+
requestId: 1,
865+
}),
866+
};
867+
liveQueryClient._handleWebSocketMessage(event);
868+
expect(liveQueryClient.subscriptions.size).toBe(0);
887869
});
888870

889871
it('can unsubscribe without subscription', async () => {

src/__tests__/ParseLiveQuery-test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ describe('ParseLiveQuery', () => {
227227
});
228228
});
229229

230-
it('should not throw on usubscribe', done => {
230+
it('should not throw on usubscribe', () => {
231231
CoreManager.set('UserController', {
232232
currentUserAsync() {
233233
return Promise.resolve({
@@ -240,7 +240,7 @@ describe('ParseLiveQuery', () => {
240240
const query = new ParseQuery('ObjectType');
241241
query.equalTo('test', 'value');
242242
const subscription = new LiveQuerySubscription('0', query, 'token');
243-
subscription.unsubscribe().then(done).catch(done.fail);
243+
subscription.unsubscribe();
244244
});
245245

246246
it('can handle LiveQuery open event', async () => {

0 commit comments

Comments
 (0)