XmLLM / src /app /jobs /models.py
Claude
Code quality: fix all ruff warnings, add CI/CD, improve test coverage
bbbfba8 unverified
Raw
History Blame Contribute Delete
2 kB
"""Job models — represents a single OCR processing run."""
from __future__ import annotations
from datetime import UTC, datetime
from enum import StrEnum
from typing import Any
from pydantic import BaseModel, Field
class JobStatus(StrEnum):
"""State machine for job lifecycle."""
QUEUED = "queued"
RUNNING = "running"
SUCCEEDED = "succeeded"
FAILED = "failed"
PARTIAL_SUCCESS = "partial_success"
class Job(BaseModel):
"""A single OCR processing job."""
job_id: str = Field(min_length=1)
status: JobStatus = JobStatus.QUEUED
# Input
provider_id: str = Field(min_length=1)
provider_family: str = Field(min_length=1)
source_filename: str | None = None
image_width: int | None = Field(default=None, gt=0)
image_height: int | None = Field(default=None, gt=0)
# Results
has_raw_payload: bool = False
has_canonical: bool = False
has_alto: bool = False
has_page_xml: bool = False
has_viewer: bool = False
# Timing
created_at: datetime = Field(default_factory=lambda: datetime.now(UTC))
started_at: datetime | None = None
completed_at: datetime | None = None
# Errors and warnings
error: str | None = None
warnings: list[str] = Field(default_factory=list)
@property
def duration_ms(self) -> float | None:
if self.started_at and self.completed_at:
return (self.completed_at - self.started_at).total_seconds() * 1000
return None
def to_summary(self) -> dict[str, Any]:
"""Lightweight summary for list views."""
return {
"job_id": self.job_id,
"status": self.status.value,
"provider_id": self.provider_id,
"source_filename": self.source_filename,
"created_at": self.created_at.isoformat(),
"duration_ms": self.duration_ms,
"has_alto": self.has_alto,
"has_page_xml": self.has_page_xml,
"error": self.error,
}