1use std::sync::Arc;
4
5use async_trait::async_trait;
6use serde_json::Value;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum StepStatus {
10 Ok,
11 Skipped,
12 Error,
13}
14
15impl StepStatus {
16 pub fn as_str(self) -> &'static str {
17 match self {
18 Self::Ok => "ok",
19 Self::Skipped => "skipped",
20 Self::Error => "error",
21 }
22 }
23}
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub enum RunStatus {
27 Ok,
28 Skipped,
29 Error,
30}
31
32impl RunStatus {
33 pub fn as_str(self) -> &'static str {
34 match self {
35 Self::Ok => "ok",
36 Self::Skipped => "skipped",
37 Self::Error => "error",
38 }
39 }
40}
41
42#[async_trait]
43pub trait RunHandle: Send {
44 async fn record_step(
45 &mut self,
46 node_id: &str,
47 node_type: &str,
48 status: StepStatus,
49 exit_reason: Option<&str>,
50 detail: Value,
51 );
52
53 async fn mark_filtered(&mut self, node_id: &str, node_type: &str, reason: &str);
55
56 async fn end(self: Box<Self>, status: RunStatus, exit_reason: Option<&str>);
57}
58
59#[async_trait]
60pub trait RunRecorder: Send + Sync {
61 async fn start(&self, trigger_kind: &str, trigger: Value) -> Box<dyn RunHandle>;
62}
63
64pub struct NoopRecorder;
65
66#[async_trait]
67impl RunRecorder for NoopRecorder {
68 async fn start(&self, _trigger_kind: &str, _trigger: Value) -> Box<dyn RunHandle> {
69 Box::new(NoopHandle)
70 }
71}
72
73struct NoopHandle;
74
75#[async_trait]
76impl RunHandle for NoopHandle {
77 async fn record_step(&mut self, _: &str, _: &str, _: StepStatus, _: Option<&str>, _: Value) {}
78 async fn mark_filtered(&mut self, _: &str, _: &str, _: &str) {}
79 async fn end(self: Box<Self>, _: RunStatus, _: Option<&str>) {}
80}
81
82pub fn noop_recorder() -> Arc<dyn RunRecorder> {
83 Arc::new(NoopRecorder)
84}