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