This reverts 2529b51. Not a retreat — a reordering, on the operator's
call, and the better sequence.
The squash's acceptance test (run 4971) found ~130 places where the ORM
models do not describe the deployed schema (#3275), including a
unique=True the database never had and two UNIQUE indexes that exist
only in migrations. Collapsing now would have baked all of that into the
one file a public installer starts from.
So: fix the drift first as ordinary migrations on the intact chain, let
the operator deploy so their database moves to the corrected head, and
only then collapse. The baseline is then generated from reconciled
models and reproduces a schema worth reproducing.
Nothing is lost by reverting. The baseline was never deployed, and
regenerating it after the fixes is strictly better than patching this
copy — it will come out of autogenerate correct rather than needing the
same hand-finishing twice.
45 lines
1.7 KiB
Python
45 lines
1.7 KiB
Python
"""partial indexes so GPU-job leasing stays O(batch), not O(completed)
|
|
|
|
The lease claims the lowest-id pending (or expired-leased) jobs. With only a
|
|
plain `status` index, `... ORDER BY id LIMIT n` walked the primary-key index from
|
|
the start, skipping the entire prefix of already-done/error rows before reaching
|
|
pending ones — so leasing slowed to a crawl as `done` piled up (the whole reason
|
|
throughput fell off a cliff mid-run and /status stalled). Two partial indexes fix
|
|
it: the pending one is id-ordered so the hot path reads just the first n entries,
|
|
and the leased-expiry one keeps the crash-recovery reclaim + the orphan sweep
|
|
cheap. They cover only the small live slice of the table, so they stay tiny even
|
|
as the done/error history grows to millions.
|
|
|
|
Revision ID: 0070
|
|
Revises: 0069
|
|
Create Date: 2026-06-30
|
|
"""
|
|
from typing import Sequence, Union
|
|
|
|
import sqlalchemy as sa
|
|
from alembic import op
|
|
|
|
revision: str = "0070"
|
|
down_revision: Union[str, None] = "0069"
|
|
branch_labels: Union[str, Sequence[str], None] = None
|
|
depends_on: Union[str, Sequence[str], None] = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
# Hot path: lowest-id pending jobs. Index on id, restricted to pending, so
|
|
# `WHERE status='pending' ORDER BY id LIMIT n` is a short index-order scan.
|
|
op.create_index(
|
|
"ix_gpu_job_pending", "gpu_job", ["id"],
|
|
postgresql_where=sa.text("status = 'pending'"),
|
|
)
|
|
# Crash-recovery: expired leases, for the lease backstop + recover_orphaned.
|
|
op.create_index(
|
|
"ix_gpu_job_leased_expires", "gpu_job", ["lease_expires_at"],
|
|
postgresql_where=sa.text("status = 'leased'"),
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.drop_index("ix_gpu_job_leased_expires", table_name="gpu_job")
|
|
op.drop_index("ix_gpu_job_pending", table_name="gpu_job")
|