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}