from datetime import datetime from typing import Any from sqlalchemy import DateTime, Enum, Index, String, Text, func from sqlalchemy.dialects.postgresql import JSONB from sqlalchemy.orm import Mapped, mapped_column from app.models.base import Base, TimestampMixin, UUIDPrimaryKeyMixin from app.models.enums import JobStatus class Job(UUIDPrimaryKeyMixin, TimestampMixin, Base): """Postgres-backed background queue, claimed via FOR UPDATE SKIP LOCKED.""" __tablename__ = "jobs" __table_args__ = (Index("ix_jobs_status_run_after", "status", "run_after"),) type: Mapped[str] = mapped_column(String(100)) payload: Mapped[dict[str, Any]] = mapped_column(JSONB, default=dict) status: Mapped[JobStatus] = mapped_column( Enum(JobStatus, native_enum=False, length=32), default=JobStatus.pending ) run_after: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now() ) attempts: Mapped[int] = mapped_column(default=0) last_error: Mapped[str | None] = mapped_column(Text)