Skip to main content

Mountain/ApplicationState/Internal/Recovery/RecoverState/
RecoverStateWithBackoff.rs

1#![allow(non_snake_case)]
2
3//! Retry a recovery `Operation` up to `MaxAttempts` times with
4//! exponential backoff (100 ms, doubled per failure). The async
5//! sleep yields the runtime so other work can proceed during the
6//! retry window. Final failure surfaces the last error verbatim.
7
8use CommonLibrary::Error::CommonError::CommonError;
9
10use crate::dev_log;
11
12pub async fn Fn<F, T>(Operation:F, MaxAttempts:u32, OperationName:&str) -> Result<T, CommonError>
13where
14	F: Fn() -> Result<T, CommonError> + Send, {
15	let mut Attempt = 0;
16	let mut DelayMs:u64 = 100;
17
18	while Attempt < MaxAttempts {
19		match Operation() {
20			Ok(Result) => return Ok(Result),
21			Err(Error) => {
22				Attempt += 1;
23				if Attempt == MaxAttempts {
24					return Err(Error);
25				}
26				dev_log!(
27					"lifecycle",
28					"warn: [RecoverState] Attempt {} failed for '{}': {}. Retrying in {}ms...",
29					Attempt,
30					OperationName,
31					Error,
32					DelayMs
33				);
34				tokio::time::sleep(tokio::time::Duration::from_millis(DelayMs)).await;
35				DelayMs *= 2;
36			},
37		}
38	}
39
40	Err(CommonError::Unknown {
41		Description:format!("Failed to recover state for '{}' after {} attempts", OperationName, MaxAttempts),
42	})
43}