Files
2026-07-16 15:02:03 +08:00

86 lines
5.2 KiB
Python

from __future__ import annotations
from datetime import datetime
from sqlalchemy import BigInteger, CheckConstraint, DateTime, Float, ForeignKey, Index, Integer, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from app.models.base import Base, TimestampMixin
class VideoUpscaleTask(Base, TimestampMixin):
__tablename__ = "video_upscale_tasks"
__table_args__ = (
CheckConstraint(
"(chat_generation_task_id IS NOT NULL AND generation_record_id IS NULL) OR "
"(chat_generation_task_id IS NULL AND generation_record_id IS NOT NULL)",
name="ck_video_upscale_tasks_exactly_one_owner",
),
Index("uq_video_upscale_tasks_chat_task", "chat_generation_task_id", unique=True),
Index("uq_video_upscale_tasks_generation_record", "generation_record_id", unique=True),
Index("idx_video_upscale_tasks_provider_task_id", "provider_task_id"),
Index("idx_video_upscale_tasks_status_next_retry", "status", "next_retry_at"),
Index("idx_video_upscale_tasks_status_lease", "status", "lease_until"),
)
id: Mapped[str] = mapped_column(String(32), primary_key=True)
chat_generation_task_id: Mapped[str | None] = mapped_column(
String(32),
ForeignKey("chat_generation_tasks.id", ondelete="CASCADE"),
nullable=True,
)
generation_record_id: Mapped[str | None] = mapped_column(
String(32),
ForeignKey("generation_records.id", ondelete="CASCADE"),
nullable=True,
)
status: Mapped[str] = mapped_column(String(32), nullable=False, default="pending", server_default="pending")
stage: Mapped[str] = mapped_column(String(48), nullable=False, default="upscale_queued", server_default="upscale_queued")
processor_key: Mapped[str] = mapped_column(String(64), nullable=False)
attempt_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0, server_default="0")
failure_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0, server_default="0")
manual_retry_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0, server_default="0")
next_retry_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
last_error: Mapped[str | None] = mapped_column(Text, nullable=True)
source_local_path: Mapped[str | None] = mapped_column(Text, nullable=True)
source_file_size_bytes: Mapped[int] = mapped_column(BigInteger, nullable=False, default=0, server_default="0")
source_width: Mapped[int | None] = mapped_column(Integer, nullable=True)
source_height: Mapped[int | None] = mapped_column(Integer, nullable=True)
source_duration_seconds: Mapped[float | None] = mapped_column(Float, nullable=True)
source_deleted_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
source_delete_error: Mapped[str | None] = mapped_column(Text, nullable=True)
source_remote_url: Mapped[str | None] = mapped_column(Text, nullable=True)
source_remote_url_signed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
source_remote_url_expires_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
source_remote_url_last_probe_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
source_remote_url_probe_status: Mapped[str | None] = mapped_column(String(32), nullable=True)
input_source_type: Mapped[str | None] = mapped_column(String(32), nullable=True)
input_source_fallback_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0, server_default="0")
target_width: Mapped[int] = mapped_column(Integer, nullable=False)
target_height: Mapped[int] = mapped_column(Integer, nullable=False)
effective_target_width: Mapped[int | None] = mapped_column(Integer, nullable=True)
effective_target_height: Mapped[int | None] = mapped_column(Integer, nullable=True)
provider_task_id: Mapped[str | None] = mapped_column(String(160), nullable=True)
provider_request_json: Mapped[str | None] = mapped_column(Text, nullable=True)
provider_response_json: Mapped[str | None] = mapped_column(Text, nullable=True)
provider_output_url: Mapped[str | None] = mapped_column(Text, nullable=True)
provider_output_url_expires_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
provider_submitted_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
final_local_path: Mapped[str | None] = mapped_column(Text, nullable=True)
final_resource_url: Mapped[str | None] = mapped_column(Text, nullable=True)
final_file_size_bytes: Mapped[int] = mapped_column(BigInteger, nullable=False, default=0, server_default="0")
celery_task_id: Mapped[str | None] = mapped_column(String(160), nullable=True)
lease_token: Mapped[str | None] = mapped_column(String(64), nullable=True)
lease_until: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
started_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
completed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
failed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)