use serde_json::{json, Value};
use octl_core::{append_and_apply_unlocked, NodeId, RunId, RunLock, RunPaths, Status};
use crate::error::CliError;
use crate::supervise::state::SupervisorState;
pub fn process_node_report(
parent_paths: &RunPaths,
parent_node_id: &str,
child_run_id: &str,
child_node_id: &str,
report_seq: u64,
_report: &Value,
state: &mut SupervisorState,
) -> Result<Option<()>, CliError> {
let parent_nid = NodeId::parse_str(parent_node_id)
.map_err(|e| CliError::user("invalid_id", e.to_string()))?;
RunId::parse_str(child_run_id).map_err(|e| CliError::user("invalid_id", e.to_string()))?;
NodeId::parse_str(child_node_id).map_err(|e| CliError::user("invalid_id", e.to_string()))?;
if let Some(prev) = state
.last_processed_report_seq_by_child
.get(child_run_id)
.copied()
{
if report_seq <= prev {
return Ok(None);
}
}
let guard = RunLock::acquire(&parent_paths.lock())
.map_err(|e| CliError::system("io_error", e.to_string()))?;
let lock = guard.witness();
append_and_apply_unlocked(
&lock,
parent_paths,
"supervisor.cursor_advanced",
Some(&parent_nid),
None,
json!({ "child_run_id": child_run_id, "report_seq": report_seq }),
)
.map_err(|e| CliError::system("io_error", e.to_string()))?;
drop(guard);
state
.last_processed_report_seq_by_child
.insert(child_run_id.to_string(), report_seq);
Ok(Some(()))
}
#[allow(dead_code)]
pub fn child_terminal_status_from_report(report: &Value) -> Status {
let cancelled = report
.get("cancelled")
.and_then(Value::as_bool)
.unwrap_or(false);
if cancelled {
return Status::Cancelled;
}
#[allow(clippy::match_same_arms)]
match report.get("success").and_then(Value::as_bool) {
Some(true) => Status::Done,
Some(false) => Status::Failed,
None => Status::Failed,
}
}