feat: add isolated utility export modes

This commit is contained in:
Media
2026-08-12 18:48:03 -05:00
parent b934b69e5a
commit 7e6b916963
11 changed files with 1876 additions and 12 deletions
+55
View File
@@ -148,6 +148,12 @@ class ControllerService:
self.store,
on_event=self._queue_download_event,
)
try:
self.downloads.reconcile_export_artifacts()
except BaseException:
LOG.exception(
"utility export reconciliation failed; Controller startup continues"
)
# Cleanup is deliberately deferred until fresh Player evidence
# (or an explicit administrative reconciliation) makes it safe.
self._reset_cleanup_evidence()
@@ -252,6 +258,26 @@ class ControllerService:
{"url": url, "submitter": submitter, "note": note},
)
def enqueue_export(
self,
url: str,
mode: str,
submitter: str | None,
note: str | None,
) -> dict[str, Any]:
return self._call(
"enqueue_export",
{
"url": url,
"mode": mode,
"submitter": submitter,
"note": note,
},
)
def list_export_jobs(self, *, limit: int = 10) -> list[dict[str, Any]]:
return self._call("list_export_jobs", {"limit": limit})
def submit_control(self, payload: Mapping[str, Any]) -> dict[str, Any]:
return self._call("control", dict(payload))
@@ -403,6 +429,35 @@ class ControllerService:
self._handle_mqtt_event(event)
def _handle_call(self, action: str, payload: Any) -> Any:
if action == "enqueue_export":
assert self.downloads is not None
reservation = self.downloads.enqueue_export(
payload["url"],
payload["mode"],
payload.get("submitter"),
payload.get("note"),
)
return {
"kind": "export",
"status": reservation.status,
"job_id": reservation.job_id,
"mode": payload["mode"],
}
if action == "list_export_jobs":
jobs = self.store.list_export_jobs(limit=payload["limit"])
return [
{
"job_id": job.job_id,
"mode": job.mode,
"url": job.url,
"status": job.status,
"requested_at": job.requested_at,
"finished_at": job.finished_at,
"output_paths": list(job.output_paths),
"error": job.error,
}
for job in jobs
]
if action == "enqueue_download":
assert self.downloads is not None
url = payload["url"]