1use std::sync::Arc;
9
10use async_trait::async_trait;
11use serde_json::Value;
12
13use crate::event::Event;
14use crate::recorder::{noop_recorder, RunRecorder};
15use crate::result::StepResult;
16use crate::state::State;
17
18pub struct WorkflowContext {
25 pub branch_id: String,
26 pub config: Value,
27 pub instance_metadata: Value,
28 pub state: Arc<dyn State>,
29 pub recorder: Arc<dyn RunRecorder>,
30 pub trigger_kind: String,
31}
32
33impl WorkflowContext {
34 pub fn new(branch_id: impl Into<String>, state: Arc<dyn State>) -> Self {
35 Self {
36 branch_id: branch_id.into(),
37 config: Value::Object(Default::default()),
38 instance_metadata: Value::Object(Default::default()),
39 state,
40 recorder: noop_recorder(),
41 trigger_kind: "event".into(),
42 }
43 }
44
45 pub fn with_config(mut self, config: Value) -> Self {
46 self.config = config;
47 self
48 }
49
50 pub fn with_recorder(mut self, recorder: Arc<dyn RunRecorder>) -> Self {
51 self.recorder = recorder;
52 self
53 }
54
55 pub fn with_trigger_kind(mut self, trigger_kind: impl Into<String>) -> Self {
56 self.trigger_kind = trigger_kind.into();
57 self
58 }
59
60 pub fn scoped(&self, key: &str) -> String {
62 format!("{}.{}", self.branch_id, key)
63 }
64}
65
66#[async_trait]
68pub trait StepNode: Send + Sync {
69 fn produces_fan_out(&self) -> bool {
71 false
72 }
73
74 async fn process(&self, event: &Event, ctx: &WorkflowContext) -> StepResult;
75}