feat: migration to add superseded column with backfill and partial index
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
"""Add superseded column to downloads
|
||||
|
||||
Revision ID: 003
|
||||
Revises: 002
|
||||
Create Date: 2026-03-18
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
revision: str = '003'
|
||||
down_revision: Union[str, None] = '002'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# Add superseded column with default False
|
||||
op.add_column(
|
||||
'downloads',
|
||||
sa.Column('superseded', sa.Boolean(), nullable=False, server_default='false')
|
||||
)
|
||||
|
||||
# Backfill: mark FAILED downloads as superseded where a later COMPLETED
|
||||
# download exists for the same source. REQUIRED — without this, all
|
||||
# previously-superseded failures reappear in the dashboard immediately.
|
||||
op.execute("""
|
||||
UPDATE downloads d
|
||||
SET superseded = TRUE
|
||||
WHERE d.status = 'failed'
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM downloads d2
|
||||
WHERE d2.source_id = d.source_id
|
||||
AND d2.status = 'completed'
|
||||
AND d2.created_at > d.created_at
|
||||
)
|
||||
""")
|
||||
|
||||
# Partial index covering the dominant query pattern: status + superseded = FALSE.
|
||||
# A single boolean column index would be ignored in favour of status indexes;
|
||||
# this form matches the WHERE clauses at all three affected query sites.
|
||||
op.create_index(
|
||||
'idx_downloads_not_superseded',
|
||||
'downloads',
|
||||
['status'],
|
||||
postgresql_where=sa.text('superseded = FALSE')
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_index('idx_downloads_not_superseded', table_name='downloads')
|
||||
op.drop_column('downloads', 'superseded')
|
||||
Reference in New Issue
Block a user