@@ -17,6 +17,12 @@ pub struct EnvoyHandle {
1717 pub ( crate ) started_rx : tokio:: sync:: watch:: Receiver < ( ) > ,
1818}
1919
20+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
21+ pub struct ServerlessActorStart {
22+ pub actor_id : String ,
23+ pub generation : u32 ,
24+ }
25+
2026impl EnvoyHandle {
2127 #[ doc( hidden) ]
2228 pub fn from_shared ( shared : Arc < SharedContext > ) -> Self {
@@ -85,6 +91,23 @@ impl EnvoyHandle {
8591 & self . shared . config . namespace
8692 }
8793
94+ pub fn active_actor_count ( & self ) -> usize {
95+ let guard = self
96+ . shared
97+ . actors
98+ . lock ( )
99+ . expect ( "shared actor registry poisoned" ) ;
100+ guard
101+ . values ( )
102+ . map ( |generations| {
103+ generations
104+ . values ( )
105+ . filter ( |actor| !actor. handle . is_closed ( ) )
106+ . count ( )
107+ } )
108+ . sum ( )
109+ }
110+
88111 pub fn pool_name ( & self ) -> & str {
89112 & self . shared . config . pool_name
90113 }
@@ -138,6 +161,40 @@ impl EnvoyHandle {
138161 rx. await . ok ( ) . flatten ( )
139162 }
140163
164+ pub async fn wait_actor_registered_then_stopped ( & self , actor_id : & str , generation : u32 ) {
165+ let mut registered = false ;
166+ loop {
167+ let notified = self . shared . actors_notify . notified ( ) ;
168+ if self . is_stopped ( ) {
169+ return ;
170+ }
171+
172+ let actor_is_registered = {
173+ let guard = self
174+ . shared
175+ . actors
176+ . lock ( )
177+ . expect ( "shared actor registry poisoned" ) ;
178+ guard
179+ . get ( actor_id)
180+ . and_then ( |generations| generations. get ( & generation) )
181+ . is_some ( )
182+ } ;
183+
184+ if registered && !actor_is_registered {
185+ return ;
186+ }
187+ if actor_is_registered {
188+ registered = true ;
189+ }
190+
191+ tokio:: select! {
192+ _ = notified => { }
193+ _ = self . wait_stopped( ) => return ,
194+ }
195+ }
196+ }
197+
141198 pub fn http_request_counter (
142199 & self ,
143200 actor_id : & str ,
@@ -484,6 +541,35 @@ impl EnvoyHandle {
484541 /// Inject a serverless start payload into the envoy.
485542 /// The payload is a u16 LE protocol version followed by a serialized ToEnvoy message.
486543 pub async fn start_serverless_actor ( & self , payload : & [ u8 ] ) -> anyhow:: Result < ( ) > {
544+ let ( message, _) = decode_serverless_actor_start_payload ( payload) ?;
545+
546+ // Wait for envoy to be started before injecting
547+ self . started ( ) . await ?;
548+
549+ tracing:: debug!(
550+ data = crate :: stringify:: stringify_to_envoy( & message) ,
551+ "received serverless start"
552+ ) ;
553+ self . shared
554+ . envoy_tx
555+ . send ( ToEnvoyMessage :: ConnMessage { message } )
556+ . map_err ( |_| anyhow:: anyhow!( "envoy channel closed" ) ) ?;
557+
558+ Ok ( ( ) )
559+ }
560+
561+ pub fn decode_serverless_actor_start (
562+ & self ,
563+ payload : & [ u8 ] ,
564+ ) -> anyhow:: Result < ServerlessActorStart > {
565+ let ( _, actor_start) = decode_serverless_actor_start_payload ( payload) ?;
566+ Ok ( actor_start)
567+ }
568+ }
569+
570+ fn decode_serverless_actor_start_payload (
571+ payload : & [ u8 ] ,
572+ ) -> anyhow:: Result < ( protocol:: ToEnvoy , ServerlessActorStart ) > {
487573 use vbare:: OwnedVersionedData ;
488574
489575 if payload. len ( ) < 2 {
@@ -524,21 +610,15 @@ impl EnvoyHandle {
524610 anyhow:: bail!( "invalid serverless payload: expected CommandStartActor" ) ;
525611 }
526612
527- // Wait for envoy to be started before injecting
528- self . started ( ) . await ?;
529-
530- tracing:: debug!(
531- data = crate :: stringify:: stringify_to_envoy( & message) ,
532- "received serverless start"
533- ) ;
534- self . shared
535- . envoy_tx
536- . send ( ToEnvoyMessage :: ConnMessage { message } )
537- . map_err ( |_| anyhow:: anyhow!( "envoy channel closed" ) ) ?;
613+ let actor_start = ServerlessActorStart {
614+ actor_id : commands[ 0 ] . checkpoint . actor_id . clone ( ) ,
615+ generation : commands[ 0 ] . checkpoint . generation ,
616+ } ;
538617
539- Ok ( ( ) )
618+ Ok ( ( message , actor_start ) )
540619 }
541620
621+ impl EnvoyHandle {
542622 async fn send_kv_request (
543623 & self ,
544624 actor_id : String ,
0 commit comments