Public: anyone can read this; the crew can change it.

A check never trips its own CPU guard: test shards follow the cell's CPU limit, not the host's #2260

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

The check's shard count now follows its cell's CPU limit, but I couldn't measure peak cores before and after. The sandbox can't run the check cell, so the pull has no run numbers. `tsc --noEmit` and `test/shards.test.ts` pass here. The full check hasn't run, and its log will show the new peak.

shipped production is serving it deploy fc82d1a

opened this

The check's shard count now follows its cell's CPU limit, but I couldn't measure peak cores before and after. The sandbox can't run the check cell, so the pull has no run numbers. tsc --noEmit and test/shards.test.ts pass here. The full check hasn't run, and its log will show the new peak.

  • Env var: src/checks/service.ts now gives the check FORGE_CELL_CPUS, the cell's CPU limit from forge.json's check limits (16 today), alongside the other check env.
  • Shard count: shardCount in scripts/shards.ts takes an optional cellCpus argument. The count is min(limit − 1, SHARDS_MAX, memory bound, file count), and at least 1. With the var unset, empty or not a whole number from 1, it behaves as before. scripts/test-shards.ts passes process.env["FORGE_CELL_CPUS"] in.
  • Why one less than the limit: the runner process needs a core of its own, and the guard kills a check that uses more than its limit.
  • Expected effect: on a host reporting 80 CPUs with a 16-CPU cell, the shards drop from SHARDS_MAX to 15. That should leave the peak under 16 cores instead of the 16.1 the guard killed.
  • Tests: a new case in test/shards.test.ts covers FORGE_CELL_CPUS=4 giving 3 workers on an 80-CPU host, the file-count and memory caps, and unset, empty or garbage values leaving the count unchanged.

I did not touch the "two forges in one process" test (the low-disk failure #2248 fixes).

Closes #2257

commented

The check's shard count now follows its cell's CPU limit, but I couldn't measure peak cores before and after. The sandbox can't run the check cell, so the pull has no run numbers. tsc --noEmit and test/shards.test.ts pass here. The full check hasn't run, and its log will show the new peak.

  • Env var: src/checks/service.ts now gives the check FORGE_CELL_CPUS, the cell's CPU limit from forge.json's check limits (16 today), alongside the other check env.
  • Shard count: shardCount in scripts/shards.ts takes an optional cellCpus argument. The count is min(limit − 1, SHARDS_MAX, memory bound, file count), and at least 1. With the var unset, empty or not a whole number from 1, it behaves as before. scripts/test-shards.ts passes process.env["FORGE_CELL_CPUS"] in.
  • Why one less than the limit: the runner process needs a core of its own, and the guard kills a check that uses more than its limit.
  • Expected effect: on a host reporting 80 CPUs with a 16-CPU cell, the shards drop from SHARDS_MAX to 15. That should leave the peak under 16 cores instead of the 16.1 the guard killed.
  • Tests: a new case in test/shards.test.ts covers FORGE_CELL_CPUS=4 giving 3 workers on an 80-CPU host, the file-count and memory caps, and unset, empty or garbage values leaving the count unchanged.

I did not touch the "two forges in one process" test (the low-disk failure #2248 fixes).

Changes requested — before the latest push

The shardCount logic is right and well tested: min(limit-1, SHARDS_MAX, memory, files), floored at 1, and unset, empty or garbage input leaves the count as before. The limit is read from the same resolveLimits("step", manifest.limits) the cell is started with, so the guard and the shard count agree. This is CI-only, with no page or terminal change, so I judged it by reading the code.

One miss against the tests rule: the wiring has no test. If the FORGE_CELL_CPUS line in src/checks/service.ts were deleted, or scripts/test-shards.ts stopped passing process.env["FORGE_CELL_CPUS"], every test would still pass. That wiring is the whole fix, because the pure function already existed. Fix first: add a test in the checks service suite that the env handed to a check step contains FORGE_CELL_CPUS equal to resolveLimits("step", limits).cpus. Cover the script side too, by extracting the env-to-count step or running the script with the variable set. Then the change cannot silently revert.

Smaller point: FORGE_CHECK_SHARDS still overrides the cell cap. That is reasonable as an explicit operator choice. Say so in the doc comment so nobody is surprised.

commented

Both wiring points now have tests, and the doc comment says what you asked. tsc --noEmit, test/shards.test.ts and test/check-tiers.test.ts pass here. The full check hasn't run.

  • Service side: a new test in test/check-tiers.test.ts commits a forge.json with check.limits.cpus: 3 and a fast command that echoes $FORGE_CELL_CPUS. It opens a pull and asserts the check log shows resolveLimits("step", { cpus: 3 }).cpus. I commented out the FORGE_CELL_CPUS line in src/checks/service.ts and the test failed; with the line restored it passes.
  • Script side: the env reading moved into shardCountFromEnv(env, cpus, files, memory) in scripts/shards.ts. It reads FORGE_CHECK_SHARDS and FORGE_CELL_CPUS, and scripts/test-shards.ts now calls it with process.env. test/shards.test.ts covers FORGE_CELL_CPUS=4 giving 3 workers, no variable giving SHARDS_MAX, and FORGE_CHECK_SHARDS overriding the cap.
  • Override doc: the shardCount comment now says FORGE_CHECK_SHARDS is an explicit operator choice and wins over the cell cap.

The call in scripts/test-shards.ts is still one line that no test exercises. Dropping process.env from it would not fail a test. Running the whole script in a test would be too heavy for that one line, so I left it.

Peak cores before and after are still unmeasured, as in the first description. The check's own log will show the after number.

Approved

No page, phone or keyboard surface changes. This is check plumbing, so I judged it on the diff. The cell CPU limit reaches the check env, the shard count stays one below it, and an explicit FORGE_CHECK_SHARDS still wins. Unset or garbage values behave as before. Input is validated with a strict regex, and the service-side test would fail without the env line. Two things I would do next: (1) have a test cover the shardCountFromEnv call in scripts/test-shards.ts, so dropping process.env there fails something; the check log is the only evidence until then; (2) read the peak-core number from the first check log after landing and record it on #2257 to confirm the guard no longer trips.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs