use std::any::Any;
use async_trait::async_trait;
use crate::context::Context;
use crate::task::Task;
#[async_trait]
pub trait Worker: Send + Sync + 'static {
type Task: Task;
async fn on_start(&self) -> anyhow::Result<()> {
Ok(())
}
async fn process(&self, task: &Self::Task, ctx: &Context) -> anyhow::Result<()>;
async fn on_stop(&self) -> anyhow::Result<()> {
Ok(())
}
}
#[async_trait]
pub trait DynWorker: Send + Sync + 'static {
async fn on_start(&self) -> anyhow::Result<()> {
Ok(())
}
async fn process(&self, payload: &(dyn Any + Send + Sync), ctx: &Context)
-> anyhow::Result<()>;
async fn on_stop(&self) -> anyhow::Result<()> {
Ok(())
}
}
pub(crate) struct Holder<W: Worker>(pub W);
#[async_trait]
impl<W: Worker> DynWorker for Holder<W> {
async fn on_start(&self) -> anyhow::Result<()> {
self.0.on_start().await
}
async fn process(
&self,
payload: &(dyn Any + Send + Sync),
ctx: &Context,
) -> anyhow::Result<()> {
let task = payload.downcast_ref::<W::Task>().ok_or_else(|| {
anyhow::anyhow!("payload is not {}", std::any::type_name::<W::Task>())
})?;
self.0.process(task, ctx).await
}
async fn on_stop(&self) -> anyhow::Result<()> {
self.0.on_stop().await
}
}
#[derive(Default)]
pub struct WorkerCfg {
pub(crate) label: Option<String>,
pub(crate) concurrency: Option<usize>,
}
impl WorkerCfg {
pub fn new() -> Self {
Self::default()
}
pub fn label(mut self, label: impl Into<String>) -> Self {
self.label = Some(label.into());
self
}
pub fn concurrency(mut self, n: usize) -> Self {
self.concurrency = Some(n);
self
}
}