59 lines
1.7 KiB
Python
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,
|
|
)
|