55 lines
1.8 KiB
Python
55 lines
1.8 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
|
|
from app_config import APP_DIR
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class JobDefinition:
|
|
job_id: str
|
|
schedule: str
|
|
input_date_policy: str
|
|
dependencies: tuple[str, ...]
|
|
lock_key: str
|
|
timeout_seconds: int
|
|
max_attempts: int
|
|
output_version: str
|
|
|
|
|
|
class JobRegistry:
|
|
def __init__(self, definitions: tuple[JobDefinition, ...]) -> None:
|
|
self.definitions = definitions
|
|
self._by_id = {item.job_id: item for item in definitions}
|
|
if len(self._by_id) != len(definitions):
|
|
raise ValueError("Background job IDs must be unique")
|
|
|
|
@classmethod
|
|
def load(cls, path: Path | None = None) -> "JobRegistry":
|
|
config_path = path or APP_DIR / "config" / "jobs.config.json"
|
|
payload = json.loads(config_path.read_text(encoding="utf-8"))
|
|
definitions = tuple(
|
|
JobDefinition(
|
|
job_id=str(item["id"]),
|
|
schedule=str(item["schedule"]),
|
|
input_date_policy=str(item["input_date_policy"]),
|
|
dependencies=tuple(str(value) for value in item.get("dependencies") or []),
|
|
lock_key=str(item["lock_key"]),
|
|
timeout_seconds=max(1, int(item["timeout_seconds"])),
|
|
max_attempts=max(1, int(item["max_attempts"])),
|
|
output_version=str(item["output_version"]),
|
|
)
|
|
for item in payload.get("jobs") or []
|
|
)
|
|
if not definitions:
|
|
raise ValueError("Background job registry is empty")
|
|
return cls(definitions)
|
|
|
|
def get(self, job_id: str) -> JobDefinition:
|
|
try:
|
|
return self._by_id[job_id]
|
|
except KeyError as exc:
|
|
raise ValueError(f"Background job is not registered: {job_id}") from exc
|