2022-03-01 19:14:15 -08:00
|
|
|
const WebSocket = require('ws')
|
|
|
|
|
const timestamp = () => new Date().toISOString().replace('T', ' ').substr(0, 19)
|
2022-02-28 20:59:49 -08:00
|
|
|
|
|
|
|
|
function WebSocketClient(url) {
|
2022-03-01 19:14:15 -08:00
|
|
|
let client
|
|
|
|
|
let timeout
|
|
|
|
|
let connecting = false
|
|
|
|
|
let backoff = 250
|
2022-02-28 20:59:49 -08:00
|
|
|
const init = () => {
|
2022-03-01 19:14:15 -08:00
|
|
|
console.error(`::SimplyWS:: [${timestamp()}] connecting`)
|
|
|
|
|
connecting = false
|
2022-02-28 20:59:49 -08:00
|
|
|
if (client !== undefined) {
|
2022-03-01 19:14:15 -08:00
|
|
|
client.removeAllListeners()
|
2022-02-28 20:59:49 -08:00
|
|
|
}
|
2022-03-01 19:14:15 -08:00
|
|
|
client = new WebSocket(url)
|
2022-02-28 20:59:49 -08:00
|
|
|
const heartbeat = () => {
|
|
|
|
|
if (timeout !== undefined) {
|
2022-03-01 19:14:15 -08:00
|
|
|
clearTimeout(timeout)
|
|
|
|
|
timeout = undefined
|
2022-02-28 20:59:49 -08:00
|
|
|
}
|
2022-03-01 19:14:15 -08:00
|
|
|
timeout = setTimeout(() => client.terminate(), 350000)
|
|
|
|
|
}
|
2022-02-28 20:59:49 -08:00
|
|
|
client.on('ping', () => {
|
2022-03-01 19:14:15 -08:00
|
|
|
console.log(`::SimplyWS:: [${timestamp()}] pinged`)
|
|
|
|
|
heartbeat()
|
|
|
|
|
})
|
2022-02-28 20:59:49 -08:00
|
|
|
client.on('open', (e) => {
|
|
|
|
|
if (typeof this.onOpen === 'function') {
|
2022-03-01 19:14:15 -08:00
|
|
|
this.onOpen()
|
2022-02-28 20:59:49 -08:00
|
|
|
} else {
|
2022-03-01 19:14:15 -08:00
|
|
|
console.log(`::SimplyWS:: [${timestamp()}] opened`)
|
|
|
|
|
console.log(e)
|
2022-02-28 20:59:49 -08:00
|
|
|
}
|
2022-03-01 19:14:15 -08:00
|
|
|
heartbeat()
|
|
|
|
|
})
|
2022-02-28 20:59:49 -08:00
|
|
|
client.on('message', (e) => {
|
|
|
|
|
if (typeof this.onMessage === 'function') {
|
2022-03-01 19:14:15 -08:00
|
|
|
this.onMessage(e)
|
2022-02-28 20:59:49 -08:00
|
|
|
} else {
|
2022-03-01 19:14:15 -08:00
|
|
|
console.log(`::SimplyWS:: [${timestamp()}] messaged`)
|
2022-02-28 20:59:49 -08:00
|
|
|
}
|
2022-03-01 19:14:15 -08:00
|
|
|
heartbeat()
|
|
|
|
|
})
|
2022-02-28 20:59:49 -08:00
|
|
|
client.on('close', (e) => {
|
|
|
|
|
if (e.code !== 1000) {
|
|
|
|
|
if (connecting === false) { // abnormal closure
|
2022-03-01 19:14:15 -08:00
|
|
|
backoff = backoff === 8000 ? 250 : backoff * 2
|
|
|
|
|
setTimeout(() => init(), backoff)
|
|
|
|
|
connecting = true
|
2022-02-28 20:59:49 -08:00
|
|
|
}
|
|
|
|
|
} else if (typeof this.onClose === 'function') {
|
2022-03-01 19:14:15 -08:00
|
|
|
this.onClose()
|
2022-02-28 20:59:49 -08:00
|
|
|
} else {
|
2022-03-01 19:14:15 -08:00
|
|
|
console.error(`::SimplyWS:: [${timestamp()}] closed`)
|
|
|
|
|
console.error(e)
|
2022-02-28 20:59:49 -08:00
|
|
|
}
|
2022-03-01 19:14:15 -08:00
|
|
|
})
|
2022-02-28 20:59:49 -08:00
|
|
|
client.on('error', (e) => {
|
|
|
|
|
if (e.code === 'ECONREFUSED') {
|
|
|
|
|
if (connecting === false) { // abnormal closure
|
2022-03-01 19:14:15 -08:00
|
|
|
backoff = backoff === 8000 ? 250 : backoff * 2
|
|
|
|
|
setTimeout(() => init(), backoff)
|
|
|
|
|
connecting = true
|
2022-02-28 20:59:49 -08:00
|
|
|
}
|
|
|
|
|
} else if (typeof this.onError === 'function') {
|
2022-03-01 19:14:15 -08:00
|
|
|
this.onError(e)
|
2022-02-28 20:59:49 -08:00
|
|
|
} else {
|
2022-03-01 19:14:15 -08:00
|
|
|
console.error(`::SimplyWS:: [${timestamp()}] errored`)
|
|
|
|
|
console.error(e)
|
2022-02-28 20:59:49 -08:00
|
|
|
}
|
2022-03-01 19:14:15 -08:00
|
|
|
})
|
|
|
|
|
this.send = client.send.bind(client)
|
|
|
|
|
}
|
|
|
|
|
init()
|
2022-02-28 20:59:49 -08:00
|
|
|
}
|
|
|
|
|
|
2022-03-01 19:14:15 -08:00
|
|
|
module.exports = WebSocketClient
|