use crate::role::context::service::ServiceContext;
use crate::role::result::service::ServiceError;
use crate::role::traits::service::ServiceRole;
use crate::task::context::TaskContext;
use crate::task::factory::{BoxTaskFuture, Service, TaskResult};
use std::sync::Arc;
use tokio::sync::Mutex;
pub struct ServiceRoleAdapter<T> {
role: Arc<Mutex<T>>,
}
impl<T> ServiceRoleAdapter<T>
where
T: ServiceRole,
{
pub fn new(role: T) -> Self {
Self {
role: Arc::new(Mutex::new(role)),
}
}
}
impl<T> Service for ServiceRoleAdapter<T>
where
T: ServiceRole,
{
fn call(&self, ctx: TaskContext) -> BoxTaskFuture {
let role = self.role.clone();
let service_context = ServiceContext::new(ctx);
Box::pin(async move {
let mut role = role.lock().await;
run_service_lifecycle(&mut *role, &service_context).await
})
}
}
async fn run_service_lifecycle<T>(role: &mut T, ctx: &ServiceContext) -> TaskResult
where
T: ServiceRole,
{
if let Err(error) = role.init(ctx).await {
return service_error_to_task_result(error);
}
if let Err(error) = role.run(ctx).await {
return service_error_to_task_result(error);
}
if let Err(error) = role.shutdown(ctx).await {
return service_error_to_task_result(error);
}
if ctx.is_shutdown_requested() {
TaskResult::Cancelled
} else {
TaskResult::Succeeded
}
}
fn service_error_to_task_result(error: ServiceError) -> TaskResult {
TaskResult::Failed(error.into_task_failure())
}