Skip to main content

rust_supervisor/role/adapter/
worker.rs

1//! Worker role adapter.
2//!
3//! The adapter owns the bridge from [`WorkerRole`] lifecycle methods to the
4//! existing [`TaskFactory`](crate::task::factory::TaskFactory) runtime contract.
5
6use crate::role::context::worker::WorkerContext;
7use crate::role::result::worker::WorkerError;
8use crate::role::traits::worker::WorkerRole;
9use crate::task::context::TaskContext;
10use crate::task::factory::{BoxTaskFuture, Service, TaskResult};
11use std::sync::Arc;
12use tokio::sync::Mutex;
13
14/// Adapter that turns a worker role into a task factory service.
15pub struct WorkerRoleAdapter<T> {
16    /// Role instance protected across runtime task starts.
17    role: Arc<Mutex<T>>,
18}
19
20impl<T> WorkerRoleAdapter<T>
21where
22    T: WorkerRole,
23{
24    /// Creates a worker role adapter.
25    ///
26    /// # Arguments
27    ///
28    /// - `role`: Worker role instance that owns user lifecycle state.
29    ///
30    /// # Returns
31    ///
32    /// Returns an adapter that implements the task factory service contract.
33    ///
34    /// # Examples
35    ///
36    /// ```
37    /// use rust_supervisor::role::adapter::worker::WorkerRoleAdapter;
38    /// use rust_supervisor::role::context::worker::WorkerContext;
39    /// use rust_supervisor::role::result::worker::WorkerResult;
40    /// use rust_supervisor::role::traits::worker::WorkerRole;
41    ///
42    /// struct ExampleWorker;
43    ///
44    /// impl WorkerRole for ExampleWorker {
45    ///     async fn work(&mut self, ctx: &WorkerContext) -> WorkerResult<()> {
46    ///         let _ = ctx;
47    ///         Ok(())
48    ///     }
49    /// }
50    ///
51    /// let _adapter = WorkerRoleAdapter::new(ExampleWorker);
52    /// ```
53    pub fn new(role: T) -> Self {
54        Self {
55            role: Arc::new(Mutex::new(role)),
56        }
57    }
58}
59
60impl<T> Service for WorkerRoleAdapter<T>
61where
62    T: WorkerRole,
63{
64    /// Builds one task future for the adapted worker role.
65    fn call(&self, ctx: TaskContext) -> BoxTaskFuture {
66        let role = self.role.clone();
67        let worker_context = WorkerContext::new(ctx);
68        Box::pin(async move {
69            let mut role = role.lock().await;
70            run_worker_lifecycle(&mut *role, &worker_context).await
71        })
72    }
73}
74
75/// Runs the worker lifecycle and maps role errors into task results.
76///
77/// # Arguments
78///
79/// - `role`: Worker role implementation.
80/// - `ctx`: Worker-specific context passed to lifecycle methods.
81///
82/// # Returns
83///
84/// Returns a [`TaskResult`] consumed by the runtime.
85async fn run_worker_lifecycle<T>(role: &mut T, ctx: &WorkerContext) -> TaskResult
86where
87    T: WorkerRole,
88{
89    if let Err(error) = role.init(ctx).await {
90        return worker_error_to_task_result(error);
91    }
92    if let Err(error) = role.work(ctx).await {
93        return worker_error_to_task_result(error);
94    }
95    if let Err(error) = role.complete(ctx).await {
96        return worker_error_to_task_result(error);
97    }
98    if ctx.is_cancelled() {
99        TaskResult::Cancelled
100    } else {
101        TaskResult::Succeeded
102    }
103}
104
105/// Converts a worker error into a failed task result.
106///
107/// # Arguments
108///
109/// - `error`: Worker role error returned by a lifecycle method.
110///
111/// # Returns
112///
113/// Returns [`TaskResult::Failed`] with a typed task failure payload.
114fn worker_error_to_task_result(error: WorkerError) -> TaskResult {
115    TaskResult::Failed(error.into_task_failure())
116}