feat: add isolated utility export modes
This commit is contained in:
+57
-1
@@ -1312,6 +1312,47 @@ class ControllerStore:
|
||||
).rowcount
|
||||
)
|
||||
|
||||
def recover_export_job(
|
||||
self,
|
||||
job_id: str,
|
||||
output_paths: Sequence[str],
|
||||
) -> bool:
|
||||
"""Record a fully verified export found during restart reconciliation."""
|
||||
|
||||
normalized = tuple(output_paths)
|
||||
if not normalized or any(
|
||||
not isinstance(path, str) or not path for path in normalized
|
||||
):
|
||||
raise ValueError("recovered export must contain output paths")
|
||||
with self._transaction() as connection:
|
||||
now = self._now()
|
||||
updated = connection.execute(
|
||||
"""
|
||||
UPDATE export_jobs
|
||||
SET status = 'completed', finished_at = ?,
|
||||
output_paths_json = ?, error = NULL
|
||||
WHERE job_id = ?
|
||||
AND status IN ('queued','running','failed','interrupted')
|
||||
""",
|
||||
(now, json.dumps(normalized), job_id),
|
||||
).rowcount
|
||||
if updated:
|
||||
connection.execute(
|
||||
"""
|
||||
INSERT INTO audit_events
|
||||
(occurred_at, event_type, actor, details_json)
|
||||
VALUES (?, 'utility_export_recovered', 'startup', ?)
|
||||
""",
|
||||
(
|
||||
now,
|
||||
json.dumps(
|
||||
{"job_id": job_id, "output_paths": normalized},
|
||||
sort_keys=True,
|
||||
),
|
||||
),
|
||||
)
|
||||
return bool(updated)
|
||||
|
||||
def get_export_job(self, job_id: str) -> ExportJob | None:
|
||||
with self._lock:
|
||||
row = self.connection.execute(
|
||||
@@ -1326,12 +1367,27 @@ class ControllerStore:
|
||||
rows = self.connection.execute(
|
||||
"""
|
||||
SELECT * FROM export_jobs
|
||||
ORDER BY requested_at DESC, job_id DESC LIMIT ?
|
||||
ORDER BY
|
||||
CASE WHEN status IN ('queued','running') THEN 0 ELSE 1 END,
|
||||
requested_at DESC,
|
||||
job_id DESC
|
||||
LIMIT ?
|
||||
""",
|
||||
(limit,),
|
||||
).fetchall()
|
||||
return [self._row_to_export_job(row) for row in rows]
|
||||
|
||||
def list_reconcilable_export_jobs(self) -> list[ExportJob]:
|
||||
with self._lock:
|
||||
rows = self.connection.execute(
|
||||
"""
|
||||
SELECT * FROM export_jobs
|
||||
WHERE status IN ('failed','interrupted')
|
||||
ORDER BY requested_at, job_id
|
||||
"""
|
||||
).fetchall()
|
||||
return [self._row_to_export_job(row) for row in rows]
|
||||
|
||||
def protect_slot(
|
||||
self,
|
||||
slot: int,
|
||||
|
||||
Reference in New Issue
Block a user