From f0d5299fb16be4fdc0386a345de2a18d20a6ea03 Mon Sep 17 00:00:00 2001 From: Stephen Bussey Date: Sun, 4 Nov 2018 14:55:04 -0500 Subject: [PATCH] Allow channels to immediately reconnect when the socket does The timer state must be known in order to know if the channel was attempting to rejoin or not. It is not correct to start a channel rejoin timer if it was not previously running. --- assets/js/phoenix.js | 27 +++++++++++++++++++++++++-- assets/test/socket_test.js | 19 +++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/assets/js/phoenix.js b/assets/js/phoenix.js index 9f56a052d2..78149265a9 100644 --- a/assets/js/phoenix.js +++ b/assets/js/phoenix.js @@ -838,6 +838,7 @@ export class Socket { this.flushSendBuffer() this.reconnectTimer.reset() this.resetHeartbeat() + this.resetChannelTimers() this.stateChangeCallbacks.open.forEach( callback => callback() ) } @@ -986,6 +987,15 @@ export class Socket { } }) } + + /** + * @private + */ + resetChannelTimers() { + this.channels.forEach(channel => { + channel.rejoinTimer.restart() + }) + } } @@ -1346,18 +1356,31 @@ class Timer { reset(){ this.tries = 0 - clearTimeout(this.timer) + this.clearTimer() + } + + restart(){ + const processing = this.timer !== null + this.reset() + if (processing){ + this.scheduleTimeout() + } } /** * Cancels any previous scheduleTimeout and schedules callback */ scheduleTimeout(){ - clearTimeout(this.timer) + this.clearTimer() this.timer = setTimeout(() => { this.tries = this.tries + 1 this.callback() }, this.timerCalc(this.tries + 1)) } + + clearTimer() { + clearTimeout(this.timer) + this.timer = null + } } diff --git a/assets/test/socket_test.js b/assets/test/socket_test.js index 4790db7759..fe38507b5d 100644 --- a/assets/test/socket_test.js +++ b/assets/test/socket_test.js @@ -605,6 +605,25 @@ describe("onConnOpen", () => { assert.ok(spy.calledOnce) }) + it("resets all channel timers and schedules a timeout if the timer was in progress", () => { + const channel = socket.channel("topic", {}) + const channel2 = socket.channel("topic2", {}) + + channel.rejoinTimer.tries = 1 + channel2.rejoinTimer.tries = 2 + channel2.rejoinTimer.scheduleTimeout() + + assert.equal(channel.rejoinTimer.timer, null) + assert.notEqual(channel2.rejoinTimer.timer, null) + + socket.onConnOpen() + + assert.equal(channel.rejoinTimer.tries, 0) + assert.equal(channel2.rejoinTimer.tries, 0) + assert.equal(channel.rejoinTimer.timer, null) + assert.notEqual(channel2.rejoinTimer.timer, null) + }) + it("triggers onOpen callback", () => { const spy = sinon.spy()