"""List (and optionally clean) ECDS jobs for this account, to manage the per-user queued-request limit. Usage: python3 scripts/ecds_jobs.py list python3 scripts/ecds_jobs.py clean-rejected # delete only failed/rejected/dismissed """ import json import os import sys import datapi ECDS_URL = "https://ecds.ecmwf.int/api" def _get_key(): k = os.environ.get("CDSAPI_KEY") if k: return k rc = os.environ.get("CDSAPI_RC", os.path.expanduser("~/.cdsapirc")) if os.path.exists(rc): for line in open(rc): if line.strip().startswith("key"): return line.split(":", 1)[1].strip() return None mode = sys.argv[1] if len(sys.argv) > 1 else "list" c = datapi.ApiClient(url=ECDS_URL, key=_get_key()) # paginate the FULL job history and collect ids ids = [] page = c.get_jobs() while page is not None: ids.extend(list(page.request_ids)) try: page = page.next except Exception: page = None print(f"{len(ids)} job(s) across all pages", flush=True) rows = [] for jid in ids: r = c.get_remote(jid) try: st = r.status except Exception as e: st = f"?({type(e).__name__})" j = {} try: j = r.json except Exception: pass coll = j.get("processID") created = j.get("created") rows.append({"id": jid, "status": st, "process": coll, "created": created}) print(f" {jid} {st:12} {coll} {created}", flush=True) if (mode == "clean-rejected" and coll == "s2s-reforecasts" and st in ("failed", "rejected", "dismissed", "deleted")): try: r.delete() print(" -> deleted", flush=True) except Exception as e: print(f" -> delete error: {e}", flush=True) active = [x for x in rows if x["status"] in ("accepted", "running")] print(f"\nactive (accepted/running): {len(active)}", flush=True) print(json.dumps(rows, indent=2, default=str)[:2000], flush=True)