aboutsummaryrefslogtreecommitdiffstats
path: root/actioncable/app/javascript/action_cable/connection_monitor.js
diff options
context:
space:
mode:
Diffstat (limited to 'actioncable/app/javascript/action_cable/connection_monitor.js')
-rw-r--r--actioncable/app/javascript/action_cable/connection_monitor.js184
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