@@ -594,6 +594,88 @@ pub fn pretty_print_send_error(error: &SendError) {
594594 ) ;
595595}
596596
597+ /// Classification for readiness polling of another process.
598+ #[ derive( Debug , PartialEq , Eq ) ]
599+ pub enum WaitClassification {
600+ /// The target responded but indicated it is still starting up.
601+ Starting ,
602+ /// The target is ready (or responded with a payload we consider ready).
603+ Ready ,
604+ /// The target responded with an unknown payload.
605+ Unknown ,
606+ }
607+
608+ /// Poll a target process until it reports ready.
609+ ///
610+ /// - `target`: process address to poll (e.g., hypermap-cacher).
611+ /// - `request_body`: request payload to send each attempt.
612+ /// - `timeout_s`: per-request timeout in seconds.
613+ /// - `retry_delay_s`: delay between attempts when not ready or on error.
614+ /// - `classify`: function to classify the response body.
615+ /// - `treat_unknown_as_ready`: if true, any non-starting response is treated as ready.
616+ pub fn wait_for_process_ready < F > (
617+ target : Address ,
618+ request_body : Vec < u8 > ,
619+ timeout_s : u64 ,
620+ retry_delay_s : u64 ,
621+ mut classify : F ,
622+ treat_unknown_as_ready : bool ,
623+ ) where
624+ F : FnMut ( & [ u8 ] ) -> WaitClassification ,
625+ {
626+ let mut attempt = 1 ;
627+ loop {
628+ match Request :: to ( target. clone ( ) )
629+ . body ( request_body. clone ( ) )
630+ . send_and_await_response ( timeout_s)
631+ {
632+ Ok ( Ok ( response) ) => {
633+ let classification = classify ( response. body ( ) ) ;
634+ match classification {
635+ WaitClassification :: Starting => {
636+ info ! (
637+ "Target {} still starting (attempt {}), retrying in {}s" ,
638+ target, attempt, retry_delay_s
639+ ) ;
640+ }
641+ WaitClassification :: Ready => {
642+ info ! ( "Target {} ready after {} attempt(s)" , target, attempt) ;
643+ break ;
644+ }
645+ WaitClassification :: Unknown => {
646+ if treat_unknown_as_ready {
647+ info ! (
648+ "Target {} responded with unknown payload, proceeding as ready" ,
649+ target
650+ ) ;
651+ break ;
652+ } else {
653+ info ! (
654+ "Target {} responded with unknown payload, retrying in {}s" ,
655+ target, retry_delay_s
656+ ) ;
657+ }
658+ }
659+ }
660+ }
661+ Ok ( Err ( e) ) => {
662+ info ! (
663+ "Error response from {} (attempt {}): {:?}, retrying in {}s" ,
664+ target, attempt, e, retry_delay_s
665+ ) ;
666+ }
667+ Err ( e) => {
668+ info ! (
669+ "Failed to contact {} (attempt {}): {:?}, retrying in {}s" ,
670+ target, attempt, e, retry_delay_s
671+ ) ;
672+ }
673+ }
674+ attempt += 1 ;
675+ std:: thread:: sleep ( std:: time:: Duration :: from_secs ( retry_delay_s) ) ;
676+ }
677+ }
678+
597679// For demonstration, we'll define them all in one place.
598680// Make sure the signatures match the real function signatures you require!
599681pub fn no_init_fn < S > ( _state : & mut S ) {
0 commit comments