pureflow_core/
lifecycle.rs1use crate::{Result, context::NodeContext};
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum LifecycleEventKind {
21 NodeScheduled,
23 NodeStarted,
25 NodeCompleted,
27 NodeFailed,
29 NodeCancelled,
31}
32
33#[derive(Debug, Clone, PartialEq, Eq)]
35pub struct LifecycleEvent {
36 kind: LifecycleEventKind,
37 context: NodeContext,
38}
39
40impl LifecycleEvent {
41 #[must_use]
43 pub const fn new(kind: LifecycleEventKind, context: NodeContext) -> Self {
44 Self { kind, context }
45 }
46
47 #[must_use]
49 pub const fn kind(&self) -> LifecycleEventKind {
50 self.kind
51 }
52
53 #[must_use]
55 pub const fn context(&self) -> &NodeContext {
56 &self.context
57 }
58}
59
60pub trait LifecycleHook: Sync {
62 fn observe(&self, event: &LifecycleEvent) -> Result<()>;
68}
69
70#[derive(Debug, Clone, Copy, Default)]
72pub struct NoopLifecycleHook;
73
74impl LifecycleHook for NoopLifecycleHook {
75 fn observe(&self, _event: &LifecycleEvent) -> Result<()> {
76 Ok(())
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83 use crate::context::ExecutionMetadata;
84 use pureflow_types::{ExecutionId, NodeId, WorkflowId};
85
86 fn execution_id(value: &str) -> ExecutionId {
87 ExecutionId::new(value).expect("valid execution id")
88 }
89
90 fn node_id(value: &str) -> NodeId {
91 NodeId::new(value).expect("valid node id")
92 }
93
94 fn workflow_id(value: &str) -> WorkflowId {
95 WorkflowId::new(value).expect("valid workflow id")
96 }
97
98 fn execution() -> ExecutionMetadata {
99 ExecutionMetadata::first_attempt(execution_id("run-1"))
100 }
101
102 #[test]
103 fn lifecycle_event_carries_kind_and_context() {
104 let context: NodeContext =
105 NodeContext::new(workflow_id("flow"), node_id("node"), execution());
106 let event: LifecycleEvent = LifecycleEvent::new(LifecycleEventKind::NodeStarted, context);
107
108 assert_eq!(event.kind(), LifecycleEventKind::NodeStarted);
109 assert_eq!(event.context().node_id().as_str(), "node");
110 }
111
112 #[test]
113 fn noop_lifecycle_hook_accepts_events() {
114 let context: NodeContext =
115 NodeContext::new(workflow_id("flow"), node_id("node"), execution());
116 let event: LifecycleEvent = LifecycleEvent::new(LifecycleEventKind::NodeCompleted, context);
117
118 NoopLifecycleHook
119 .observe(&event)
120 .expect("noop hook should accept lifecycle events");
121 }
122}