Skip to content

Commit 96d7174

Browse files
authored
fix: Parse.Query.subscribe() does not return a rejected promise on error in Cloud Code Triggers beforeConnect or beforeSubscribe (#1490)
BREAKING CHANGE: Calling `Parse.Query.subscribe()` will now return a rejected promise if an error is thrown in Cloud Code Triggers `beforeConnect` or `beforeSubscribe`; in previous releases a resolved promise was returned, even if subscribing failed and it was necessary to create an `error.on` listener to handle these errors (#1490)
1 parent 744b721 commit 96d7174

File tree

2 files changed

+68
-5
lines changed

2 files changed

+68
-5
lines changed

integration/test/ParseLiveQueryTest.js

+52
Original file line numberDiff line numberDiff line change
@@ -256,4 +256,56 @@ describe('Parse LiveQuery', () => {
256256
object.set({ foo: 'bar' });
257257
await object.save();
258258
});
259+
260+
it('live query can handle beforeConnect and beforeSubscribe errors', async () => {
261+
await reconfigureServer({
262+
cloud({ Cloud }) {
263+
Cloud.beforeSubscribe('TestError', () => {
264+
throw 'not allowed to subscribe';
265+
});
266+
},
267+
});
268+
const client = new Parse.LiveQueryClient({
269+
applicationId: 'integration',
270+
serverURL: 'ws://localhost:1337',
271+
javascriptKey: null,
272+
masterKey: null,
273+
sessionToken: null,
274+
installationId: null,
275+
});
276+
client.open();
277+
const query = new Parse.Query('TestError');
278+
const subscription = client.subscribe(query);
279+
await expectAsync(subscription.subscribePromise).toBeRejectedWith(
280+
new Parse.Error(141, 'not allowed to subscribe')
281+
);
282+
client.close();
283+
});
284+
285+
it('connectPromise does throw', async () => {
286+
await reconfigureServer({
287+
cloud({ Cloud }) {
288+
Cloud.beforeConnect((params) => {
289+
if (params.sessionToken === 'testToken') {
290+
throw 'not allowed to connect';
291+
}
292+
});
293+
},
294+
});
295+
const client = new Parse.LiveQueryClient({
296+
applicationId: 'integration',
297+
serverURL: 'ws://localhost:1337',
298+
javascriptKey: null,
299+
masterKey: null,
300+
sessionToken: 'testToken',
301+
installationId: null,
302+
});
303+
client.open();
304+
const query = new Parse.Query('TestError');
305+
const subscription = client.subscribe(query);
306+
await expectAsync(subscription.subscribePromise).toBeRejectedWith(
307+
new Parse.Error(141, 'not allowed to connect')
308+
);
309+
client.close();
310+
});
259311
});

src/LiveQueryClient.js

+16-5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import EventEmitter from './EventEmitter';
1414
import ParseObject from './ParseObject';
1515
import LiveQuerySubscription from './LiveQuerySubscription';
1616
import { resolvingPromise } from './promiseUtils';
17+
import ParseError from './ParseError';
1718

1819
// The LiveQuery client inner state
1920
const CLIENT_STATE = {
@@ -217,9 +218,13 @@ class LiveQueryClient extends EventEmitter {
217218
const subscription = new LiveQuerySubscription(this.requestId, query, sessionToken);
218219
this.subscriptions.set(this.requestId, subscription);
219220
this.requestId += 1;
220-
this.connectPromise.then(() => {
221-
this.socket.send(JSON.stringify(subscribeRequest));
222-
});
221+
this.connectPromise
222+
.then(() => {
223+
this.socket.send(JSON.stringify(subscribeRequest));
224+
})
225+
.catch(error => {
226+
subscription.subscribePromise.reject(error);
227+
});
223228

224229
return subscription;
225230
}
@@ -382,10 +387,15 @@ class LiveQueryClient extends EventEmitter {
382387
setTimeout(() => subscription.emit(SUBSCRIPTION_EMMITER_TYPES.OPEN, response), 200);
383388
}
384389
break;
385-
case OP_EVENTS.ERROR:
390+
case OP_EVENTS.ERROR: {
391+
const parseError = new ParseError(data.code, data.error);
392+
if (!this.id) {
393+
this.connectPromise.reject(parseError);
394+
this.state = CLIENT_STATE.DISCONNECTED;
395+
}
386396
if (data.requestId) {
387397
if (subscription) {
388-
subscription.subscribePromise.resolve();
398+
subscription.subscribePromise.reject(parseError);
389399
setTimeout(() => subscription.emit(SUBSCRIPTION_EMMITER_TYPES.ERROR, data.error), 200);
390400
}
391401
} else {
@@ -398,6 +408,7 @@ class LiveQueryClient extends EventEmitter {
398408
this._handleReconnect();
399409
}
400410
break;
411+
}
401412
case OP_EVENTS.UNSUBSCRIBED:
402413
// We have already deleted subscription in unsubscribe(), do nothing here
403414
break;

0 commit comments

Comments
 (0)