"""library_audit_run: resume cursor + progress timestamp for chunked scans Revision ID: 0039 Revises: 0038 Create Date: 2026-06-07 scan_library_for_rule used to run one 2h pass that timed out on large libraries and monopolized the concurrency-1 maintenance queue (operator-flagged). It now runs short time-boxed chunks that re-enqueue: `resume_after_id` persists the keyset cursor so the next chunk continues where it left off, and `last_progress_at` lets the recovery sweep tell a progressing multi-chunk audit from a genuinely stuck one. """ from typing import Sequence, Union import sqlalchemy as sa from alembic import op revision: str = "0039" down_revision: Union[str, None] = "0038" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: op.add_column( "library_audit_run", sa.Column( "resume_after_id", sa.Integer, nullable=False, server_default="0" ), ) op.add_column( "library_audit_run", sa.Column("last_progress_at", sa.DateTime(timezone=True), nullable=True), ) def downgrade() -> None: op.drop_column("library_audit_run", "last_progress_at") op.drop_column("library_audit_run", "resume_after_id")