Files
Video-Player-Controller/controller/models.py
T

114 lines
2.4 KiB
Python

"""Controller domain records shared by persistence and orchestration."""
from __future__ import annotations
from dataclasses import dataclass
MEDIA_STATES = frozenset(
{"empty", "queued", "downloading", "ready", "error", "deleting"}
)
LIVE_JOB_STATES = frozenset({"reserved", "running"})
LIVE_GUARD_STATES = frozenset({"active", "review_required"})
@dataclass(frozen=True)
class SlotRecord:
slot: int
generation: int
media_state: str
url: str | None
yt_id: str | None
title: str
item_count: int
published_item_count: int
created_at: float | None
ready_at: float | None
expires_at: float | None
last_error: str | None
updated_at: float
@dataclass(frozen=True)
class DownloadReservation:
status: str
slot: int | None = None
generation: int | None = None
job_id: str | None = None
reused_slot: bool = False
oldest_expires_at: float | None = None
@dataclass(frozen=True)
class DownloadJob:
job_id: str
slot: int
generation: int
url: str
status: str
submitter: str | None
note: str | None
requested_at: float
started_at: float | None
finished_at: float | None
error: str | None
@dataclass(frozen=True)
class DeleteToken:
slot: int
generation: int
reason: str
@dataclass(frozen=True)
class SlotGuard:
guard_id: str
slot: int
kind: str
state: str
created_at: float
review_after: float | None
cleared_at: float | None
cleared_by: str | None
clear_reason: str | None
@dataclass(frozen=True)
class PlayerObservation:
availability: str
phase: str
active_slot: int | None
active_path: str | None
paused: bool | None
generation: int
reconciliation_state: str
reconciliation_due_at: float | None
last_status_at: float | None
last_telemetry_at: float | None
@dataclass(frozen=True)
class MigrationReport:
migrated: bool
source_path: str | None = None
source_sha256: str | None = None
backup_path: str | None = None
warnings: tuple[str, ...] = ()
class StoreError(RuntimeError):
"""Base persistence error."""
class MigrationError(StoreError):
"""Legacy migration was rejected or could not complete safely."""
class SlotProtectedError(StoreError):
"""A slot cannot be modified because live activity protects it."""
class StaleOperationError(StoreError):
"""An operation token no longer identifies the slot occupant."""