Release: dev → main (first public release) #258
@@ -273,9 +273,14 @@ def test_one_lane_failing_does_not_stop_the_others(monkeypatch):
|
|||||||
def test_a_lane_disabled_in_settings_but_still_consuming_is_stopped(monkeypatch):
|
def test_a_lane_disabled_in_settings_but_still_consuming_is_stopped(monkeypatch):
|
||||||
"""The case that made `consuming` necessary: a lane turned off while its
|
"""The case that made `consuming` necessary: a lane turned off while its
|
||||||
worker was down comes back consuming, and must be stopped when it
|
worker was down comes back consuming, and must be stopped when it
|
||||||
returns."""
|
returns.
|
||||||
|
|
||||||
|
Its live pool is ONE — zero slots means zero WORK, not an empty pool.
|
||||||
|
billiard will not run one, and the process is what the enable switch lands
|
||||||
|
on.
|
||||||
|
"""
|
||||||
control = _stub_control(monkeypatch)
|
control = _stub_control(monkeypatch)
|
||||||
_stub_live(monkeypatch, "ml", pools={"host-a": 0}, consuming={"ml"})
|
_stub_live(monkeypatch, "ml", pools={"host-a": 1}, consuming={"ml"})
|
||||||
|
|
||||||
result = wc.reconcile_lanes_sync({"ml": (0, False)})
|
result = wc.reconcile_lanes_sync({"ml": (0, False)})
|
||||||
|
|
||||||
@@ -286,9 +291,16 @@ def test_a_lane_disabled_in_settings_but_still_consuming_is_stopped(monkeypatch)
|
|||||||
def test_an_already_disabled_lane_is_not_cancelled_again(monkeypatch):
|
def test_an_already_disabled_lane_is_not_cancelled_again(monkeypatch):
|
||||||
"""The other half of the fixed point. `cancel_consumer` on a queue that is
|
"""The other half of the fixed point. `cancel_consumer` on a queue that is
|
||||||
not being consumed succeeds and does nothing, so an unconditional
|
not being consumed succeeds and does nothing, so an unconditional
|
||||||
reconcile would churn here forever with no symptom."""
|
reconcile would churn here forever with no symptom.
|
||||||
|
|
||||||
|
The live pool is ONE, not zero. This fixture said zero until the floor
|
||||||
|
landed, and it was describing a container that cannot exist — billiard
|
||||||
|
will not run an empty pool, and the generator starts ml at one process for
|
||||||
|
exactly that reason. A fixture in an impossible state passes for the wrong
|
||||||
|
reason and then fails on the correct fix, which is what it did.
|
||||||
|
"""
|
||||||
control = _stub_control(monkeypatch)
|
control = _stub_control(monkeypatch)
|
||||||
_stub_live(monkeypatch, "ml", pools={"host-a": 0}, consuming=set())
|
_stub_live(monkeypatch, "ml", pools={"host-a": 1}, consuming=set())
|
||||||
|
|
||||||
result = wc.reconcile_lanes_sync({"ml": (0, False)})
|
result = wc.reconcile_lanes_sync({"ml": (0, False)})
|
||||||
|
|
||||||
@@ -692,30 +704,6 @@ def test_a_lane_at_zero_slots_is_never_shrunk_to_an_empty_pool(monkeypatch):
|
|||||||
assert control.shrank == [], "tried to empty a pool billiard will not empty"
|
assert control.shrank == [], "tried to empty a pool billiard will not empty"
|
||||||
|
|
||||||
|
|
||||||
def test_that_lane_then_reports_nothing_to_do(monkeypatch):
|
|
||||||
"""The fixed point. It is not enough to stop sending the doomed message —
|
|
||||||
the reconcile must also stop CALLING the lane changed, or the log fills
|
|
||||||
with a correction that never corrects anything."""
|
|
||||||
_stub_control(monkeypatch)
|
|
||||||
_stub_live(monkeypatch, "ml", pools={"host-a": 1}, consuming=set())
|
|
||||||
|
|
||||||
result = wc.reconcile_lanes_sync({"ml": (0, False)})
|
|
||||||
|
|
||||||
assert result["changed"] == []
|
|
||||||
|
|
||||||
|
|
||||||
def test_zero_slots_still_means_zero_work(monkeypatch):
|
|
||||||
"""The floor is one PROCESS, not one consumer. A lane at zero keeps an
|
|
||||||
idle worker so the enable switch has something to reach, and stays off
|
|
||||||
because its queues are cancelled."""
|
|
||||||
control = _stub_control(monkeypatch)
|
|
||||||
_stub_live(monkeypatch, "ml", pools={"host-a": 1}, consuming={"ml"})
|
|
||||||
|
|
||||||
wc.reconcile_lanes_sync({"ml": (0, False)})
|
|
||||||
|
|
||||||
assert control.cancelled == [("ml", ["host-a"])]
|
|
||||||
|
|
||||||
|
|
||||||
def test_the_floor_applies_to_a_direct_resize_too(monkeypatch):
|
def test_the_floor_applies_to_a_direct_resize_too(monkeypatch):
|
||||||
"""Not only the reconcile — the UI dial and the autoscaler go through the
|
"""Not only the reconcile — the UI dial and the autoscaler go through the
|
||||||
same function, so the clamp belongs there rather than at each caller."""
|
same function, so the clamp belongs there rather than at each caller."""
|
||||||
|
|||||||
Reference in New Issue
Block a user