razeri_plugin_api/sinks/
stdout.rs1use std::sync::Arc;
7
8use async_trait::async_trait;
9
10use crate::builder::EventSinkRegistration;
11use crate::error::EventSinkError;
12use crate::event::{EventSink, RazeriEvent};
13
14pub struct StdoutSink;
16
17impl StdoutSink {
18 #[must_use]
20 pub fn new() -> Self {
21 Self
22 }
23}
24
25impl Default for StdoutSink {
26 fn default() -> Self {
27 Self::new()
28 }
29}
30
31#[async_trait]
32impl EventSink for StdoutSink {
33 fn name(&self) -> &'static str {
34 "stdout"
35 }
36
37 async fn on_event(&self, event: &RazeriEvent) -> Result<(), EventSinkError> {
38 let json = serde_json::to_string(event)
39 .map_err(|e| EventSinkError::SinkError(format!("serialization failed: {e}")))?;
40 eprintln!("{json}");
41 Ok(())
42 }
43
44 async fn flush(&self) -> Result<(), EventSinkError> {
45 Ok(())
46 }
47}
48
49inventory::submit! {
50 EventSinkRegistration::new("stdout", || Arc::new(StdoutSink::new()))
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56 use crate::event::{RazeriEvent, WorkflowContext};
57 use chrono::Utc;
58
59 fn test_workflow() -> WorkflowContext {
60 WorkflowContext::new("test-wf").unwrap()
61 }
62
63 #[tokio::test]
64 async fn stdout_sink_accepts_events() {
65 let sink = StdoutSink::new();
66 assert_eq!(sink.name(), "stdout");
67
68 let event = RazeriEvent::design_validated(
69 "test-stdout-1",
70 Utc::now(),
71 test_workflow(),
72 "test.yaml",
73 0,
74 0,
75 )
76 .unwrap();
77 let result = sink.on_event(&event).await;
78 assert!(result.is_ok());
79 }
80
81 #[tokio::test]
82 async fn stdout_sink_flush_is_noop() {
83 let sink = StdoutSink::new();
84 assert!(sink.flush().await.is_ok());
85 }
86}