1use crate::types::{GraphMutation, GraphSnapshot, NodeId, NodeSpec, RunId};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
6pub enum GraphEvent {
7 NodeAdded {
8 id: NodeId,
9 spec: NodeSpec,
10 ts: u64,
11 },
12 NodeReady {
13 id: NodeId,
14 ts: u64,
15 },
16 NodeStarted {
17 id: NodeId,
18 ts: u64,
19 },
20 NodeCompleted {
21 id: NodeId,
22 result: serde_json::Value,
23 ts: u64,
24 },
25 NodeFailed {
26 id: NodeId,
27 error: String,
28 ts: u64,
29 },
30 NodeAbandoned {
31 id: NodeId,
32 ts: u64,
33 },
34 EdgeAdded {
35 from: NodeId,
36 to: NodeId,
37 ts: u64,
38 },
39 EdgeRemoved {
40 from: NodeId,
41 to: NodeId,
42 ts: u64,
43 },
44 MutationApplied {
45 mutation: GraphMutation,
46 ts: u64,
47 },
48 MutationRejected {
49 reason: String,
50 ts: u64,
51 },
52 SnapshotTaken {
53 snapshot: GraphSnapshot,
54 ts: u64,
55 },
56 RunStarted {
57 run_id: RunId,
58 ts: u64,
59 },
60 RunCompleted {
61 run_id: RunId,
62 ts: u64,
63 },
64 RunFailed {
65 run_id: RunId,
66 error: String,
67 ts: u64,
68 },
69}
70
71impl GraphEvent {
72 pub fn ts(&self) -> u64 {
73 match self {
74 GraphEvent::NodeAdded { ts, .. } => *ts,
75 GraphEvent::NodeReady { ts, .. } => *ts,
76 GraphEvent::NodeStarted { ts, .. } => *ts,
77 GraphEvent::NodeCompleted { ts, .. } => *ts,
78 GraphEvent::NodeFailed { ts, .. } => *ts,
79 GraphEvent::NodeAbandoned { ts, .. } => *ts,
80 GraphEvent::EdgeAdded { ts, .. } => *ts,
81 GraphEvent::EdgeRemoved { ts, .. } => *ts,
82 GraphEvent::MutationApplied { ts, .. } => *ts,
83 GraphEvent::MutationRejected { ts, .. } => *ts,
84 GraphEvent::SnapshotTaken { ts, .. } => *ts,
85 GraphEvent::RunStarted { ts, .. } => *ts,
86 GraphEvent::RunCompleted { ts, .. } => *ts,
87 GraphEvent::RunFailed { ts, .. } => *ts,
88 }
89 }
90}
91
92pub fn now_ms() -> u64 {
94 std::time::SystemTime::now()
95 .duration_since(std::time::UNIX_EPOCH)
96 .unwrap_or_default()
97 .as_millis() as u64
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103 use crate::types::NodeId;
104
105 #[test]
106 fn graph_event_serializes() {
107 let id = NodeId::new();
108 let event = GraphEvent::NodeCompleted {
109 id: id.clone(),
110 result: serde_json::json!({"output": "done"}),
111 ts: now_ms(),
112 };
113 let json = serde_json::to_string(&event).unwrap();
114 let event2: GraphEvent = serde_json::from_str(&json).unwrap();
115 assert!(event2.ts() > 0);
116 }
117
118 #[test]
119 fn now_ms_is_reasonable() {
120 let ts = now_ms();
121 assert!(ts > 1_700_000_000_000); }
123}