Say at startup when a flow wants a card, and record one seed rather than two
Docs / docs (push) Successful in 22s
Playwright Tests / test-playwright (1, 2) (push) Failing after 2m46s
Playwright Tests / test-playwright (2, 2) (push) Successful in 1m49s
pre-commit / pre-commit (push) Failing after 1m57s
Test Backend / test-backend (push) Failing after 2m28s
Compose Smoke Test / test-compose (push) Successful in 35s
Playwright Tests / merge-reports (push) Successful in 1m19s

Three things the first pass left.

`serve` now names the flows asking for a GPU when the engine has none
declared. The placer already warned, but into the log, where a fresh install
that forgot `--gpus` does not read it — and the cost of missing it is GPU
nodes running concurrently, which is what the declaration exists to prevent.

The seed was the one field an export still had to coalesce: `--seed 1`
filled the run-level column and left `param.seed` blank, while a declared
seed filled the parameter and left the column blank. It is resolved like
every other input now, and the column carries the seed the run actually used
however it arrived — including when a parameter outranks the run's own,
where the column used to report the one that lost.

And the docs say plainly that declaring the card is what buys the worker
retirement: a node that imports jax without `resources={"gpus": 1}` never
gets CUDA_VISIBLE_DEVICES, so nothing marks its worker as one holding a card.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Hra4ndWMCLU5F3KjUuVAc
This commit is contained in:
2026-08-29 15:18:42 +02:00
co-authored by Claude Opus 5
parent 6111b90747
commit 68d2565054
5 changed files with 127 additions and 10 deletions
+36
View File
@@ -455,6 +455,42 @@ def test_a_run_records_the_inputs_it_actually_starts_from():
session.commit()
def test_the_seed_is_recorded_the_same_way_however_it_arrived():
"""One field an export should not have to coalesce two columns for.
`--seed 1` fills the run's own column; a flow declaring a `seed` input
fills the parameter. Both are the seed the run used, so both are written.
"""
flow = FlowDef(
name="seeded",
mode="batch",
inputs=[FlowInput(spec=MessageSpec(name="seed", dtype=DType.INT), initial=42)],
)
service = RunService(controller=_OneFlow(flow), queue=_Collect())
made = []
try:
passed = service.submit("seeded", {}, seed=1)
made.append(passed.id)
assert (passed.seed, passed.params) == (1, {"seed": 1})
# Nothing passed: the declared value is the seed it ran with, and the
# run-level column says so rather than staying empty.
defaulted = service.submit("seeded", {})
made.append(defaulted.id)
assert (defaulted.seed, defaulted.params) == (42, {"seed": 42})
# A parameter still outranks the run's own seed, as it always has —
# and the column follows it rather than reporting the one that lost.
both = service.submit("seeded", {"seed": 7}, seed=1)
made.append(both.id)
assert (both.seed, both.params) == (7, {"seed": 7})
finally:
with Session(db_engine) as session:
for run in session.exec(select(Run).where(col(Run.id).in_(made))).all():
session.delete(run)
session.commit()
def test_a_key_nobody_used_submits_normally(
client, superuser_token_headers, monkeypatch
):