From eb26ea5233ca9351ce948f6fb8d006346149159b Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Tue, 2 Dec 2025 15:05:19 -0800 Subject: [PATCH 1/3] move wait_for_process_ready --- src/hyperapp.rs | 82 ------------------------------------------------- src/lib.rs | 82 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 82 deletions(-) diff --git a/src/hyperapp.rs b/src/hyperapp.rs index d6f63d0..13a3693 100644 --- a/src/hyperapp.rs +++ b/src/hyperapp.rs @@ -594,88 +594,6 @@ pub fn pretty_print_send_error(error: &SendError) { ); } -/// Classification for readiness polling of another process. -#[derive(Debug, PartialEq, Eq)] -pub enum WaitClassification { - /// The target responded but indicated it is still starting up. - Starting, - /// The target is ready (or responded with a payload we consider ready). - Ready, - /// The target responded with an unknown payload. - Unknown, -} - -/// Poll a target process until it reports ready. -/// -/// - `target`: process address to poll (e.g., hypermap-cacher). -/// - `request_body`: request payload to send each attempt. -/// - `timeout_s`: per-request timeout in seconds. -/// - `retry_delay_s`: delay between attempts when not ready or on error. -/// - `classify`: function to classify the response body. -/// - `treat_unknown_as_ready`: if true, any non-starting response is treated as ready. -pub fn wait_for_process_ready( - target: Address, - request_body: Vec, - timeout_s: u64, - retry_delay_s: u64, - mut classify: F, - treat_unknown_as_ready: bool, -) where - F: FnMut(&[u8]) -> WaitClassification, -{ - let mut attempt = 1; - loop { - match Request::to(target.clone()) - .body(request_body.clone()) - .send_and_await_response(timeout_s) - { - Ok(Ok(response)) => { - let classification = classify(response.body()); - match classification { - WaitClassification::Starting => { - info!( - "Target {} still starting (attempt {}), retrying in {}s", - target, attempt, retry_delay_s - ); - } - WaitClassification::Ready => { - info!("Target {} ready after {} attempt(s)", target, attempt); - break; - } - WaitClassification::Unknown => { - if treat_unknown_as_ready { - info!( - "Target {} responded with unknown payload, proceeding as ready", - target - ); - break; - } else { - info!( - "Target {} responded with unknown payload, retrying in {}s", - target, retry_delay_s - ); - } - } - } - } - Ok(Err(e)) => { - info!( - "Error response from {} (attempt {}): {:?}, retrying in {}s", - target, attempt, e, retry_delay_s - ); - } - Err(e) => { - info!( - "Failed to contact {} (attempt {}): {:?}, retrying in {}s", - target, attempt, e, retry_delay_s - ); - } - } - attempt += 1; - std::thread::sleep(std::time::Duration::from_secs(retry_delay_s)); - } -} - // For demonstration, we'll define them all in one place. // Make sure the signatures match the real function signatures you require! pub fn no_init_fn(_state: &mut S) { diff --git a/src/lib.rs b/src/lib.rs index f294f2c..859c2cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -364,6 +364,88 @@ pub fn eval_our(address: &Address) -> Address { address } +/// Classification for readiness polling of another process. +#[derive(Debug, PartialEq, Eq)] +pub enum WaitClassification { + /// The target responded but indicated it is still starting up. + Starting, + /// The target is ready (or responded with a payload we consider ready). + Ready, + /// The target responded with an unknown payload. + Unknown, +} + +/// Poll a target process until it reports ready. +/// +/// - `target`: process address to poll (e.g., hypermap-cacher). +/// - `request_body`: request payload to send each attempt. +/// - `timeout_s`: per-request timeout in seconds. +/// - `retry_delay_s`: delay between attempts when not ready or on error. +/// - `classify`: function to classify the response body. +/// - `treat_unknown_as_ready`: if true, any non-starting response is treated as ready. +pub fn wait_for_process_ready( + target: Address, + request_body: Vec, + timeout_s: u64, + retry_delay_s: u64, + mut classify: F, + treat_unknown_as_ready: bool, +) where + F: FnMut(&[u8]) -> WaitClassification, +{ + let mut attempt = 1; + loop { + match Request::to(target.clone()) + .body(request_body.clone()) + .send_and_await_response(timeout_s) + { + Ok(Ok(response)) => { + let classification = classify(response.body()); + match classification { + WaitClassification::Starting => { + info!( + "Target {} still starting (attempt {}), retrying in {}s", + target, attempt, retry_delay_s + ); + } + WaitClassification::Ready => { + info!("Target {} ready after {} attempt(s)", target, attempt); + break; + } + WaitClassification::Unknown => { + if treat_unknown_as_ready { + info!( + "Target {} responded with unknown payload, proceeding as ready", + target + ); + break; + } else { + info!( + "Target {} responded with unknown payload, retrying in {}s", + target, retry_delay_s + ); + } + } + } + } + Ok(Err(e)) => { + info!( + "Error response from {} (attempt {}): {:?}, retrying in {}s", + target, attempt, e, retry_delay_s + ); + } + Err(e) => { + info!( + "Failed to contact {} (attempt {}): {:?}, retrying in {}s", + target, attempt, e, retry_delay_s + ); + } + } + attempt += 1; + std::thread::sleep(std::time::Duration::from_secs(retry_delay_s)); + } +} + /// The `Spawn!()` macro is defined here as a no-op. /// However, in practice, `kit build` will rewrite it during pre-processing. /// From bbe9f579903512547a6b6a5c72005c5bebc40aab Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Tue, 2 Dec 2025 15:27:27 -0800 Subject: [PATCH 2/3] fix logging (not always available -> use print_to_terminal) and add `max_attempts` option --- Cargo.lock | 2 +- src/lib.rs | 59 +++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ceba34b..2bde1f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1617,7 +1617,7 @@ dependencies = [ [[package]] name = "hyperware_process_lib" -version = "2.2.0" +version = "2.2.1" dependencies = [ "alloy", "alloy-primitives", diff --git a/src/lib.rs b/src/lib.rs index 859c2cb..763d5a9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -383,6 +383,7 @@ pub enum WaitClassification { /// - `retry_delay_s`: delay between attempts when not ready or on error. /// - `classify`: function to classify the response body. /// - `treat_unknown_as_ready`: if true, any non-starting response is treated as ready. +/// - `max_attempts`: number of attempts before continuing without a ready response. pub fn wait_for_process_ready( target: Address, request_body: Vec, @@ -390,11 +391,19 @@ pub fn wait_for_process_ready( retry_delay_s: u64, mut classify: F, treat_unknown_as_ready: bool, + max_attempts: Option, ) where F: FnMut(&[u8]) -> WaitClassification, { let mut attempt = 1; loop { + let mut fail_message_suffix = format!(", retrying in {retry_delay_s}s"); + if let Some(ma) = max_attempts { + if attempt >= ma { + fail_message_suffix = ", abandoning waiting and proceeding as if ready".to_string() + } + } + match Request::to(target.clone()) .body(request_body.clone()) .send_and_await_response(timeout_s) @@ -403,41 +412,59 @@ pub fn wait_for_process_ready( let classification = classify(response.body()); match classification { WaitClassification::Starting => { - info!( - "Target {} still starting (attempt {}), retrying in {}s", - target, attempt, retry_delay_s + crate::print_to_terminal( + 2, + &format!( + "Target {} still starting (attempt {}){}", + target, attempt, fail_message_suffix + ), ); } WaitClassification::Ready => { - info!("Target {} ready after {} attempt(s)", target, attempt); + crate::print_to_terminal( + 2, + &format!("Target {} ready after {} attempt(s)", target, attempt), + ); break; } WaitClassification::Unknown => { if treat_unknown_as_ready { - info!( - "Target {} responded with unknown payload, proceeding as ready", - target + crate::print_to_terminal( + 2, + &format!( + "Target {} responded with unknown payload, proceeding as ready", + target + ), ); break; } else { - info!( - "Target {} responded with unknown payload, retrying in {}s", - target, retry_delay_s + crate::print_to_terminal( + 2, + &format!( + "Target {} responded with unknown payload{}", + target, fail_message_suffix + ), ); } } } } Ok(Err(e)) => { - info!( - "Error response from {} (attempt {}): {:?}, retrying in {}s", - target, attempt, e, retry_delay_s + crate::print_to_terminal( + 2, + &format!( + "Error response from {} (attempt {}): {:?}{}", + target, attempt, e, fail_message_suffix + ), ); } Err(e) => { - info!( - "Failed to contact {} (attempt {}): {:?}, retrying in {}s", - target, attempt, e, retry_delay_s + crate::print_to_terminal( + 2, + &format!( + "Failed to contact {} (attempt {}): {:?}{}", + target, attempt, e, fail_message_suffix + ), ); } } From f5a7adc56fb0407fab6d0ecd575552b2ec55046c Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Tue, 2 Dec 2025 15:34:48 -0800 Subject: [PATCH 3/3] update docs comment --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 763d5a9..d7102df 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -375,7 +375,7 @@ pub enum WaitClassification { Unknown, } -/// Poll a target process until it reports ready. +/// Poll a target process until it reports ready while blocking. /// /// - `target`: process address to poll (e.g., hypermap-cacher). /// - `request_body`: request payload to send each attempt.