hyperclock/
events.rs

1//! Defines all public event types broadcast by the Hyperclock engine.
2//!
3//! This module acts as the public API for the engine's event system. Listeners
4//! subscribe to these specific, strongly-typed events to perform their work.
5
6use crate::common::{ListenerId, PhaseId, TaskId};
7use crate::time::TickEvent;
8use chrono::{NaiveDate, NaiveTime};
9use std::any::Any;
10use std::sync::Arc;
11use tokio::time::Instant;
12
13/// The primary event that drives the engine's internal cycle.
14///
15/// It is fired for each configured phase within a single master `TickEvent`.
16#[derive(Debug, Clone)]
17pub struct PhaseEvent {
18    /// The ID of the phase that is currently active.
19    pub phase: PhaseId,
20    /// A shared pointer to the master tick this phase belongs to.
21    pub tick: Arc<TickEvent>,
22}
23
24/// Events related to the lifecycle and state of the engine itself.
25#[derive(Debug, Clone)]
26pub enum SystemEvent {
27    /// Fired once when the engine's `run` loop begins.
28    EngineStarted { timestamp: Instant },
29    /// Fired once when the engine's `run` loop is about to exit.
30    EngineShutdown,
31    /// Fired when a new listener is successfully added to the engine.
32    ListenerAdded { id: ListenerId },
33    /// Fired when a listener is removed from the engine.
34    ListenerRemoved { id: ListenerId },
35}
36
37/// High-level, human-meaningful calendar and time-of-day events.
38#[derive(Debug, Clone)]
39pub enum GongEvent {
40    /// Fired once when the calendar date changes.
41    DateChanged { new_date: NaiveDate },
42    /// Fired at specific, named times of the day.
43    TimeOfDay(TimeOfDay),
44    /// Fired at specific, named workday milestones.
45    WorkdayMilestone(WorkdayMilestone),
46    /// Fired on a specific holiday defined in the `GongConfig`.
47    Holiday { name: String, date: NaiveDate },
48}
49
50/// A named time of day for `GongEvent`s.
51#[derive(Debug, Clone, Copy, PartialEq, Eq)]
52pub enum TimeOfDay {
53    Noon,
54    Midnight,
55}
56
57/// A named workday milestone for `GongEvent`s.
58#[derive(Debug, Clone, Copy, PartialEq, Eq)]
59pub struct WorkdayMilestone {
60    pub label: &'static str,
61    pub time: NaiveTime,
62}
63
64/// Events related to the lifecycle of scheduled, repeating tasks.
65#[derive(Debug, Clone)]
66pub enum TaskEvent {
67    /// Fired when a new task is successfully registered with the engine.
68    TaskScheduled { id: TaskId },
69    /// Fired each time a scheduled task's logic is executed.
70    TaskFired {
71        /// The ID of the listener that triggered this event (e.g., an IntervalWatcher).
72        listener_id: ListenerId,
73        tick: Arc<TickEvent>,
74    },
75    /// Fired when a finite task has completed all its runs.
76    TaskCompleted { id: TaskId },
77}
78
79/// Events related to the `LifecycleLoop` automation component.
80#[derive(Debug, Clone)]
81pub enum AutomationEvent {
82    /// Fired when a new lifecycle loop is started.
83    LifecycleStarted { id: TaskId },
84    /// Fired each time the lifecycle advances to a new step.
85    LifecycleStepAdvanced { id: TaskId, step_index: usize },
86    /// Fired when a finite lifecycle has completed all its steps and repetitions.
87    LifecycleCompleted { id: TaskId },
88    /// Fired when a repeating lifecycle finishes its last step and starts over.
89    LifecycleLooped { id: TaskId },
90}
91
92/// Fired when a registered condition is met.
93#[derive(Debug, Clone)]
94pub struct ConditionalEvent {
95    pub condition_id: ListenerId,
96    pub timestamp: Instant,
97}
98
99/// A generic container for custom, application-defined events.
100#[derive(Clone)]
101pub struct UserEvent {
102    /// The name or type of the event, used for filtering.
103    pub name: String,
104    /// The type-erased data payload. The receiver is responsible for
105    /// downcasting this to the expected concrete type.
106    pub payload: Arc<dyn Any + Send + Sync>,
107}
108
109impl std::fmt::Debug for UserEvent {
110    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
111        f.debug_struct("UserEvent")
112            .field("name", &self.name)
113            .field("payload", &"...")
114            .finish()
115    }
116}