use crate::role::context::worker::WorkerContext;
use crate::role::result::worker::WorkerError;
use crate::role::traits::worker::WorkerRole;
use crate::task::context::TaskContext;
use crate::task::factory::{BoxTaskFuture, Service, TaskResult};
use std::sync::Arc;
use tokio::sync::Mutex;
pub struct WorkerRoleAdapter<T> {
role: Arc<Mutex<T>>,
}
impl<T> WorkerRoleAdapter<T>
where
T: WorkerRole,
{
pub fn new(role: T) -> Self {
Self {
role: Arc::new(Mutex::new(role)),
}
}
}
impl<T> Service for WorkerRoleAdapter<T>
where
T: WorkerRole,
{
fn call(&self, ctx: TaskContext) -> BoxTaskFuture {
let role = self.role.clone();
let worker_context = WorkerContext::new(ctx);
Box::pin(async move {
let mut role = role.lock().await;
run_worker_lifecycle(&mut *role, &worker_context).await
})
}
}
async fn run_worker_lifecycle<T>(role: &mut T, ctx: &WorkerContext) -> TaskResult
where
T: WorkerRole,
{
if let Err(error) = role.init(ctx).await {
return worker_error_to_task_result(error);
}
if let Err(error) = role.work(ctx).await {
return worker_error_to_task_result(error);
}
if let Err(error) = role.complete(ctx).await {
return worker_error_to_task_result(error);
}
if ctx.is_cancelled() {
TaskResult::Cancelled
} else {
TaskResult::Succeeded
}
}
fn worker_error_to_task_result(error: WorkerError) -> TaskResult {
TaskResult::Failed(error.into_task_failure())
}