@@ -12,10 +12,15 @@ import {
1212import { IS_LOCAL } from "common/envs/constants" ;
1313import { getWebsocketUrl } from "common/api/utils" ;
1414
15+ // Extend the type definition locally
16+ interface HeartbeatWebSocket extends WebSocket {
17+ isAlive ?: boolean
18+ }
19+
1520const SWITCHBOARD = new Switchboard ( )
1621
1722// if a connection doesn't ping for this long, we assume the other side is toast
18- const CONNECTION_TIMEOUT_MS = 60 * 1000
23+ // const CONNECTION_TIMEOUT_MS = 60 * 1000
1924
2025export class MessageParseError extends Error {
2126 details ?: unknown
@@ -52,7 +57,7 @@ function parseMessage(data: RawData): ClientMessage {
5257 }
5358}
5459
55- function processMessage ( ws : WebSocket , data : RawData ) : ServerMessage < 'ack' > {
60+ function processMessage ( ws : HeartbeatWebSocket , data : RawData ) : ServerMessage < 'ack' > {
5661 try {
5762 const msg = parseMessage ( data )
5863 const { type, txid } = msg
@@ -129,21 +134,26 @@ export function listen(server: HttpServer, path: string) {
129134 let deadConnectionCleaner : NodeJS . Timeout | undefined
130135 wss . on ( 'listening' , ( ) => {
131136 log . info ( `Web socket server listening on ${ path } . ${ getWebsocketUrl ( ) } ` )
132- deadConnectionCleaner = setInterval ( function ping ( ) {
133- const now = Date . now ( )
134- for ( const ws of wss . clients ) {
135- const lastSeen = SWITCHBOARD . getClient ( ws ) . lastSeen
136- if ( lastSeen < now - CONNECTION_TIMEOUT_MS ) {
137- ws . terminate ( )
137+ deadConnectionCleaner = setInterval ( ( ) => {
138+ for ( const ws of wss . clients as Set < HeartbeatWebSocket > ) {
139+ if ( ws . isAlive === false ) {
140+ log . debug ( 'Terminating dead connection' ) ;
141+ ws . terminate ( ) ;
142+ continue ;
138143 }
144+ ws . isAlive = false ;
145+ log . debug ( 'Sending ping to client' ) ;
146+ ws . ping ( ) ;
139147 }
140- } , CONNECTION_TIMEOUT_MS )
148+ } , 25000 ) ;
141149 } )
142150 wss . on ( 'error' , ( err ) => {
143151 log . error ( 'Error on websocket server.' , { error : err } )
144152 } )
145- wss . on ( 'connection' , ( ws ) => {
146- // todo: should likely kill connections that haven't sent any ping for a long time
153+ wss . on ( 'connection' , ( ws : HeartbeatWebSocket ) => {
154+ ws . isAlive = true ;
155+ log . debug ( 'Received pong from client' ) ;
156+ ws . on ( 'pong' , ( ) => ( ws . isAlive = true ) ) ;
147157 metrics . inc ( 'ws/connections_established' )
148158 metrics . set ( 'ws/open_connections' , wss . clients . size )
149159 log . debug ( 'WS client connected.' )
0 commit comments