1use super::log::{EventKind, EventLog};
11
12pub trait EventEmitter: Send + Sync {
17 fn emit(&self, kind: EventKind) -> u64;
19}
20
21impl EventEmitter for EventLog {
23 fn emit(&self, kind: EventKind) -> u64 {
24 EventLog::emit(self, kind)
25 }
26}
27
28#[derive(Debug, Clone, Default)]
30pub struct NoopEmitter;
31
32impl NoopEmitter {
33 pub fn new() -> Self {
35 Self
36 }
37}
38
39impl EventEmitter for NoopEmitter {
40 fn emit(&self, _kind: EventKind) -> u64 {
41 0 }
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48 use serde_json::json;
49 use std::sync::Arc;
50
51 const TEST_VERSION: &str = env!("CARGO_PKG_VERSION");
53
54 #[test]
59 fn event_emitter_trait_is_object_safe() {
60 fn accepts_emitter(_: &dyn EventEmitter) {}
62
63 let log = EventLog::new();
64 accepts_emitter(&log);
65
66 let noop = NoopEmitter::new();
67 accepts_emitter(&noop);
68 }
69
70 #[test]
71 fn event_emitter_trait_works_with_arc() {
72 let emitter: Arc<dyn EventEmitter> = Arc::new(EventLog::new());
74 let id = emitter.emit(EventKind::WorkflowStarted {
75 task_count: 1,
76 generation_id: "test".to_string(),
77 workflow_hash: "hash".to_string(),
78 nika_version: TEST_VERSION.to_string(),
79 });
80 assert_eq!(id, 0); }
82
83 #[test]
88 fn eventlog_implements_emitter() {
89 let log = EventLog::new();
90 let emitter: &dyn EventEmitter = &log;
91
92 let id = emitter.emit(EventKind::TaskStarted {
93 task_id: Arc::from("test_task"),
94 verb: "infer".into(),
95 inputs: json!({}),
96 });
97
98 assert_eq!(id, 0);
99 assert_eq!(log.len(), 1);
100 }
101
102 #[test]
103 fn eventlog_emitter_returns_monotonic_ids() {
104 let log = EventLog::new();
105 let emitter: &dyn EventEmitter = &log;
106
107 let id1 = emitter.emit(EventKind::WorkflowStarted {
108 task_count: 2,
109 generation_id: "gen1".to_string(),
110 workflow_hash: "hash1".to_string(),
111 nika_version: TEST_VERSION.to_string(),
112 });
113 let id2 = emitter.emit(EventKind::TaskStarted {
114 task_id: Arc::from("task1"),
115 verb: "infer".into(),
116 inputs: json!({}),
117 });
118 let id3 = emitter.emit(EventKind::TaskCompleted {
119 task_id: Arc::from("task1"),
120 output: Arc::new(json!("done")),
121 duration_ms: 100,
122 });
123
124 assert_eq!(id1, 0);
125 assert_eq!(id2, 1);
126 assert_eq!(id3, 2);
127 }
128
129 #[test]
134 fn noop_emitter_always_returns_zero() {
135 let noop = NoopEmitter::new();
136
137 let id1 = noop.emit(EventKind::WorkflowStarted {
138 task_count: 5,
139 generation_id: "gen".to_string(),
140 workflow_hash: "hash".to_string(),
141 nika_version: TEST_VERSION.to_string(),
142 });
143 let id2 = noop.emit(EventKind::TaskStarted {
144 task_id: Arc::from("task"),
145 verb: "infer".into(),
146 inputs: json!({}),
147 });
148 let id3 = noop.emit(EventKind::WorkflowCompleted {
149 final_output: Arc::new(json!("output")),
150 total_duration_ms: 1000,
151 });
152
153 assert_eq!(id1, 0);
154 assert_eq!(id2, 0);
155 assert_eq!(id3, 0);
156 }
157
158 #[test]
159 fn noop_emitter_is_clone() {
160 let noop = NoopEmitter::new();
161 let _cloned = noop.clone();
162 }
163
164 #[test]
165 fn noop_emitter_is_default() {
166 let noop = NoopEmitter;
167 assert_eq!(
168 noop.emit(EventKind::WorkflowStarted {
169 task_count: 1,
170 generation_id: "".to_string(),
171 workflow_hash: "".to_string(),
172 nika_version: TEST_VERSION.to_string(),
173 }),
174 0
175 );
176 }
177
178 #[test]
179 fn noop_emitter_is_send_sync() {
180 fn assert_send_sync<T: Send + Sync>() {}
181 assert_send_sync::<NoopEmitter>();
182 }
183
184 fn emit_workflow_started<E: EventEmitter>(emitter: &E, task_count: usize) -> u64 {
189 emitter.emit(EventKind::WorkflowStarted {
190 task_count,
191 generation_id: "test-gen".to_string(),
192 workflow_hash: "test-hash".to_string(),
193 nika_version: TEST_VERSION.to_string(),
194 })
195 }
196
197 #[test]
198 fn generic_function_works_with_eventlog() {
199 let log = EventLog::new();
200 let id = emit_workflow_started(&log, 3);
201 assert_eq!(id, 0);
202 assert_eq!(log.len(), 1);
203 }
204
205 #[test]
206 fn generic_function_works_with_noop() {
207 let noop = NoopEmitter::new();
208 let id = emit_workflow_started(&noop, 3);
209 assert_eq!(id, 0);
210 }
211}