"""`running` no CHECK de `registry_acts.content_status`.

Bug meu na 0023: o `take_content` reclama um acto marcando-o `running` com
`FOR UPDATE SKIP LOCKED`, para dois trabalhadores nunca pegarem no mesmo, mas o
CHECK só permitia `('pending','fetched','empty','error','skipped')`. O
`registry_sweep_days` tem `running` no CHECK dele; esqueci-me de o pôr no dos
actos.

Consequência: o job de conteúdo morria no **primeiro** acto que tentava abrir,
sempre. Fechava em 1 segundo com `erro` e 0 linhas, com o orçamento intacto — nem
um pedido chegava a sair para o IRN. Os actos lidos ficaram presos nos 2734 do
backfill inicial enquanto a listagem nacional acumulava 193 mil por abrir, e o
grafo parou de crescer, que é precisamente o que esta fase toda existia para
fazer.

O job falhou alto e ficou registado no `scraping_logs`, como devia. O que faltou
foi olhar para esse log em vez de assumir, pelos números da listagem a subir, que
a outra metade também andava.
"""
from alembic import op

revision = "0027"
down_revision = "0026"
branch_labels = None
depends_on = None


def upgrade() -> None:
    op.execute("ALTER TABLE registry_acts DROP CONSTRAINT IF EXISTS registry_acts_content_status_check")
    op.execute(
        """
        ALTER TABLE registry_acts ADD CONSTRAINT registry_acts_content_status_check
            CHECK (content_status IN ('pending','running','fetched','empty','error','skipped'))
        """
    )
    # Momento da reclamação, em coluna própria. Reutilizar o `content_fetched_at`
    # dava-lhe dois significados — "reclamado às" enquanto corre e "lido às"
    # depois — e é o tipo de ambiguidade que se paga meses mais tarde.
    op.execute("ALTER TABLE registry_acts ADD COLUMN content_claimed_at TIMESTAMPTZ")
    # Índice da recuperação: actos reclamados por um trabalhador que morreu têm de
    # voltar à fila sozinhos. Sem isto, um restart do contentor a meio deixa-os
    # invisíveis para sempre — e a 193 mil actos isso não se resolve à mão, como
    # se resolveu com os dias do varrimento.
    op.execute(
        """
        CREATE INDEX ix_racts_stale_claim ON registry_acts(content_claimed_at NULLS FIRST)
         WHERE content_status = 'running'
        """
    )


def downgrade() -> None:
    op.execute("DROP INDEX IF EXISTS ix_racts_stale_claim")
    op.execute("ALTER TABLE registry_acts DROP COLUMN IF EXISTS content_claimed_at")
    op.execute("UPDATE registry_acts SET content_status = 'pending' WHERE content_status = 'running'")
    op.execute("ALTER TABLE registry_acts DROP CONSTRAINT IF EXISTS registry_acts_content_status_check")
    op.execute(
        """
        ALTER TABLE registry_acts ADD CONSTRAINT registry_acts_content_status_check
            CHECK (content_status IN ('pending','fetched','empty','error','skipped'))
        """
    )
