use crate::app::AppContext;
use crate::error::{Result, TidewayError};
use crate::traits::job::JobData;
use futures::future::BoxFuture;
use std::collections::HashMap;
use std::sync::Arc;
type JobHandler =
Arc<dyn Fn(JobData, Arc<AppContext>) -> BoxFuture<'static, Result<()>> + Send + Sync>;
#[derive(Clone)]
pub struct JobRegistry {
handlers: Arc<tokio::sync::RwLock<HashMap<String, JobHandler>>>,
}
impl JobRegistry {
pub fn new() -> Self {
Self {
handlers: Arc::new(tokio::sync::RwLock::new(HashMap::new())),
}
}
pub async fn register<F>(&self, job_type: &str, handler: F)
where
F: Fn(JobData, Arc<AppContext>) -> BoxFuture<'static, Result<()>> + Send + Sync + 'static,
{
let handler: JobHandler = Arc::new(handler);
let mut handlers = self.handlers.write().await;
handlers.insert(job_type.to_string(), handler);
}
pub async fn execute(&self, data: JobData, ctx: Arc<AppContext>) -> Result<()> {
let handlers = self.handlers.read().await;
let handler = handlers.get(&data.job_type).ok_or_else(|| {
TidewayError::internal(format!(
"No handler registered for job type: {}",
data.job_type
))
})?;
handler(data, ctx).await
}
pub async fn is_registered(&self, job_type: &str) -> bool {
let handlers = self.handlers.read().await;
handlers.contains_key(job_type)
}
pub async fn registered_types(&self) -> Vec<String> {
let handlers = self.handlers.read().await;
handlers.keys().cloned().collect()
}
}
impl Default for JobRegistry {
fn default() -> Self {
Self::new()
}
}