diff --git a/spec/ParseLiveQuery.spec.js b/spec/ParseLiveQuery.spec.js index 496f9fb922..8192597aa0 100644 --- a/spec/ParseLiveQuery.spec.js +++ b/spec/ParseLiveQuery.spec.js @@ -231,7 +231,6 @@ describe('ParseLiveQuery', function () { object.set({ foo: 'bar' }); await object.save(); }); - it('can handle afterEvent throw', async done => { await reconfigureServer({ liveQuery: { @@ -245,6 +244,37 @@ describe('ParseLiveQuery', function () { const object = new TestObject(); await object.save(); + Parse.Cloud.afterLiveQueryEvent('TestObject', () => { + throw 'Throw error from LQ afterEvent.'; + }); + + const query = new Parse.Query(TestObject); + query.equalTo('objectId', object.id); + const subscription = await query.subscribe(); + subscription.on('update', () => { + fail('update should not have been called.'); + }); + subscription.on('error', e => { + expect(e).toBe('Throw error from LQ afterEvent.'); + done(); + }); + object.set({ foo: 'bar' }); + await object.save(); + }); + + it('can handle afterEvent sendEvent to false', async done => { + await reconfigureServer({ + liveQuery: { + classNames: ['TestObject'], + }, + startLiveQueryServer: true, + verbose: false, + silent: true, + }); + + const object = new TestObject(); + await object.save(); + Parse.Cloud.afterLiveQueryEvent('TestObject', req => { const current = req.object; const original = req.original; @@ -254,7 +284,7 @@ describe('ParseLiveQuery', function () { }, 2000); if (current.get('foo') != original.get('foo')) { - throw "Don't pass an update trigger, or message"; + req.sendEvent = false; } }); diff --git a/src/LiveQuery/ParseLiveQueryServer.js b/src/LiveQuery/ParseLiveQueryServer.js index e535480a71..f0d0db19a4 100644 --- a/src/LiveQuery/ParseLiveQueryServer.js +++ b/src/LiveQuery/ParseLiveQueryServer.js @@ -182,11 +182,15 @@ class ParseLiveQueryServer { clients: this.clients.size, subscriptions: this.subscriptions.size, useMasterKey: client.hasMasterKey, - installationId: client.installationId + installationId: client.installationId, + sendEvent: true, }; return maybeRunAfterEventTrigger('afterEvent', className, res); }) .then(() => { + if (!res.sendEvent) { + return; + } if (res.object && typeof res.object.toJSON === 'function') { deletedParseObject = res.object.toJSON(); deletedParseObject.className = className; @@ -194,7 +198,17 @@ class ParseLiveQueryServer { client.pushDelete(requestId, deletedParseObject); }) .catch(error => { - logger.error('Matching ACL error : ', error); + Client.pushError( + client.parseWebSocket, + error.code || 141, + error.message || error, + false, + requestId + ); + logger.error( + `Failed running afterLiveQueryEvent on class ${className} for event ${res.event} with session ${res.sessionToken} with:\n Error: ` + + JSON.stringify(error) + ); }); } } @@ -297,7 +311,6 @@ class ParseLiveQueryServer { isCurrentMatched, subscription.hash ); - // Decide event type let type; if (isOriginalMatched && isCurrentMatched) { @@ -322,12 +335,16 @@ class ParseLiveQueryServer { clients: this.clients.size, subscriptions: this.subscriptions.size, useMasterKey: client.hasMasterKey, - installationId: client.installationId + installationId: client.installationId, + sendEvent: true, }; return maybeRunAfterEventTrigger('afterEvent', className, res); }) .then( () => { + if (!res.sendEvent) { + return; + } if (res.object && typeof res.object.toJSON === 'function') { currentParseObject = res.object.toJSON(); currentParseObject.className = @@ -349,7 +366,17 @@ class ParseLiveQueryServer { } }, error => { - logger.error('Matching ACL error : ', error); + Client.pushError( + client.parseWebSocket, + error.code || 141, + error.message || error, + false, + requestId + ); + logger.error( + `Failed running afterLiveQueryEvent on class ${className} for event ${res.event} with session ${res.sessionToken} with:\n Error: ` + + JSON.stringify(error) + ); } ); } @@ -658,7 +685,7 @@ class ParseLiveQueryServer { } catch (error) { Client.pushError( parseWebsocket, - error.code || 101, + error.code || 141, error.message || error, false ); @@ -776,7 +803,7 @@ class ParseLiveQueryServer { } catch (e) { Client.pushError( parseWebsocket, - e.code || 101, + e.code || 141, e.message || e, false, request.requestId diff --git a/src/cloud-code/Parse.Cloud.js b/src/cloud-code/Parse.Cloud.js index c3f0536c2b..01d1569bc1 100644 --- a/src/cloud-code/Parse.Cloud.js +++ b/src/cloud-code/Parse.Cloud.js @@ -600,6 +600,7 @@ module.exports = ParseCloud; * @property {Parse.Object} original If set, the object, as currently stored. * @property {Integer} clients The number of clients connected. * @property {Integer} subscriptions The number of subscriptions connected. + * @property {Boolean} sendEvent If the LiveQuery event should be sent to the client. Set to false to prevent LiveQuery from pushing to the client. */ /**