Skip to main content

azoth_scheduler/
task_handler.rs

1//! Task handler trait and registry.
2
3use crate::error::{Result, SchedulerError};
4use chrono::{DateTime, Utc};
5use std::collections::HashMap;
6use std::sync::Arc;
7
8/// Context provided to task handlers during execution.
9#[derive(Debug, Clone)]
10pub struct TaskContext {
11    /// Unique identifier for the task.
12    pub task_id: String,
13    /// Unique identifier for this execution.
14    pub execution_id: String,
15    /// When this execution was scheduled to run.
16    pub scheduled_at: DateTime<Utc>,
17    /// Number of attempts (0 for first attempt).
18    pub execution_attempt: u32,
19}
20
21/// Event produced by a task handler.
22#[derive(Debug, Clone)]
23pub struct TaskEvent {
24    /// Type of event (used to route to event handlers).
25    pub event_type: String,
26    /// Serialized event payload.
27    pub payload: Vec<u8>,
28}
29
30/// Trait implemented by task handlers.
31///
32/// Task handlers execute scheduled tasks and produce events
33/// that are written to the canonical event log.
34pub trait TaskHandler: Send + Sync {
35    /// Returns the task type this handler processes.
36    fn task_type(&self) -> &str;
37
38    /// Execute the task with the given context and payload.
39    ///
40    /// Returns a `TaskEvent` that will be written to the canonical log.
41    /// The event will then be processed by registered event handlers.
42    fn execute(&self, ctx: &TaskContext, payload: &[u8]) -> Result<TaskEvent>;
43
44    /// Validate the task payload (optional).
45    ///
46    /// Called when scheduling a task to ensure the payload is valid.
47    /// Default implementation always succeeds.
48    fn validate(&self, _payload: &[u8]) -> Result<()> {
49        Ok(())
50    }
51}
52
53/// Registry of task handlers.
54#[derive(Clone)]
55pub struct TaskHandlerRegistry {
56    handlers: Arc<HashMap<String, Arc<dyn TaskHandler>>>,
57}
58
59impl TaskHandlerRegistry {
60    /// Create a new empty registry.
61    pub fn new() -> Self {
62        Self {
63            handlers: Arc::new(HashMap::new()),
64        }
65    }
66
67    /// Register a task handler.
68    pub fn register(&mut self, handler: Arc<dyn TaskHandler>) {
69        let task_type = handler.task_type().to_string();
70        Arc::make_mut(&mut self.handlers).insert(task_type, handler);
71    }
72
73    /// Get a handler by task type.
74    pub fn get(&self, task_type: &str) -> Result<Arc<dyn TaskHandler>> {
75        self.handlers
76            .get(task_type)
77            .cloned()
78            .ok_or_else(|| SchedulerError::HandlerNotFound(task_type.to_string()))
79    }
80
81    /// Check if a handler is registered for a task type.
82    pub fn has(&self, task_type: &str) -> bool {
83        self.handlers.contains_key(task_type)
84    }
85
86    /// Get all registered task types.
87    pub fn task_types(&self) -> Vec<String> {
88        self.handlers.keys().cloned().collect()
89    }
90}
91
92impl Default for TaskHandlerRegistry {
93    fn default() -> Self {
94        Self::new()
95    }
96}