"""add video upscale pipeline Revision ID: 3f47680a71d0 Revises: abae3e1c70f7 Create Date: 2026-07-16 11:08:16.449960 """ from typing import Sequence, Union from alembic import op import sqlalchemy as sa # revision identifiers, used by Alembic. revision: str = "3f47680a71d0" down_revision: Union[str, None] = "abae3e1c70f7" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: op.add_column( "chat_generation_tasks", sa.Column("provider_generation_resolution", sa.String(length=16), nullable=True), ) op.add_column( "chat_generation_tasks", sa.Column( "video_upscale_enabled_snapshot", sa.Boolean(), server_default=sa.text("false"), nullable=False, ), ) op.add_column( "chat_generation_tasks", sa.Column("video_upscale_snapshot_json", sa.Text(), nullable=True), ) op.add_column( "generation_records", sa.Column("provider_generation_resolution", sa.String(length=16), nullable=True), ) op.add_column( "generation_records", sa.Column( "video_upscale_enabled_snapshot", sa.Boolean(), server_default=sa.text("false"), nullable=False, ), ) op.add_column( "generation_records", sa.Column("video_upscale_snapshot_json", sa.Text(), nullable=True), ) op.add_column( "generation_records", sa.Column("pipeline_stage", sa.String(length=48), nullable=True), ) op.create_index( "ix_generation_records_pipeline_stage", "generation_records", ["pipeline_stage"], unique=False, ) op.create_table( "video_upscale_tasks", sa.Column("id", sa.String(length=32), nullable=False), sa.Column("chat_generation_task_id", sa.String(length=32), nullable=True), sa.Column("generation_record_id", sa.String(length=32), nullable=True), sa.Column("status", sa.String(length=32), server_default="pending", nullable=False), sa.Column("stage", sa.String(length=48), server_default="upscale_queued", nullable=False), sa.Column("processor_key", sa.String(length=64), nullable=False), sa.Column("attempt_count", sa.Integer(), server_default="0", nullable=False), sa.Column("failure_count", sa.Integer(), server_default="0", nullable=False), sa.Column("manual_retry_count", sa.Integer(), server_default="0", nullable=False), sa.Column("next_retry_at", sa.DateTime(timezone=True), nullable=True), sa.Column("last_error", sa.Text(), nullable=True), sa.Column("source_local_path", sa.Text(), nullable=True), sa.Column("source_file_size_bytes", sa.BigInteger(), server_default="0", nullable=False), sa.Column("source_width", sa.Integer(), nullable=True), sa.Column("source_height", sa.Integer(), nullable=True), sa.Column("source_duration_seconds", sa.Float(), nullable=True), sa.Column("source_deleted_at", sa.DateTime(timezone=True), nullable=True), sa.Column("source_delete_error", sa.Text(), nullable=True), sa.Column("source_remote_url", sa.Text(), nullable=True), sa.Column("source_remote_url_signed_at", sa.DateTime(timezone=True), nullable=True), sa.Column("source_remote_url_expires_at", sa.DateTime(timezone=True), nullable=True), sa.Column("source_remote_url_last_probe_at", sa.DateTime(timezone=True), nullable=True), sa.Column("source_remote_url_probe_status", sa.String(length=32), nullable=True), sa.Column("input_source_type", sa.String(length=32), nullable=True), sa.Column("input_source_fallback_count", sa.Integer(), server_default="0", nullable=False), sa.Column("target_width", sa.Integer(), nullable=False), sa.Column("target_height", sa.Integer(), nullable=False), sa.Column("effective_target_width", sa.Integer(), nullable=True), sa.Column("effective_target_height", sa.Integer(), nullable=True), sa.Column("provider_task_id", sa.String(length=160), nullable=True), sa.Column("provider_request_json", sa.Text(), nullable=True), sa.Column("provider_response_json", sa.Text(), nullable=True), sa.Column("provider_output_url", sa.Text(), nullable=True), sa.Column("provider_output_url_expires_at", sa.DateTime(timezone=True), nullable=True), sa.Column("provider_submitted_at", sa.DateTime(timezone=True), nullable=True), sa.Column("final_local_path", sa.Text(), nullable=True), sa.Column("final_resource_url", sa.Text(), nullable=True), sa.Column("final_file_size_bytes", sa.BigInteger(), server_default="0", nullable=False), sa.Column("celery_task_id", sa.String(length=160), nullable=True), sa.Column("lease_token", sa.String(length=64), nullable=True), sa.Column("lease_until", sa.DateTime(timezone=True), nullable=True), sa.Column("started_at", sa.DateTime(timezone=True), nullable=True), sa.Column("completed_at", sa.DateTime(timezone=True), nullable=True), sa.Column("failed_at", sa.DateTime(timezone=True), nullable=True), sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False), sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False), sa.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", ), sa.ForeignKeyConstraint( ["chat_generation_task_id"], ["chat_generation_tasks.id"], ondelete="CASCADE", ), sa.ForeignKeyConstraint( ["generation_record_id"], ["generation_records.id"], ondelete="CASCADE", ), sa.PrimaryKeyConstraint("id"), ) op.create_index( "idx_video_upscale_tasks_provider_task_id", "video_upscale_tasks", ["provider_task_id"], unique=False, ) op.create_index( "idx_video_upscale_tasks_status_lease", "video_upscale_tasks", ["status", "lease_until"], unique=False, ) op.create_index( "idx_video_upscale_tasks_status_next_retry", "video_upscale_tasks", ["status", "next_retry_at"], unique=False, ) op.create_index( "uq_video_upscale_tasks_chat_task", "video_upscale_tasks", ["chat_generation_task_id"], unique=True, ) op.create_index( "uq_video_upscale_tasks_generation_record", "video_upscale_tasks", ["generation_record_id"], unique=True, ) def downgrade() -> None: op.drop_index("uq_video_upscale_tasks_generation_record", table_name="video_upscale_tasks") op.drop_index("uq_video_upscale_tasks_chat_task", table_name="video_upscale_tasks") op.drop_index("idx_video_upscale_tasks_status_next_retry", table_name="video_upscale_tasks") op.drop_index("idx_video_upscale_tasks_status_lease", table_name="video_upscale_tasks") op.drop_index("idx_video_upscale_tasks_provider_task_id", table_name="video_upscale_tasks") op.drop_table("video_upscale_tasks") op.drop_index("ix_generation_records_pipeline_stage", table_name="generation_records") op.drop_column("generation_records", "pipeline_stage") op.drop_column("generation_records", "video_upscale_snapshot_json") op.drop_column("generation_records", "video_upscale_enabled_snapshot") op.drop_column("generation_records", "provider_generation_resolution") op.drop_column("chat_generation_tasks", "video_upscale_snapshot_json") op.drop_column("chat_generation_tasks", "video_upscale_enabled_snapshot") op.drop_column("chat_generation_tasks", "provider_generation_resolution")