Skip to main content

rust_supervisor/role/adapter/
supervisor.rs

1//! Supervisor role adapter.
2//!
3//! The adapter owns the bridge from [`SupervisorRole`] lifecycle methods to the
4//! existing [`TaskFactory`](crate::task::factory::TaskFactory) runtime contract.
5
6use crate::role::context::supervisor::SupervisorContext;
7use crate::role::lifecycle::RoleLifecyclePhase;
8use crate::role::result::supervisor::SupervisorRoleError;
9use crate::role::traits::supervisor::SupervisorRole;
10use crate::runtime::supervisor::Supervisor;
11use crate::task::context::TaskContext;
12use crate::task::factory::{BoxTaskFuture, Service, TaskResult};
13use std::sync::Arc;
14use tokio::sync::Mutex;
15
16/// Adapter that turns a supervisor role into a task factory service.
17pub struct SupervisorRoleAdapter<T> {
18    /// Role instance protected across runtime task starts.
19    role: Arc<Mutex<T>>,
20}
21
22impl<T> SupervisorRoleAdapter<T>
23where
24    T: SupervisorRole,
25{
26    /// Creates a supervisor role adapter.
27    ///
28    /// # Arguments
29    ///
30    /// - `role`: Supervisor role instance that owns user lifecycle state.
31    ///
32    /// # Returns
33    ///
34    /// Returns an adapter that implements the task factory service contract.
35    ///
36    /// # Examples
37    ///
38    /// ```
39    /// use rust_supervisor::role::adapter::supervisor::SupervisorRoleAdapter;
40    /// use rust_supervisor::role::context::supervisor::SupervisorContext;
41    /// use rust_supervisor::role::result::supervisor::SupervisorResult;
42    /// use rust_supervisor::role::traits::supervisor::SupervisorRole;
43    /// use rust_supervisor::spec::supervisor::SupervisorSpec;
44    ///
45    /// struct ExampleSupervisor;
46    ///
47    /// impl SupervisorRole for ExampleSupervisor {
48    ///     async fn build_tree(
49    ///         &mut self,
50    ///         ctx: &SupervisorContext,
51    ///     ) -> SupervisorResult<SupervisorSpec> {
52    ///         let _ = ctx;
53    ///         Ok(SupervisorSpec::root(Vec::new()))
54    ///     }
55    /// }
56    ///
57    /// let _adapter = SupervisorRoleAdapter::new(ExampleSupervisor);
58    /// ```
59    pub fn new(role: T) -> Self {
60        Self {
61            role: Arc::new(Mutex::new(role)),
62        }
63    }
64}
65
66impl<T> Service for SupervisorRoleAdapter<T>
67where
68    T: SupervisorRole,
69{
70    /// Builds one task future for the adapted supervisor role.
71    fn call(&self, ctx: TaskContext) -> BoxTaskFuture {
72        let role = self.role.clone();
73        let supervisor_context = SupervisorContext::new(ctx);
74        Box::pin(async move {
75            let mut role = role.lock().await;
76            run_supervisor_lifecycle(&mut *role, &supervisor_context).await
77        })
78    }
79}
80
81/// Runs the supervisor lifecycle and maps role errors into task results.
82///
83/// # Arguments
84///
85/// - `role`: Supervisor role implementation.
86/// - `ctx`: Supervisor-specific context passed to lifecycle methods.
87///
88/// # Returns
89///
90/// Returns a [`TaskResult`] consumed by the runtime.
91async fn run_supervisor_lifecycle<T>(role: &mut T, ctx: &SupervisorContext) -> TaskResult
92where
93    T: SupervisorRole,
94{
95    let spec = match role.build_tree(ctx).await {
96        Ok(spec) => spec,
97        Err(error) => return supervisor_error_to_task_result(error),
98    };
99    let handle = match Supervisor::start(spec).await {
100        Ok(handle) => handle,
101        Err(error) => {
102            return supervisor_error_to_task_result(SupervisorRoleError::from_supervisor_error(
103                ctx.child_id().clone(),
104                RoleLifecyclePhase::BuildTree,
105                error,
106            ));
107        }
108    };
109
110    let run_result = role.run(ctx, &handle).await;
111    let shutdown_result = role.shutdown(ctx, &handle).await;
112    if let Err(error) = run_result {
113        return supervisor_error_to_task_result(error);
114    }
115    if let Err(error) = shutdown_result {
116        return supervisor_error_to_task_result(error);
117    }
118    if ctx.is_shutdown_requested() {
119        TaskResult::Cancelled
120    } else {
121        TaskResult::Succeeded
122    }
123}
124
125/// Converts a supervisor role error into a failed task result.
126///
127/// # Arguments
128///
129/// - `error`: Supervisor role error returned by a lifecycle method.
130///
131/// # Returns
132///
133/// Returns [`TaskResult::Failed`] with a typed task failure payload.
134fn supervisor_error_to_task_result(error: SupervisorRoleError) -> TaskResult {
135    TaskResult::Failed(error.into_task_failure())
136}