@@ -196,7 +196,15 @@ class WebSocketSSHProxy {
196196 localSession . onAuthenticating ( async ( e ) => {
197197 this . flow . workspaceId = e . username ?? '' ;
198198 this . sendUserStatusFlow ( 'connecting' ) ;
199- e . authenticationPromise = this . authenticateClient ( e . username ?? '' )
199+ e . authenticationPromise = this . authenticateClient ( e . username ?? '' , ( ) => {
200+ // in case of stale connection ensure to trigger the reconnect asap
201+ // try gracefully
202+ localSession . close ( SshDisconnectReason . connectionLost ) ;
203+ // but if not force exit
204+ setTimeout ( ( ) => {
205+ exitProcess ( true ) ;
206+ } , 50 ) ;
207+ } )
200208 . then ( async session => {
201209 this . sendUserStatusFlow ( 'connected' ) ;
202210 pipeSession = session ;
@@ -237,7 +245,7 @@ class WebSocketSSHProxy {
237245 }
238246 }
239247
240- private async authenticateClient ( username : string ) {
248+ private async authenticateClient ( username : string , onStale : ( ) => void ) {
241249 const workspaceInfo = await this . retryGetWorkspaceInfo ( username ) ;
242250 this . flow . instanceId = workspaceInfo . instanceId ;
243251 this . flow . userId = workspaceInfo . userId ;
@@ -246,13 +254,13 @@ class WebSocketSSHProxy {
246254 }
247255
248256 if ( FORCE_TUNNEL ) {
249- return this . getTunnelSSHConfig ( workspaceInfo ) ;
257+ return this . getTunnelSSHConfig ( workspaceInfo , onStale ) ;
250258 }
251259 try {
252260 return await this . tryDirectSSH ( workspaceInfo ) ;
253261 } catch ( e ) {
254262 this . sendErrorReport ( this . flow , e , 'try direct ssh failed' ) ;
255- return this . getTunnelSSHConfig ( workspaceInfo ) ;
263+ return this . getTunnelSSHConfig ( workspaceInfo , onStale ) ;
256264 }
257265 }
258266
@@ -279,7 +287,7 @@ class WebSocketSSHProxy {
279287 }
280288 }
281289
282- private async getTunnelSSHConfig ( workspaceInfo : GetWorkspaceAuthInfoResponse ) : Promise < SshClientSession > {
290+ private async getTunnelSSHConfig ( workspaceInfo : GetWorkspaceAuthInfoResponse , onStale : ( ) => void ) : Promise < SshClientSession > {
283291 try {
284292 const workspaceWSUrl = `wss://${ workspaceInfo . workspaceId } .${ workspaceInfo . workspaceHost } ` ;
285293 const socket = new WebSocket ( workspaceWSUrl + '/_supervisor/tunnel/ssh' , undefined , {
@@ -306,7 +314,8 @@ class WebSocketSSHProxy {
306314 // sends out pings plus a conservative assumption of the latency.
307315 pingTimeout = setTimeout ( ( ) => {
308316 this . telemetryService . sendUserFlowStatus ( 'stale' , this . flow ) ;
309- socket . terminate ( ) ;
317+ session . close ( SshDisconnectReason . byApplication ) ;
318+ onStale ( ) ;
310319 } , pingPeriod + 1000 ) ;
311320 } ;
312321 const stopHearbeat = ( ) => {
0 commit comments