Artifex/graph/inspection.py

42 lines
1.8 KiB
Python
Raw Normal View History

2026-08-15 17:10:50 +07:00
from __future__ import annotations
from graph.models import GraphRun
def graph_run_inspection(graph_run: GraphRun) -> dict[str, object]:
spec = graph_run.execution_graph_version.graph_spec
node_runs = {
node.node_id: node
for node in graph_run.node_runs.order_by("node_id", "-visit_index")
}
nodes = []
for node_id, node_spec in spec.get("nodes", {}).items():
run = node_runs.get(node_id)
nodes.append(
{
"id": node_id,
"type": node_spec.get("type"),
"status": run.status if run else "PENDING",
"visit_index": run.visit_index if run else 0,
"duration_ms": (run.telemetry or {}).get("duration_ms") if run else None,
"failure": run.failure_evidence if run else {},
"metadata": node_spec.get("metadata", {}),
}
)
return {
"graph": graph_run.execution_graph_version.graph.name,
"version": graph_run.execution_graph_version.version,
"version_status": graph_run.execution_graph_version.status,
"version_promoted_at": graph_run.execution_graph_version.promoted_at,
2026-08-15 17:10:50 +07:00
"status": graph_run.status,
"current_node": graph_run.current_node,
"final_failure_reason": graph_run.metadata.get("final_failure_reason") or graph_run.failure_reason or None,
"historical_failures": graph_run.metadata.get("historical_failures", []),
2026-08-15 17:10:50 +07:00
"nodes": nodes,
"edges": spec.get("edges", []),
"edge_traversals": list(
graph_run.edge_traversals.order_by("created_at").values("source_node", "target_node", "condition", "result", "metadata", "created_at")
),
"failures": list(graph_run.node_runs.exclude(failure_evidence={}).values("node_id", "failure_evidence")),
}