use crate::role::context::job::JobContext;
use crate::role::result::job::JobError;
use crate::role::traits::job::JobRole;
use crate::task::context::TaskContext;
use crate::task::factory::{BoxTaskFuture, Service, TaskResult};
use std::sync::Arc;
use tokio::sync::Mutex;
pub struct JobRoleAdapter<T> {
role: Arc<Mutex<T>>,
}
impl<T> JobRoleAdapter<T>
where
T: JobRole,
{
pub fn new(role: T) -> Self {
Self {
role: Arc::new(Mutex::new(role)),
}
}
}
impl<T> Service for JobRoleAdapter<T>
where
T: JobRole,
{
fn call(&self, ctx: TaskContext) -> BoxTaskFuture {
let role = self.role.clone();
let job_context = JobContext::new(ctx);
Box::pin(async move {
let mut role = role.lock().await;
run_job_lifecycle(&mut *role, &job_context).await
})
}
}
async fn run_job_lifecycle<T>(role: &mut T, ctx: &JobContext) -> TaskResult
where
T: JobRole,
{
if let Err(error) = role.init(ctx).await {
return job_error_to_task_result(error);
}
if let Err(error) = role.run(ctx).await {
return job_error_to_task_result(error);
}
if let Err(error) = role.complete(ctx).await {
return job_error_to_task_result(error);
}
if ctx.is_cancelled() {
TaskResult::Cancelled
} else {
TaskResult::Succeeded
}
}
fn job_error_to_task_result(error: JobError) -> TaskResult {
TaskResult::Failed(error.into_task_failure())
}