Mountain/RunTime/Execute/
RunWithRetry.rs1
2use std::sync::Arc;
7
8use CommonLibrary::{
9 Effect::{ActionEffect::ActionEffect, ApplicationRunTime::ApplicationRunTime as ApplicationRunTimeTrait},
10 Environment::Requires::Requires,
11 Error::CommonError::CommonError,
12};
13
14use crate::{RunTime::ApplicationRunTime::ApplicationRunTime, dev_log};
15
16impl ApplicationRunTime {
17 pub async fn RunWithRetry<TCapabilityProvider, TError, TOutput>(
18 &self,
19
20 Effect:ActionEffect<Arc<TCapabilityProvider>, TError, TOutput>,
21
22 MaximumRetries:u32,
23
24 InitialDelay:std::time::Duration,
25 ) -> Result<TOutput, TError>
26 where
27 TCapabilityProvider: ?Sized + Send + Sync + 'static,
28 <Self as CommonLibrary::Environment::HasEnvironment::HasEnvironment>::EnvironmentType:
29 Requires<TCapabilityProvider>,
30 TError: From<CommonError> + Send + Sync + 'static + std::fmt::Display,
31 TOutput: Send + Sync + 'static, {
32 let mut RetryCount = 0;
33
34 let mut CurrentDelay = InitialDelay;
35
36 while RetryCount <= MaximumRetries {
37 match ApplicationRunTimeTrait::Run(self, Effect.clone()).await {
38 Ok(Result) => return Ok(Result),
39
40 Err(Error) => {
41 if RetryCount == MaximumRetries {
42 return Err(Error);
43 }
44
45 RetryCount += 1;
46
47 dev_log!(
48 "lifecycle",
49 "warn: [ApplicationRunTime] Effect execution failed (attempt {}): {}. Retrying in {:?}...",
50 RetryCount,
51 Error,
52 CurrentDelay
53 );
54
55 tokio::time::sleep(CurrentDelay).await;
56
57 CurrentDelay *= 2;
58 },
59 }
60 }
61
62 Err(
63 CommonError::Unknown { Description:format!("Effect execution failed after {} retries", MaximumRetries) }
64 .into(),
65 )
66 }
67}