Skip to main content

apalis_core/worker/
event.rs

1//! Event definitions and utility types for worker events
2//!
3//! The `Event` enum defines various events that can occur during the lifecycle of a worker, such as starting, stopping, idling, and encountering errors.
4
5use std::{
6    any::Any,
7    fmt,
8    sync::{Arc, RwLock},
9};
10
11use crate::{error::BoxDynError, worker::context::WorkerContext};
12
13/// An event handler for a worker
14pub type EventHandlerBuilder =
15    Arc<RwLock<Option<Box<dyn Fn(&WorkerContext, &Event) + Send + Sync>>>>;
16
17/// Type alias for an event listener function wrapped in an `Arc`
18pub type EventListener = Arc<RawEventListener>;
19
20/// Event listening type
21pub(crate) type RawEventListener = Box<dyn Fn(&WorkerContext, &Event) + Send + Sync>;
22
23/// Events emitted by a worker
24#[non_exhaustive]
25pub enum Event {
26    /// Worker started
27    Start,
28    /// Worker did a heartbeat
29    HeartBeat,
30    /// A custom event
31    Custom(Box<dyn Any + 'static + Send + Sync>),
32    /// A result of processing
33    Success(Box<dyn Any + 'static + Send + Sync>),
34    /// Error encountered during processing, would not stop the worker, but would be logged and sent to the event handler
35    Error(Arc<BoxDynError>),
36    /// Worker stopped
37    Stop,
38    /// Worker exited, no further processing
39    Exit,
40}
41
42impl std::fmt::Debug for Event {
43    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44        match self {
45            Self::Start => f.write_str("Start"),
46            Self::HeartBeat => f.write_str("HeartBeat"),
47            Self::Custom(_) => f.write_str("Custom(..)"),
48            Self::Success(_) => f.write_str("Success(..)"),
49            Self::Error(error) => f.debug_tuple("Error").field(error).finish(),
50            Self::Stop => f.write_str("Stop"),
51            Self::Exit => f.write_str("Exit"),
52        }
53    }
54}
55
56impl fmt::Display for Event {
57    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58        let event_description = match &self {
59            Self::Start => "worker started".to_owned(),
60            Self::Custom(_) => "custom event".to_owned(),
61            Self::Error(err) => format!("worker encountered an error: {err}"),
62            Self::Stop => "worker stopped".to_owned(),
63            Self::HeartBeat => "worker heartbeat".to_owned(),
64            Self::Success(_) => "worker completed task successfully".to_owned(),
65            Self::Exit => "worker exited".to_owned(),
66        };
67
68        write!(f, "{event_description}")
69    }
70}
71
72impl Event {
73    /// If the event is an error, return the error
74    #[must_use]
75    pub fn as_error(&self) -> Option<Arc<BoxDynError>> {
76        match self {
77            Self::Error(err) => Some(err.clone()),
78            _ => None,
79        }
80    }
81
82    /// Create a custom event
83    #[must_use]
84    pub fn custom<T: 'static + Send + Sync>(data: T) -> Self {
85        Self::Custom(Box::new(data))
86    }
87}