diff options
Diffstat (limited to 'actioncable/app/javascript/action_cable/connection_monitor.js')
-rw-r--r-- | actioncable/app/javascript/action_cable/connection_monitor.js | 184 |
1 files changed, 92 insertions, 92 deletions
diff --git a/actioncable/app/javascript/action_cable/connection_monitor.js b/actioncable/app/javascript/action_cable/connection_monitor.js index 4d2db5b4ae..8d6ac1f682 100644 --- a/actioncable/app/javascript/action_cable/connection_monitor.js +++ b/actioncable/app/javascript/action_cable/connection_monitor.js @@ -1,125 +1,125 @@ +import ActionCable from "./index" + // Responsible for ensuring the cable connection is in good health by validating the heartbeat pings sent from the server, and attempting // revival reconnections if things go astray. Internal class, not intended for direct user manipulation. -ActionCable.ConnectionMonitor = (function() { - const now = () => new Date().getTime() - const secondsSince = time => (now() - time) / 1000 +const now = () => new Date().getTime() - const clamp = (number, min, max) => Math.max(min, Math.min(max, number)) +const secondsSince = time => (now() - time) / 1000 - class ConnectionMonitor { - constructor(connection) { - this.visibilityDidChange = this.visibilityDidChange.bind(this) - this.connection = connection - this.reconnectAttempts = 0 - } +const clamp = (number, min, max) => Math.max(min, Math.min(max, number)) - start() { - if (!this.isRunning()) { - this.startedAt = now() - delete this.stoppedAt - this.startPolling() - document.addEventListener("visibilitychange", this.visibilityDidChange) - ActionCable.log(`ConnectionMonitor started. pollInterval = ${this.getPollInterval()} ms`) - } - } +class ConnectionMonitor { + constructor(connection) { + this.visibilityDidChange = this.visibilityDidChange.bind(this) + this.connection = connection + this.reconnectAttempts = 0 + } - stop() { - if (this.isRunning()) { - this.stoppedAt = now() - this.stopPolling() - document.removeEventListener("visibilitychange", this.visibilityDidChange) - ActionCable.log("ConnectionMonitor stopped") - } + start() { + if (!this.isRunning()) { + this.startedAt = now() + delete this.stoppedAt + this.startPolling() + document.addEventListener("visibilitychange", this.visibilityDidChange) + ActionCable.log(`ConnectionMonitor started. pollInterval = ${this.getPollInterval()} ms`) } + } - isRunning() { - return this.startedAt && !this.stoppedAt + stop() { + if (this.isRunning()) { + this.stoppedAt = now() + this.stopPolling() + document.removeEventListener("visibilitychange", this.visibilityDidChange) + ActionCable.log("ConnectionMonitor stopped") } + } - recordPing() { - this.pingedAt = now() - } + isRunning() { + return this.startedAt && !this.stoppedAt + } - recordConnect() { - this.reconnectAttempts = 0 - this.recordPing() - delete this.disconnectedAt - ActionCable.log("ConnectionMonitor recorded connect") - } + recordPing() { + this.pingedAt = now() + } - recordDisconnect() { - this.disconnectedAt = now() - ActionCable.log("ConnectionMonitor recorded disconnect") - } + recordConnect() { + this.reconnectAttempts = 0 + this.recordPing() + delete this.disconnectedAt + ActionCable.log("ConnectionMonitor recorded connect") + } - // Private + recordDisconnect() { + this.disconnectedAt = now() + ActionCable.log("ConnectionMonitor recorded disconnect") + } - startPolling() { - this.stopPolling() - this.poll() - } + // Private - stopPolling() { - clearTimeout(this.pollTimeout) - } + startPolling() { + this.stopPolling() + this.poll() + } - poll() { - this.pollTimeout = setTimeout(() => { - this.reconnectIfStale() - this.poll() - } - , this.getPollInterval()) - } + stopPolling() { + clearTimeout(this.pollTimeout) + } - getPollInterval() { - const {min, max} = this.constructor.pollInterval - const interval = 5 * Math.log(this.reconnectAttempts + 1) - return Math.round(clamp(interval, min, max) * 1000) + poll() { + this.pollTimeout = setTimeout(() => { + this.reconnectIfStale() + this.poll() } + , this.getPollInterval()) + } - reconnectIfStale() { - if (this.connectionIsStale()) { - ActionCable.log(`ConnectionMonitor detected stale connection. reconnectAttempts = ${this.reconnectAttempts}, pollInterval = ${this.getPollInterval()} ms, time disconnected = ${secondsSince(this.disconnectedAt)} s, stale threshold = ${this.constructor.staleThreshold} s`) - this.reconnectAttempts++ - if (this.disconnectedRecently()) { - ActionCable.log("ConnectionMonitor skipping reopening recent disconnect") - } else { - ActionCable.log("ConnectionMonitor reopening") - this.connection.reopen() - } + getPollInterval() { + const {min, max} = this.constructor.pollInterval + const interval = 5 * Math.log(this.reconnectAttempts + 1) + return Math.round(clamp(interval, min, max) * 1000) + } + + reconnectIfStale() { + if (this.connectionIsStale()) { + ActionCable.log(`ConnectionMonitor detected stale connection. reconnectAttempts = ${this.reconnectAttempts}, pollInterval = ${this.getPollInterval()} ms, time disconnected = ${secondsSince(this.disconnectedAt)} s, stale threshold = ${this.constructor.staleThreshold} s`) + this.reconnectAttempts++ + if (this.disconnectedRecently()) { + ActionCable.log("ConnectionMonitor skipping reopening recent disconnect") + } else { + ActionCable.log("ConnectionMonitor reopening") + this.connection.reopen() } } + } - connectionIsStale() { - return secondsSince(this.pingedAt ? this.pingedAt : this.startedAt) > this.constructor.staleThreshold - } + connectionIsStale() { + return secondsSince(this.pingedAt ? this.pingedAt : this.startedAt) > this.constructor.staleThreshold + } - disconnectedRecently() { - return this.disconnectedAt && (secondsSince(this.disconnectedAt) < this.constructor.staleThreshold) - } + disconnectedRecently() { + return this.disconnectedAt && (secondsSince(this.disconnectedAt) < this.constructor.staleThreshold) + } - visibilityDidChange() { - if (document.visibilityState === "visible") { - setTimeout(() => { - if (this.connectionIsStale() || !this.connection.isOpen()) { - ActionCable.log(`ConnectionMonitor reopening stale connection on visibilitychange. visbilityState = ${document.visibilityState}`) - this.connection.reopen() - } + visibilityDidChange() { + if (document.visibilityState === "visible") { + setTimeout(() => { + if (this.connectionIsStale() || !this.connection.isOpen()) { + ActionCable.log(`ConnectionMonitor reopening stale connection on visibilitychange. visbilityState = ${document.visibilityState}`) + this.connection.reopen() } - , 200) } + , 200) } - } - ConnectionMonitor.pollInterval = { - min: 3, - max: 30 - } +} - ConnectionMonitor.staleThreshold = 6 // Server::Connections::BEAT_INTERVAL * 2 (missed two pings) +ConnectionMonitor.pollInterval = { + min: 3, + max: 30 +} - return ConnectionMonitor +ConnectionMonitor.staleThreshold = 6 // Server::Connections::BEAT_INTERVAL * 2 (missed two pings) -})() +export default ConnectionMonitor |