Files
geointel/backend/app/services/runtime_reconciliation_service.py
T
Codex 9c402e0df2
GeoIntel CI / docs-smoke (push) Canceled after 0s
GeoIntel CI / contract-smoke (push) Canceled after 0s
Start autonomous Belgium and North Sea RC
2026-07-18 00:12:34 +02:00

59 lines
1.7 KiB
Python

from __future__ import annotations
from dataclasses import dataclass
from datetime import datetime, timezone
from sqlalchemy.orm import Session
from app.models import AnalysisRun, Job
@dataclass(frozen=True)
class ReconciliationResult:
interrupted_jobs: int
interrupted_analysis_runs: int
class RuntimeReconciliationService:
ERROR_MESSAGE = (
"PROCESS_INTERRUPTED: the GeoIntel process restarted before this work "
"reached a terminal state"
)
@staticmethod
def reconcile(
db: Session,
*,
finished_at: datetime | None = None,
) -> ReconciliationResult:
resolved_finished_at = finished_at or datetime.now(timezone.utc)
interrupted_jobs = (
db.query(Job)
.filter(Job.status == "running")
.update(
{
Job.status: "failed",
Job.finished_at: resolved_finished_at,
Job.error_message: RuntimeReconciliationService.ERROR_MESSAGE,
},
synchronize_session=False,
)
)
interrupted_analysis_runs = (
db.query(AnalysisRun)
.filter(AnalysisRun.status == "running")
.update(
{
AnalysisRun.status: "failed",
AnalysisRun.finished_at: resolved_finished_at,
AnalysisRun.error_message: RuntimeReconciliationService.ERROR_MESSAGE,
},
synchronize_session=False,
)
)
db.commit()
return ReconciliationResult(
interrupted_jobs=interrupted_jobs,
interrupted_analysis_runs=interrupted_analysis_runs,
)