execution_policy/
policy.rs1use std::sync::Arc;
4
5use crate::attempt::Attempt;
6use crate::builder::ExecutionPolicyBuilder;
7use crate::core::Core;
8use crate::engine::run_pipeline;
9use crate::error::ExecutionError;
10use crate::plan::Plan;
11
12pub struct ExecutionPolicy<C, T, E> {
14 core: C,
15 plan: Arc<Plan<T, E>>,
16}
17
18impl<C: std::fmt::Debug, T, E> std::fmt::Debug for ExecutionPolicy<C, T, E> {
19 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20 f.debug_struct("ExecutionPolicy")
21 .field("core", &self.core)
22 .field("plan", &self.plan)
23 .finish()
24 }
25}
26
27impl<C: Clone, T, E> Clone for ExecutionPolicy<C, T, E> {
28 fn clone(&self) -> Self {
29 Self {
30 core: self.core.clone(),
31 plan: Arc::clone(&self.plan),
32 }
33 }
34}
35
36impl ExecutionPolicy<(), (), ()> {
37 pub fn builder<T, E>() -> ExecutionPolicyBuilder<T, E> {
40 ExecutionPolicyBuilder::new()
41 }
42}
43
44impl<C, T, E> ExecutionPolicy<C, T, E> {
45 pub(crate) fn from_parts(core: C, plan: Arc<Plan<T, E>>) -> Self {
46 Self { core, plan }
47 }
48
49 pub fn circuit_state(&self) -> Option<crate::error::BreakerState> {
51 self.plan.breaker.as_ref().map(|b| b.runtime.state())
52 }
53}
54
55impl<C, T, E> ExecutionPolicy<C, T, E>
56where
57 C: Core,
58{
59 pub async fn run<F>(&self, mut op: F) -> Result<T, ExecutionError<E>>
61 where
62 F: AsyncFnMut() -> Result<T, E>,
63 {
64 run_pipeline(
65 &self.core,
66 &self.plan,
67 async move |_attempt: Attempt<'_>| op().await,
68 )
69 .await
70 }
71
72 pub async fn execute<F>(&self, op: F) -> Result<T, ExecutionError<E>>
74 where
75 F: AsyncFnMut(Attempt<'_>) -> Result<T, E>,
76 {
77 run_pipeline(&self.core, &self.plan, op).await
78 }
79
80 pub async fn run_with<S, F>(&self, state: &S, mut op: F) -> Result<T, ExecutionError<E>>
82 where
83 S: Sync + ?Sized,
84 F: AsyncFnMut(&S) -> Result<T, E>,
85 {
86 run_pipeline(
87 &self.core,
88 &self.plan,
89 async move |_attempt: Attempt<'_>| op(state).await,
90 )
91 .await
92 }
93
94 pub async fn execute_with<S, F>(&self, state: &S, mut op: F) -> Result<T, ExecutionError<E>>
96 where
97 S: Sync + ?Sized,
98 F: AsyncFnMut(&S, Attempt<'_>) -> Result<T, E>,
99 {
100 run_pipeline(&self.core, &self.plan, async move |attempt: Attempt<'_>| {
101 op(state, attempt).await
102 })
103 .await
104 }
105}