@@ -152,6 +152,11 @@ impl CustomServeTrait for PegboardGateway {
152152 . context ( "failed to read body" ) ?
153153 . to_bytes ( ) ;
154154
155+ let mut stopped_sub = self
156+ . ctx
157+ . subscribe :: < pegboard:: workflows:: actor:: Stopped > ( ( "actor_id" , self . actor_id ) )
158+ . await ?;
159+
155160 // Build subject to publish to
156161 let tunnel_subject =
157162 pegboard:: pubsub_subjects:: RunnerReceiverSubject :: new ( self . runner_id ) . to_string ( ) ;
@@ -212,6 +217,10 @@ impl CustomServeTrait for PegboardGateway {
212217 break ;
213218 }
214219 }
220+ _ = stopped_sub. next( ) => {
221+ tracing:: debug!( "actor stopped while waiting for request response" ) ;
222+ return Err ( ServiceUnavailable . build( ) ) ;
223+ }
215224 _ = drop_rx. changed( ) => {
216225 tracing:: warn!( "tunnel message timeout" ) ;
217226 return Err ( ServiceUnavailable . build( ) ) ;
@@ -278,6 +287,11 @@ impl CustomServeTrait for PegboardGateway {
278287 }
279288 }
280289
290+ let mut stopped_sub = self
291+ . ctx
292+ . subscribe :: < pegboard:: workflows:: actor:: Stopped > ( ( "actor_id" , self . actor_id ) )
293+ . await ?;
294+
281295 // Build subject to publish to
282296 let tunnel_subject =
283297 pegboard:: pubsub_subjects:: RunnerReceiverSubject :: new ( self . runner_id ) . to_string ( ) ;
@@ -339,6 +353,10 @@ impl CustomServeTrait for PegboardGateway {
339353 break ;
340354 }
341355 }
356+ _ = stopped_sub. next( ) => {
357+ tracing:: debug!( "actor stopped while waiting for websocket open" ) ;
358+ return Err ( WebSocketServiceUnavailable . build( ) ) ;
359+ }
342360 _ = drop_rx. changed( ) => {
343361 tracing:: warn!( "websocket open timeout" ) ;
344362 return Err ( WebSocketServiceUnavailable . build( ) ) ;
@@ -364,7 +382,7 @@ impl CustomServeTrait for PegboardGateway {
364382 open_msg. can_hibernate
365383 } ;
366384
367- // Send reclaimed messages
385+ // Send pending messages
368386 self . shared_state
369387 . resend_pending_websocket_messages ( request_id)
370388 . await ?;
@@ -415,6 +433,15 @@ impl CustomServeTrait for PegboardGateway {
415433 return Err ( WebSocketServiceHibernate . build( ) ) ;
416434 }
417435 }
436+ _ = stopped_sub. next( ) => {
437+ tracing:: debug!( "actor stopped during websocket handler loop" ) ;
438+
439+ if can_hibernate {
440+ return Err ( WebSocketServiceHibernate . build( ) ) ;
441+ } else {
442+ return Err ( WebSocketServiceUnavailable . build( ) ) ;
443+ }
444+ }
418445 _ = drop_rx. changed( ) => {
419446 tracing:: warn!( "websocket message timeout" ) ;
420447 return Err ( WebSocketServiceTimeout . build( ) ) ;
@@ -579,6 +606,15 @@ impl CustomServeTrait for PegboardGateway {
579606 client_ws : WebSocketHandle ,
580607 unique_request_id : Uuid ,
581608 ) -> Result < HibernationResult > {
609+ // Immediately rewake if we have pending messages
610+ if self
611+ . shared_state
612+ . has_pending_websocket_messages ( unique_request_id. into_bytes ( ) )
613+ . await ?
614+ {
615+ return Ok ( HibernationResult :: Continue ) ;
616+ }
617+
582618 // Start keepalive task
583619 let ctx = self . ctx . clone ( ) ;
584620 let actor_id = self . actor_id ;
0 commit comments