From ab4cddfedde67aa3c287b10e8a81c300ffcc808f Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Fri, 26 Jan 2024 20:55:14 +0100 Subject: [PATCH] Force a reconnect in case a heartbeat is missing (#569) There seems to be cases where the connection is lost without the client being able to reconnect (e.g. active subscription -> system hibernation -> waking up system => not receiving any messages anymore). --- src/lib/requests/client/GraphQLClient.ts | 48 +++++++++++------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/src/lib/requests/client/GraphQLClient.ts b/src/lib/requests/client/GraphQLClient.ts index 1a60a56b..27aee8fd 100644 --- a/src/lib/requests/client/GraphQLClient.ts +++ b/src/lib/requests/client/GraphQLClient.ts @@ -157,37 +157,33 @@ export class GraphQLClient extends BaseClient< } protected createClient() { + const heartbeatInterval = 1000 * 20; + this.wsClient = createClient({ url: () => this.getBaseUrl().replace(/http(|s)/g, 'ws'), - keepAlive: 20000, + keepAlive: heartbeatInterval, retryAttempts: Infinity, - retryWait: async (retries) => { - const getDelayInMS = () => { - if (retries < 10) { - return 1000 * 5; - } - - if (retries < 50) { - return 1000 * 10; - } - - if (retries < 500) { - return 1000 * 30; - } - - if (retries < 1000) { - return 1000 * 60; - } - - return 1000 * 60 * 5; - }; - - await new Promise((resolve) => { - setTimeout(resolve, getDelayInMS()); - }); - }, }); + let lastHeartbeat: number = 0; + this.wsClient.on('connected', () => { + lastHeartbeat = Date.now(); + }); + this.wsClient.on('pong', () => { + lastHeartbeat = Date.now(); + }); + + const checkHeartbeatInterval = heartbeatInterval + 1000 * 10; + // for some reason "this.wsClient" is undefined in the "setInterval" callback + const { wsClient } = this; + setInterval(() => { + const isHeartbeatMissing = Date.now() - lastHeartbeat > checkHeartbeatInterval * 1.1; + if (isHeartbeatMissing) { + // force a reconnect + wsClient.terminate(); + } + }, checkHeartbeatInterval); + this.client = new ApolloClient({ cache: new InMemoryCache({ // for whatever reason there is some weird TypeError complaining that