diff --git a/alembic/versions/0105_worker_lane_one_cap.py b/alembic/versions/0105_worker_lane_one_cap.py index 01b4813..d36458b 100644 --- a/alembic/versions/0105_worker_lane_one_cap.py +++ b/alembic/versions/0105_worker_lane_one_cap.py @@ -70,11 +70,21 @@ _CAPS = ( def upgrade() -> None: - # The constraint goes first: it names `slots`, so dropping the column out - # from under it fails on Postgres. - op.drop_constraint("ck_worker_lane_slots_within_cap", "worker_lane", type_="check") + # The constraints go first: they name `slots`, so dropping the column out + # from under them fails on Postgres. + # + # `op.f()` around each name, and it is load-bearing. Without it alembic + # runs the name through Base.metadata's naming convention, which prepends + # `ck_worker_lane_` to a string that already carries it — and the DROP + # goes looking for `ck_worker_lane_ck_worker_lane_slots_within_cap`, which + # no database has. That is #3275 exactly, from the other direction: + # alembic 0088 had to RENAME four constraints created with the same + # doubling. Caught here by the integration lane, run 7365. op.drop_constraint( - "ck_worker_lane_slots_non_negative", "worker_lane", type_="check", + op.f("ck_worker_lane_slots_within_cap"), "worker_lane", type_="check", + ) + op.drop_constraint( + op.f("ck_worker_lane_slots_non_negative"), "worker_lane", type_="check", ) op.drop_column("worker_lane", "slots") op.drop_column("worker_lane", "enabled") diff --git a/tests/test_worker_lanes.py b/tests/test_worker_lanes.py index b3ba4fc..14be621 100644 --- a/tests/test_worker_lanes.py +++ b/tests/test_worker_lanes.py @@ -246,22 +246,16 @@ def test_an_unrecognised_queue_set_still_gets_a_true_label(): # --- the model's invariant --------------------------------------------------- -@pytest.mark.parametrize( - "slots,cap,ok", - [ - (0, 0, True), - (1, 1, True), - (1, 4, True), - (5, 4, False), # slots above its own cap - (-1, 1, False), # negative slots - (1, -1, False), # negative cap - ], -) -def test_worker_lane_check_constraints(slots, cap, ok): - """The constraints live in the database, not only in the service, because - a row violating `slots <= slots_cap` is not a rejected request — it is a - lane the reconcile (step 3) will drive UP to a number the operator - capped.""" +def test_the_row_carries_exactly_one_constraint_now(): + """`slots >= 0` and `slots <= slots_cap` went with the `slots` column on + 2026-09-23 — there is one number left, and the only thing that can be + wrong with it is being negative. + + Asserted as the WHOLE set rather than as a membership check: a constraint + left behind naming a dropped column is not a harmless leftover, it is a + table the migration cannot have produced, and the model would then + describe a schema no database has. + """ from backend.app.models import WorkerLane constraints = { @@ -269,17 +263,13 @@ def test_worker_lane_check_constraints(slots, cap, ok): if hasattr(c, "sqltext") } # The names carry the convention's `ck_worker_lane_` prefix ALREADY — the - # model declares them bare and Base.metadata's naming_convention applies it. - # Asserting the prefixed form is what pins the thing that actually went - # wrong once: alembic 0088 had to rename four constraints that shipped as - # `ck_x_ck_x_name`, because the migration pre-prefixed a name the - # convention then prefixed again (#3275). A bare-name assertion here would - # pass just as happily against a doubled one. - assert constraints == { - "ck_worker_lane_slots_non_negative": "slots >= 0", - "ck_worker_lane_cap_non_negative": "slots_cap >= 0", - "ck_worker_lane_slots_within_cap": "slots <= slots_cap", - } + # model declares them bare and Base.metadata's naming_convention applies + # it. Asserting the prefixed form is what pins the thing that actually + # went wrong once: alembic 0088 had to rename four constraints that + # shipped as `ck_x_ck_x_name`, because the migration pre-prefixed a name + # the convention then prefixed again (#3275). A bare-name assertion here + # would pass just as happily against a doubled one. + assert constraints == {"ck_worker_lane_cap_non_negative": "slots_cap >= 0"} for name in constraints: assert not name.startswith("ck_worker_lane_ck_"), f"doubled prefix: {name}"