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
17	let mut DelayMs:u64 = 100;
18
19	while Attempt < MaxAttempts {
20		match Operation() {
21			Ok(Result) => return Ok(Result),
22
23			Err(Error) => {
24				Attempt += 1;
25
26				if Attempt == MaxAttempts {
27					return Err(Error);
28				}
29
30				dev_log!(
31					"lifecycle",
32					"warn: [RecoverState] Attempt {} failed for '{}': {}. Retrying in {}ms...",
33					Attempt,
34					OperationName,
35					Error,
36					DelayMs
37				);
38
39				tokio::time::sleep(tokio::time::Duration::from_millis(DelayMs)).await;
40
41				DelayMs *= 2;
42			},
43		}
44	}
45
46	Err(CommonError::Unknown {
47		Description:format!("Failed to recover state for '{}' after {} attempts", OperationName, MaxAttempts),
48	})
49}