"""Durable jobs: jobs, job_items, job_events. Revision ID: 0004_durable_jobs Revises: 0003_thumbnails Create Date: 2026-07-15 """ import sqlalchemy as sa from alembic import op revision = "0004_durable_jobs" down_revision = "0003_thumbnails" branch_labels = None depends_on = None def upgrade() -> None: op.create_table( "jobs", sa.Column("id", sa.String(), primary_key=True), sa.Column("job_type", sa.String(), nullable=False), sa.Column("state", sa.String(), nullable=False), sa.Column("lock_key", sa.String(), nullable=True), sa.Column("idempotency_key", sa.String(), nullable=True, unique=True), sa.Column("lease_owner", sa.String(), nullable=True), sa.Column("lease_expires_at", sa.DateTime(timezone=True), nullable=True), sa.Column("heartbeat_at", sa.DateTime(timezone=True), nullable=True), sa.Column("fencing_token", sa.Integer(), nullable=False, server_default="0"), sa.Column("error_code", sa.String(), nullable=True), sa.Column("error_message", sa.String(), nullable=True), sa.Column( "created_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.text("CURRENT_TIMESTAMP"), ), sa.Column( "updated_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.text("CURRENT_TIMESTAMP"), ), sa.Column("started_at", sa.DateTime(timezone=True), nullable=True), sa.Column("finished_at", sa.DateTime(timezone=True), nullable=True), sa.Column("version", sa.Integer(), nullable=False, server_default="1"), ) op.create_index("ix_jobs_state", "jobs", ["state"]) op.create_index("ix_jobs_lock_key", "jobs", ["lock_key"]) op.create_table( "job_items", sa.Column("job_id", sa.String(), sa.ForeignKey("jobs.id"), primary_key=True), sa.Column("item_key", sa.String(), primary_key=True), sa.Column("state", sa.String(), nullable=False), sa.Column("attempt_count", sa.Integer(), nullable=False, server_default="0"), sa.Column("error_code", sa.String(), nullable=True), sa.Column("error_message", sa.String(), nullable=True), sa.Column( "updated_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.text("CURRENT_TIMESTAMP"), ), ) op.create_table( "job_events", sa.Column("id", sa.String(), primary_key=True), sa.Column("job_id", sa.String(), sa.ForeignKey("jobs.id"), nullable=False), sa.Column("event_type", sa.String(), nullable=False), sa.Column("message", sa.String(), nullable=True), sa.Column( "created_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.text("CURRENT_TIMESTAMP"), ), ) op.create_index("ix_job_events_job_id", "job_events", ["job_id"]) def downgrade() -> None: op.drop_table("job_events") op.drop_table("job_items") op.drop_table("jobs")