feat(pipeline): add stop and prune commands to pipeline engine and CLI
- Add stop_pipeline and prune_pipelines to bin/pipeline_engine.py - Support prefix matching and custom cancellation reason - Wire 'super pipeline stop <run_id>' and 'super pipeline prune [--max-age H]' into bin/super-cli.py
This commit is contained in:
+54
-1
@@ -158,9 +158,61 @@ def fail_pipeline(run_id, reason="failed"):
|
||||
save_pipelines(data)
|
||||
|
||||
|
||||
def stop_pipeline(run_id, reason="cancelled_by_operator"):
|
||||
"""Manually cancel or stop an active pipeline run."""
|
||||
data = load_pipelines()
|
||||
# Support prefix matching
|
||||
target_key = None
|
||||
for k in data.keys():
|
||||
if k == run_id or k.startswith(run_id):
|
||||
target_key = k
|
||||
break
|
||||
|
||||
if not target_key:
|
||||
return None
|
||||
|
||||
entry = data[target_key]
|
||||
entry["status"] = "canceled"
|
||||
entry["canceled_at"] = utcnow()
|
||||
entry["updated_at"] = utcnow()
|
||||
entry["cancel_reason"] = reason
|
||||
save_pipelines(data)
|
||||
return entry
|
||||
|
||||
|
||||
def prune_pipelines(max_age_hours=24):
|
||||
"""Mark stale running pipeline runs older than max_age_hours as timed_out."""
|
||||
data = load_pipelines()
|
||||
now = datetime.now(timezone.utc)
|
||||
pruned = []
|
||||
for k, v in data.items():
|
||||
if v.get("status") == "running":
|
||||
created_str = v.get("created_at")
|
||||
if created_str:
|
||||
try:
|
||||
dt = datetime.fromisoformat(created_str.replace("Z", "+00:00"))
|
||||
diff_h = (now - dt).total_seconds() / 3600.0
|
||||
if diff_h >= max_age_hours:
|
||||
v["status"] = "timed_out"
|
||||
v["completed_at"] = utcnow()
|
||||
v["updated_at"] = utcnow()
|
||||
v["timeout_reason"] = f"stale_exceeded_{max_age_hours}h"
|
||||
pruned.append(k)
|
||||
except Exception:
|
||||
pass
|
||||
if pruned:
|
||||
save_pipelines(data)
|
||||
return pruned
|
||||
|
||||
|
||||
def get_pipeline(run_id):
|
||||
data = load_pipelines()
|
||||
return data.get(run_id)
|
||||
if run_id in data:
|
||||
return data[run_id]
|
||||
for k, v in data.items():
|
||||
if k.startswith(run_id):
|
||||
return v
|
||||
return None
|
||||
|
||||
|
||||
def list_active_pipelines():
|
||||
@@ -176,3 +228,4 @@ def list_pipeline_history(limit=20):
|
||||
reverse=True,
|
||||
)
|
||||
return sorted_runs[:limit]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user