50 lines
2.8 KiB
Python
50 lines
2.8 KiB
Python
#!/usr/bin/env python3
|
|
"""Schedule bounded failure review alongside the owning module's business."""
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
from datetime import datetime, timezone
|
|
|
|
from failure_reconciliation import ROOT, synchronize, write, read
|
|
from scheduler_progress import cooling_ids, retry_details
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--module")
|
|
options = parser.parse_args()
|
|
ledger = synchronize()
|
|
rows = [row for row in ledger["records"].values() if row["status"] == "pending"
|
|
and (options.module is None or options.module in row["modules"])]
|
|
for row in rows:
|
|
owner = options.module or next((module for module in row["modules"] if module != "Shared"), "Web")
|
|
row["queueModule"] = owner
|
|
row["queueId"] = f"failure:{owner}:{row['key']}"
|
|
cooling = cooling_ids(candidates={row["queueId"] for row in rows})
|
|
deferred = {row["queueId"] for row in rows if row["queueId"] in cooling}
|
|
pending = [row for row in rows if row["queueId"] not in cooling]
|
|
output = ROOT / "docs/current/module-batch-manifest.json"
|
|
if not pending:
|
|
payload = {"schema": "freecad-web-module-business-batch/v1", "status": "no_ready_batch", "records": [],
|
|
"strategy": "module-business-first-deferred-validation", **retry_details(deferred)}
|
|
else:
|
|
pending.sort(key=lambda row: (row["queueModule"], row["legacyValidation"], row["category"], row["key"]))
|
|
module = pending[0]["queueModule"]
|
|
selected = [row for row in pending if row["queueModule"] == module][:4]
|
|
ids = [row["queueId"] for row in selected]
|
|
identity = "|".join([module, "failure-reconciliation", "failure-reconciliation", *ids])
|
|
payload = {"schema": "freecad-web-module-business-batch/v1", "status": "ready",
|
|
"strategy": "module-business-first-deferred-validation", "taskId": read(ROOT / "docs/current/task-state.json").get("active_task"),
|
|
"batchId": hashlib.sha256(identity.encode()).hexdigest()[:24], "minimumRecords": 1, "singletonFallback": len(ids) == 1,
|
|
"selected": {"module": module, "tier": "failure-reconciliation", "family": "failure-reconciliation", "recordCount": len(ids)},
|
|
"records": [[row["queueId"], row["category"], "pending", "tools/failure_reconciliation.py", 1] for row in selected],
|
|
"failureKeys": [row["key"] for row in selected], "queue": []}
|
|
payload["generatedAt"] = datetime.now(timezone.utc).isoformat()
|
|
write(output, payload)
|
|
print(json.dumps({"status": payload["status"], "selected": payload.get("selected"), "pendingFailures": len(rows)}, ensure_ascii=False))
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|