1use crate::{ErrorCode, history::Journal, state::SignalPaths};
3use serde_json::json;
4#[derive(Clone)]
5pub struct Request {
6 pub run_id: String,
7 pub request_id: String,
8 pub action: String,
9 pub source: String,
10}
11pub fn request_id() -> String {
12 std::env::var("ACTL_FLOW_REQUEST_ID")
13 .ok()
14 .filter(|v| crate::history::valid_id(v))
15 .unwrap_or_else(crate::snapshot::new_snapshot_id)
16}
17pub fn source() -> &'static str {
18 match std::env::var("ACTL_FLOW_REQUEST_SOURCE").as_deref() {
19 Ok("signal_control") => "signal_control",
20 Err(std::env::VarError::NotPresent) => "cli",
21 _ => "unknown",
22 }
23}
24impl Request {
25 pub fn new(run_id: &str, action: &str) -> Self {
26 Self {
27 run_id: run_id.into(),
28 request_id: request_id(),
29 action: action.into(),
30 source: source().into(),
31 }
32 }
33 pub fn record(&self, stage: &str, error: Option<ErrorCode>) {
34 let root = SignalPaths::default().dir;
35 let call = format!("control-{}", crate::snapshot::new_snapshot_id());
36 let Ok(mut journal) = Journal::open(&root, &call, Some(self.run_id.clone())) else {
37 return;
38 };
39 journal.record(
40 "call_started",
41 json!({"command":"flow-control","version":env!("CARGO_PKG_VERSION")}),
42 );
43 journal.record("control_request", json!({"run_id":self.run_id,"request_id":self.request_id,
44 "action":self.action,"source":self.source,"source_verified":false,"stage":stage,"error_code":error}));
45 journal.record(
46 "call_finished",
47 json!({"phase":if error.is_some(){"error"}else{"done"},"error_code":error}),
48 );
49 }
50}