← 1.0.0 backlogs ISS-29 Done

SAPE-18's standing gate measured how many cores the machine had, and reported it as a verdict about locks

Type
Bug in a test — and the failure message it printed was false
Found while
ISS-28, within an hour of CI existing
Triage
Fix in 1.0.0
Status
Done
Version
1.0.0

The measurement that settled it

The old gate timed one read against four at once and failed when four cost more than three times one. On a ten-core machine, the same build, with reads that do share:

ThreadsUnmodified (reads share)Exclusive-lock copy (reads queue)Verdict at the 3× bar
101.68–2.10×3.61–4.35×correct both ways
22.34–2.76×3.89–3.91×passes by 8%
14.02–4.06×3.90–4.08×fails both — indistinguishable

That bottom row is the whole issue. Given one usable thread, a build that shares and a build that serializes produce the same number. The gate could not tell a lock from a core count, and CI's 3.41–4.59× for the sharing build sits inside the serialized band. Its message — "they are queueing, not sharing" — was false every time it appeared.

The test's own comment blamed a loaded CI box. Load was not the cause; cores were. A confident wrong explanation had been sitting in the source, and nothing could check it until there was CI.

What replaced it

A read now counts itself. Two atomic adds on a call that walks a whole collection maintain how many reads are inside a database at this instant and the most that ever were at once; TestReadsShareTheDatabase asserts the high-water mark reached two.

Two is not a tuned threshold — it is where sharing begins. A database behind an exclusive lock cannot reach two on any number of cores, because the second read was never let in. So the measurement no longer depends on the machine being fast, only on it having more than one thread.

On the very runner that had been failing, it found four reads inside the database together, in three milliseconds. The code had been sharing the whole time.

Proven red, which is the part that makes green mean anything

4 connections counted for 5s; reads reached the database and ran there, and
never two of them at once: a read waited for the one before it to finish,
which is queueing, not sharing

That is the new gate against a copy of the same commit with the read lock made exclusive — reproduced independently, at two thread counts. Note what the message asserts before it accuses: that reads reached the database and ran there. A run that measured nothing cannot masquerade as a run that measured queueing.

Where it refuses to answer

At one usable thread, two reads cannot be inside a database at once whatever the locking allows — the overlap is absent in fact, not prevented by a lock, and nothing can tell those apart. The test says so and fails loudly rather than skipping, because this repository's CI treats a skip as red on purpose:

GOMAXPROCS is 1, and two reads cannot be inside a database at once on one
thread whatever the locking allows, so nothing here could be measured: this
test needs at least two

Worth stressing what that precondition is not: it does not need cores to be free. Two fully-loaded threads still run these reads inside each other, only slower. That is exactly the difference from the gate it replaces.

What it still cannot detect, said plainly

TestReadsRunTogetherAtN32 was deleted. It asserted nothing, cost every run 20,000 documents and 32 connections, and logged a ratio that is readers ÷ cores — 19.45× on CI, which reads alarming and means nothing. A log line that needs a paragraph to stop being alarming is worse than no log line.

What this says about ISS-28

This is the argument for CI, made by CI, within an hour of it existing — and a better argument than ISS-28 could make for itself. The defect sat in a gate guarding a Done ticket, on every machine with few cores, and nothing on a developer's laptop was ever going to say so.