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}