From be11cbc30aded4b10aea5314aebf8f1e1eb9cacd Mon Sep 17 00:00:00 2001 From: Diamond Lewis Date: Sun, 23 Jun 2024 14:52:12 -0500 Subject: [PATCH 1/3] fix: Add `keys` and `watch` to `LiveQueryClient.resubscribe` --- integration/test/ParseLiveQueryTest.js | 36 ++++++++++++++++++++++++++ src/LiveQueryClient.ts | 13 +++++----- src/__tests__/LiveQueryClient-test.js | 9 +++++++ 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/integration/test/ParseLiveQueryTest.js b/integration/test/ParseLiveQueryTest.js index f7231b551..f0f1148b6 100644 --- a/integration/test/ParseLiveQueryTest.js +++ b/integration/test/ParseLiveQueryTest.js @@ -90,6 +90,42 @@ describe('Parse LiveQuery', () => { await promise; }); + it('can resubscribe', async () => { + const client = new Parse.LiveQueryClient({ + applicationId: 'integration', + serverURL: 'ws://localhost:1337', + javascriptKey: null, + masterKey: null, + sessionToken: null, + }); + client.open(); + const resubscribeSpy = spyOn(client, 'resubscribe').and.callThrough(); + const consoleSpy = spyOn(console, 'error').and.callFake(() => {}); + const subscribeRequest = { + op: 'subscribe', + requestId: 1, + query: { + className: 'TestObject', + where: { objectId: 'HEXkuHFm0D' }, + keys: ['foo', 'objectId'], + watch: undefined, + unknownField: 'throws Additional properties not allowed error', + }, + sessionToken: undefined, + }; + await client.connectPromise; + client.socket.send(JSON.stringify(subscribeRequest)); + await sleep(1000); + expect(resubscribeSpy).toHaveBeenCalled(); + expect(consoleSpy).toHaveBeenCalledWith( + 'LiveQuery reconnecting with error:', + 'Additional properties not allowed', + 'code:', + 1 + ); + await client.close(); + }); + it('can subscribe to multiple queries', async () => { const objectA = new TestObject(); const objectB = new TestObject(); diff --git a/src/LiveQueryClient.ts b/src/LiveQueryClient.ts index b497fb4e9..bbf4ae890 100644 --- a/src/LiveQueryClient.ts +++ b/src/LiveQueryClient.ts @@ -55,6 +55,7 @@ const SUBSCRIPTION_EMMITER_TYPES = { DELETE: 'delete', }; +// Exponentially-growing random delay const generateInterval = k => { return Math.random() * Math.min(30, Math.pow(2, k) - 1) * 1000; }; @@ -291,7 +292,8 @@ class LiveQueryClient { const query = subscription.query; const queryJSON = query.toJSON(); const where = queryJSON.where; - const fields = queryJSON.keys ? queryJSON.keys.split(',') : undefined; + const keys = queryJSON.keys?.split(','); + const watch = queryJSON.watch?.split(','); const className = query.className; const sessionToken = subscription.sessionToken; const subscribeRequest = { @@ -300,7 +302,8 @@ class LiveQueryClient { query: { className, where, - fields, + keys, + watch, }, sessionToken: undefined as string | undefined, }; @@ -347,7 +350,6 @@ class LiveQueryClient { } _handleWebSocketOpen() { - this.attempts = 1; const connectRequest = { op: OP_TYPES.CONNECT, applicationId: this.applicationId, @@ -387,6 +389,7 @@ class LiveQueryClient { break; case OP_EVENTS.SUBSCRIBED: if (subscription) { + this.attempts = 1; subscription.subscribed = true; subscription.subscribePromise.resolve(); setTimeout(() => subscription.emit(SUBSCRIPTION_EMMITER_TYPES.OPEN, response), 200); @@ -410,6 +413,7 @@ class LiveQueryClient { this.additionalProperties = false; } if (data.reconnect) { + console.error('LiveQuery reconnecting with error:', data.error, 'code:', data.code); this._handleReconnect(); } break; @@ -485,7 +489,6 @@ class LiveQueryClient { if (this.state === CLIENT_STATE.DISCONNECTED) { return; } - this.state = CLIENT_STATE.RECONNECTING; const time = generateInterval(this.attempts); @@ -493,11 +496,9 @@ class LiveQueryClient { // we're unable to distinguish different between close/error when we're unable to reconnect therefore // we try to reconnect in both cases // server side ws and browser WebSocket behave differently in when close/error get triggered - if (this.reconnectHandle) { clearTimeout(this.reconnectHandle); } - this.reconnectHandle = setTimeout( (() => { this.attempts++; diff --git a/src/__tests__/LiveQueryClient-test.js b/src/__tests__/LiveQueryClient-test.js index 4588cc1cc..cccdc71a6 100644 --- a/src/__tests__/LiveQueryClient-test.js +++ b/src/__tests__/LiveQueryClient-test.js @@ -748,6 +748,7 @@ describe('LiveQueryClient', () => { expect(error).toEqual(data.error); }); const spy = jest.spyOn(liveQueryClient, '_handleReconnect'); + jest.spyOn(console, 'error').mockImplementationOnce(() => {}); try { liveQueryClient._handleWebSocketMessage(event); await liveQueryClient.connectPromise; @@ -944,6 +945,8 @@ describe('LiveQueryClient', () => { }; const query = new ParseQuery('Test'); query.equalTo('key', 'value'); + query.select(['key']); + query.watch(['key']); liveQueryClient.subscribe(query); liveQueryClient.connectPromise.resolve(); @@ -961,6 +964,8 @@ describe('LiveQueryClient', () => { where: { key: 'value', }, + keys: ['key'], + watch: ['key'], }, }); }); @@ -978,6 +983,8 @@ describe('LiveQueryClient', () => { }; const query = new ParseQuery('Test'); query.equalTo('key', 'value'); + query.select(['key']); + query.watch(['key']); liveQueryClient.subscribe(query, 'mySessionToken'); liveQueryClient.connectPromise.resolve(); @@ -996,6 +1003,8 @@ describe('LiveQueryClient', () => { where: { key: 'value', }, + keys: ['key'], + watch: ['key'], }, }); }); From c8ed1b89d9ff288515aacfecccc409177a38820a Mon Sep 17 00:00:00 2001 From: Diamond Lewis Date: Sun, 23 Jun 2024 15:09:33 -0500 Subject: [PATCH 2/3] remove console log --- integration/test/ParseLiveQueryTest.js | 7 ------- src/LiveQueryClient.ts | 1 - src/__tests__/LiveQueryClient-test.js | 1 - 3 files changed, 9 deletions(-) diff --git a/integration/test/ParseLiveQueryTest.js b/integration/test/ParseLiveQueryTest.js index f0f1148b6..b81441579 100644 --- a/integration/test/ParseLiveQueryTest.js +++ b/integration/test/ParseLiveQueryTest.js @@ -100,7 +100,6 @@ describe('Parse LiveQuery', () => { }); client.open(); const resubscribeSpy = spyOn(client, 'resubscribe').and.callThrough(); - const consoleSpy = spyOn(console, 'error').and.callFake(() => {}); const subscribeRequest = { op: 'subscribe', requestId: 1, @@ -117,12 +116,6 @@ describe('Parse LiveQuery', () => { client.socket.send(JSON.stringify(subscribeRequest)); await sleep(1000); expect(resubscribeSpy).toHaveBeenCalled(); - expect(consoleSpy).toHaveBeenCalledWith( - 'LiveQuery reconnecting with error:', - 'Additional properties not allowed', - 'code:', - 1 - ); await client.close(); }); diff --git a/src/LiveQueryClient.ts b/src/LiveQueryClient.ts index bbf4ae890..512d5ac6e 100644 --- a/src/LiveQueryClient.ts +++ b/src/LiveQueryClient.ts @@ -413,7 +413,6 @@ class LiveQueryClient { this.additionalProperties = false; } if (data.reconnect) { - console.error('LiveQuery reconnecting with error:', data.error, 'code:', data.code); this._handleReconnect(); } break; diff --git a/src/__tests__/LiveQueryClient-test.js b/src/__tests__/LiveQueryClient-test.js index cccdc71a6..be9c90fae 100644 --- a/src/__tests__/LiveQueryClient-test.js +++ b/src/__tests__/LiveQueryClient-test.js @@ -748,7 +748,6 @@ describe('LiveQueryClient', () => { expect(error).toEqual(data.error); }); const spy = jest.spyOn(liveQueryClient, '_handleReconnect'); - jest.spyOn(console, 'error').mockImplementationOnce(() => {}); try { liveQueryClient._handleWebSocketMessage(event); await liveQueryClient.connectPromise; From 4b41a0646d4ee809b23bb9b27ca4c27a2423c513 Mon Sep 17 00:00:00 2001 From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com> Date: Mon, 24 Jun 2024 22:18:40 +0200 Subject: [PATCH 3/3] remove unused sleep --- integration/test/helper.js | 1 - 1 file changed, 1 deletion(-) diff --git a/integration/test/helper.js b/integration/test/helper.js index c60b173a0..acd11093a 100644 --- a/integration/test/helper.js +++ b/integration/test/helper.js @@ -5,7 +5,6 @@ jasmine.getEnv().addReporter(new SpecReporter()); const ParseServer = require('parse-server').default; const CustomAuth = require('./CustomAuth'); -const sleep = require('./sleep'); const { TestUtils } = require('parse-server'); const Parse = require('../../node'); const fs = require('fs');