Skip to main content

af_workflow/
recorder.rs

1//! Infra-agnostic workflow run and step persistence seam.
2
3use 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    /// Record routine negative evidence without materializing a full run.
54    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}