From dbbf7c24e48166a221222bfaaee7e636aa3089b5 Mon Sep 17 00:00:00 2001 From: Gancho Radkov Date: Wed, 28 Aug 2024 14:18:10 +0300 Subject: [PATCH] fix: fixes bug where relayer could go into reconnection loop when multiple disconnect events are emitted at the same time --- packages/core/src/controllers/relayer.ts | 15 +++++++++++---- packages/core/test/relayer.spec.ts | 17 +++++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/packages/core/src/controllers/relayer.ts b/packages/core/src/controllers/relayer.ts index 5195314b3..d8b5980fe 100644 --- a/packages/core/src/controllers/relayer.ts +++ b/packages/core/src/controllers/relayer.ts @@ -93,6 +93,7 @@ export class Relayer extends IRelayer { * meaning if we don't receive a message in 30 seconds, the connection can be considered dead */ private heartBeatTimeout = toMiliseconds(THIRTY_SECONDS + ONE_SECOND); + private reconnectTimeout: NodeJS.Timeout | undefined; constructor(opts: RelayerOptions) { super(opts); @@ -295,9 +296,14 @@ export class Relayer extends IRelayer { this.provider.connect(), toMiliseconds(ONE_MINUTE), `Socket stalled when trying to connect to ${this.relayUrl}`, - ).catch((e) => { - reject(e); - }); + ) + .catch((e) => { + reject(e); + }) + .finally(() => { + clearTimeout(this.reconnectTimeout); + this.reconnectTimeout = undefined; + }); this.subscriber.start().catch((error) => { this.logger.error(error); this.onDisconnectHandler(); @@ -536,7 +542,8 @@ export class Relayer extends IRelayer { this.events.emit(RELAYER_EVENTS.disconnect); this.connectionAttemptInProgress = false; if (this.transportExplicitlyClosed) return; - setTimeout(async () => { + if (this.reconnectTimeout) return; + this.reconnectTimeout = setTimeout(async () => { await this.transportOpen().catch((error) => this.logger.error(error)); }, toMiliseconds(RELAYER_RECONNECT_TIMEOUT)); } diff --git a/packages/core/test/relayer.spec.ts b/packages/core/test/relayer.spec.ts index 2bceebc06..50a04fc5b 100644 --- a/packages/core/test/relayer.spec.ts +++ b/packages/core/test/relayer.spec.ts @@ -283,6 +283,23 @@ describe("Relayer", () => { // the identifier should be the same expect(relayer.core.crypto.randomSessionIdentifier).to.eq(randomSessionIdentifier); }); + it("should connect once regardless of the number of disconnect events", async () => { + const disconnectsToEmit = 10; + let disconnectsReceived = 0; + let connectReceived = 0; + relayer.on(RELAYER_EVENTS.connect, () => { + connectReceived++; + }); + relayer.on(RELAYER_EVENTS.disconnect, () => { + disconnectsReceived++; + }); + await Promise.all( + Array.from(Array(disconnectsToEmit).keys()).map(() => relayer.onDisconnectHandler()), + ); + await throttle(1000); + expect(connectReceived).to.eq(1); + expect(disconnectsReceived).to.eq(disconnectsToEmit); + }); it("should close transport 10 seconds after init if NOT active", async () => { relayer = new Relayer({