Skip to main content

actl_core/
control_log.rs

1//! Independent control records never publish desktop feedback or grant permission.
2use 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}