Skip to main content

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

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