@@ -53,7 +53,7 @@ import {
5353import { Patterns } from "./patterns" ;
5454import { is_array } from "@cocalc/util/misc" ;
5555import { UsageMonitor } from "@cocalc/conat/monitor/usage" ;
56- import { once } from "@cocalc/util/async-utils" ;
56+ import { once , until } from "@cocalc/util/async-utils" ;
5757import {
5858 clusterLink ,
5959 type ClusterLink ,
@@ -940,7 +940,7 @@ export class ConatServer extends EventEmitter {
940940 this . subscriptions [ id ] = new Set < string > ( ) ;
941941 }
942942
943- socket . emit ( "info" , { ... this . info ( ) , user } ) ;
943+ this . sendInfo ( socket , user ) ;
944944
945945 socket . on ( "stats" , ( { recv0 } ) => {
946946 const s = this . stats [ socket . id ] ;
@@ -1086,6 +1086,38 @@ export class ConatServer extends EventEmitter {
10861086 } ) ;
10871087 } ;
10881088
1089+ sendInfo = async ( socket , user ) => {
1090+ // we send info with an ack because I think sometimes the initial "info"
1091+ // message gets dropped, leaving a broken hanging connection that never
1092+ // does anything (until the user explicitly refreshes their browser).
1093+ // I did see what is probably this in production frequently.
1094+ try {
1095+ await until (
1096+ async ( ) => {
1097+ if ( ! socket . conn ?. readyState . startsWith ( "o" ) ) {
1098+ // logger.debug(`failed to send "info" message to ${socket.id}`);
1099+ // readyState not defined or not opened or opening, so connection must
1100+ // have been closed before success.
1101+ return true ;
1102+ }
1103+ try {
1104+ await socket
1105+ . timeout ( 7500 )
1106+ . emitWithAck ( "info" , { ...this . info ( ) , user } ) ;
1107+ return true ;
1108+ } catch ( err ) {
1109+ // logger.debug(`error sending "info" message to ${socket.id}`, err);
1110+ return false ;
1111+ }
1112+ } ,
1113+ { min : 5000 , max : 30000 , timeout : 120_000 } ,
1114+ ) ;
1115+ } catch {
1116+ // never ack'd "info" after a few minutes -- could just be an old client,
1117+ // so don't do anything at this point.
1118+ }
1119+ } ;
1120+
10891121 address = ( ) => getServerAddress ( this . options ) ;
10901122
10911123 // create new client in the same process connected to this server.
@@ -1349,8 +1381,8 @@ export class ConatServer extends EventEmitter {
13491381 const usage = async ( ) => {
13501382 return { [ this . id ] : this . usage . stats ( ) } ;
13511383 } ;
1352- // user has to explicitly refresh there browser after
1353- // being disconnected this way
1384+ // user has to explicitly refresh their browser after
1385+ // being disconnected this way:
13541386 const disconnect = async ( ids : string | string [ ] ) => {
13551387 if ( typeof ids == "string" ) {
13561388 ids = [ ids ] ;
0 commit comments