feat(frontend): increase reconnect timeout with every try

Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
Tilman Vatteroth 2023-04-23 21:41:46 +02:00
parent a554a48577
commit 3dea91523d

View file

@ -16,7 +16,8 @@ import WebSocket from 'isomorphic-ws'
import { useCallback, useEffect, useMemo, useRef } from 'react' import { useCallback, useEffect, useMemo, useRef } from 'react'
const logger = new Logger('websocket connection') const logger = new Logger('websocket connection')
const WEBSOCKET_RECONNECT_INTERVAL = 3000 const WEBSOCKET_RECONNECT_INTERVAL = 2000
const WEBSOCKET_RECONNECT_MAX_DURATION = 5000
/** /**
* Creates a {@link WebsocketTransporter websocket message transporter} that handles the realtime communication with the backend. * Creates a {@link WebsocketTransporter websocket message transporter} that handles the realtime communication with the backend.
@ -35,14 +36,18 @@ export const useRealtimeConnection = (): MessageTransporter => {
} }
}, []) }, [])
const reconnectCount = useRef(0)
const establishWebsocketConnection = useCallback(() => { const establishWebsocketConnection = useCallback(() => {
if (messageTransporter instanceof WebsocketTransporter && websocketUrl) { if (messageTransporter instanceof WebsocketTransporter && websocketUrl) {
logger.debug(`Connecting to ${websocketUrl.toString()}`) logger.debug(`Connecting to ${websocketUrl.toString()}`)
const socket = new WebSocket(websocketUrl) const socket = new WebSocket(websocketUrl)
socket.addEventListener('error', () => { socket.addEventListener('error', () => {
const timeout = WEBSOCKET_RECONNECT_INTERVAL + reconnectCount.current * 1000 + Math.random() * 1000
setTimeout(() => { setTimeout(() => {
reconnectCount.current += 1
establishWebsocketConnection() establishWebsocketConnection()
}, WEBSOCKET_RECONNECT_INTERVAL) }, Math.max(timeout, WEBSOCKET_RECONNECT_MAX_DURATION))
}) })
socket.addEventListener('open', () => { socket.addEventListener('open', () => {
messageTransporter.setWebsocket(socket) messageTransporter.setWebsocket(socket)
@ -51,39 +56,23 @@ export const useRealtimeConnection = (): MessageTransporter => {
}, [messageTransporter, websocketUrl]) }, [messageTransporter, websocketUrl])
const isConnected = useApplicationState((state) => state.realtimeStatus.isConnected) const isConnected = useApplicationState((state) => state.realtimeStatus.isConnected)
const firstConnect = useRef(true)
const reconnectTimeout = useRef<number | undefined>(undefined)
useEffect(() => { useEffect(() => {
if (isConnected) { if (isConnected || reconnectCount.current > 0) {
return return
} }
if (firstConnect.current) { establishWebsocketConnection()
establishWebsocketConnection() }, [establishWebsocketConnection, isConnected])
firstConnect.current = false
} else {
reconnectTimeout.current = window.setTimeout(() => {
establishWebsocketConnection()
}, WEBSOCKET_RECONNECT_INTERVAL)
}
}, [establishWebsocketConnection, isConnected, messageTransporter])
useEffect(() => { useEffect(() => {
const readyListener = messageTransporter.doAsSoonAsReady(() => { const readyListener = messageTransporter.doAsSoonAsReady(() => {
const timerId = reconnectTimeout.current reconnectCount.current = 0
if (timerId !== undefined) {
window.clearTimeout(timerId)
}
reconnectTimeout.current = undefined
}) })
messageTransporter.on('connected', () => logger.debug(`Connected`)) messageTransporter.on('connected', () => logger.debug(`Connected`))
messageTransporter.on('disconnected', () => logger.debug(`Disconnected`)) messageTransporter.on('disconnected', () => logger.debug(`Disconnected`))
return () => { return () => {
const interval = reconnectTimeout.current
interval && window.clearTimeout(interval)
readyListener.off() readyListener.off()
} }
}, [messageTransporter]) }, [messageTransporter])