169 lines
5.6 KiB
Python
169 lines
5.6 KiB
Python
"""
|
|
run_orchestration.py
|
|
|
|
Small CLI for the minimal SQLite-backed orchestration layer.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
from pathlib import Path
|
|
import sys
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
SRC_DIR = REPO_ROOT / "src"
|
|
if str(SRC_DIR) not in sys.path:
|
|
sys.path.insert(0, str(SRC_DIR))
|
|
|
|
from renunney.orchestration import (
|
|
collate_track1_figure1,
|
|
expand_track1_figure1_manifest,
|
|
initialize_registry,
|
|
list_jobs,
|
|
run_one_job,
|
|
run_worker_loop,
|
|
submit_job_manifest,
|
|
submit_track1_figure1_jobs,
|
|
)
|
|
|
|
|
|
def save_payload(payload: dict, path: str | Path) -> None:
|
|
out = Path(path)
|
|
out.parent.mkdir(parents=True, exist_ok=True)
|
|
out.write_text(json.dumps(payload, indent=2, sort_keys=True) + "\n", encoding="utf-8")
|
|
|
|
|
|
def build_parser() -> argparse.ArgumentParser:
|
|
parser = argparse.ArgumentParser(description="Minimal orchestration CLI for cost-of-substitution sweeps.")
|
|
subparsers = parser.add_subparsers(dest="command", required=True)
|
|
|
|
init_db = subparsers.add_parser("init-db")
|
|
init_db.add_argument("--db", required=True)
|
|
|
|
submit = subparsers.add_parser("submit")
|
|
submit.add_argument("--db", required=True)
|
|
submit.add_argument("--manifest", required=True)
|
|
|
|
submit_fig1 = subparsers.add_parser("submit-figure1")
|
|
submit_fig1.add_argument("--db", required=True)
|
|
submit_fig1.add_argument("--config", required=True)
|
|
submit_fig1.add_argument("--job-prefix", required=True)
|
|
submit_fig1.add_argument("--priority", type=int, default=0)
|
|
submit_fig1.add_argument("--created-by", default="codex")
|
|
submit_fig1.add_argument("--result-prefix", default="results/track1/figure1")
|
|
|
|
list_cmd = subparsers.add_parser("list")
|
|
list_cmd.add_argument("--db", required=True)
|
|
|
|
run_one = subparsers.add_parser("run-one")
|
|
run_one.add_argument("--db", required=True)
|
|
run_one.add_argument("--result-root", required=True)
|
|
run_one.add_argument("--worker-backend", default="python-track1")
|
|
run_one.add_argument("--worker-host", default=None)
|
|
run_one.add_argument("--scratch-root", default=None)
|
|
|
|
run_loop = subparsers.add_parser("run-loop")
|
|
run_loop.add_argument("--db", required=True)
|
|
run_loop.add_argument("--result-root", required=True)
|
|
run_loop.add_argument("--worker-backend", default="python-track1")
|
|
run_loop.add_argument("--worker-host", default=None)
|
|
run_loop.add_argument("--scratch-root", default=None)
|
|
run_loop.add_argument("--max-jobs", type=int, default=None)
|
|
|
|
collate = subparsers.add_parser("collate-figure1")
|
|
collate.add_argument("--db", required=True)
|
|
collate.add_argument("--output", default=None)
|
|
|
|
return parser
|
|
|
|
|
|
def main() -> int:
|
|
parser = build_parser()
|
|
args = parser.parse_args()
|
|
|
|
if args.command == "init-db":
|
|
initialize_registry(args.db)
|
|
print(json.dumps({"db": str(Path(args.db)), "status": "initialized"}, indent=2, sort_keys=True))
|
|
return 0
|
|
|
|
if args.command == "submit":
|
|
manifest = json.loads(Path(args.manifest).read_text(encoding="utf-8"))
|
|
job_id = submit_job_manifest(args.db, manifest)
|
|
print(json.dumps({"db": str(Path(args.db)), "job_id": job_id, "status": "submitted"}, indent=2, sort_keys=True))
|
|
return 0
|
|
|
|
if args.command == "submit-figure1":
|
|
config = json.loads(Path(args.config).read_text(encoding="utf-8"))
|
|
manifests = expand_track1_figure1_manifest(
|
|
base_job_id_prefix=args.job_prefix,
|
|
config=config,
|
|
priority=args.priority,
|
|
created_by=args.created_by,
|
|
result_prefix=args.result_prefix,
|
|
)
|
|
job_ids = submit_track1_figure1_jobs(
|
|
db_path=args.db,
|
|
base_job_id_prefix=args.job_prefix,
|
|
config=config,
|
|
priority=args.priority,
|
|
created_by=args.created_by,
|
|
result_prefix=args.result_prefix,
|
|
)
|
|
print(
|
|
json.dumps(
|
|
{
|
|
"db": str(Path(args.db)),
|
|
"job_count": len(job_ids),
|
|
"job_ids": job_ids,
|
|
"status": "submitted",
|
|
"preview": manifests,
|
|
},
|
|
indent=2,
|
|
sort_keys=True,
|
|
)
|
|
)
|
|
return 0
|
|
|
|
if args.command == "list":
|
|
print(json.dumps(list_jobs(args.db), indent=2, sort_keys=True))
|
|
return 0
|
|
|
|
if args.command == "run-one":
|
|
result = run_one_job(
|
|
db_path=args.db,
|
|
result_root=args.result_root,
|
|
worker_backend=args.worker_backend,
|
|
worker_host=args.worker_host,
|
|
scratch_root=args.scratch_root,
|
|
cwd=REPO_ROOT,
|
|
)
|
|
print(json.dumps(result, indent=2, sort_keys=True))
|
|
return 0 if result is None or result["status"] == "succeeded" else 1
|
|
|
|
if args.command == "run-loop":
|
|
payload = run_worker_loop(
|
|
db_path=args.db,
|
|
result_root=args.result_root,
|
|
worker_backend=args.worker_backend,
|
|
worker_host=args.worker_host,
|
|
scratch_root=args.scratch_root,
|
|
cwd=REPO_ROOT,
|
|
max_jobs=args.max_jobs,
|
|
)
|
|
print(json.dumps(payload, indent=2, sort_keys=True))
|
|
return 0 if payload["failed_jobs"] == 0 else 1
|
|
|
|
if args.command == "collate-figure1":
|
|
payload = collate_track1_figure1(args.db)
|
|
if args.output:
|
|
save_payload(payload, args.output)
|
|
print(json.dumps(payload, indent=2, sort_keys=True))
|
|
return 0
|
|
|
|
raise ValueError(args.command)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|