diff --git a/11-Features.md b/11-Features.md index 99424dc..e4fa326 100644 --- a/11-Features.md +++ b/11-Features.md @@ -3715,3 +3715,27 @@ becomes the lead. The range matters because on Linux the whole `/8` is bound to `127.0.0.2` is bindable; measured on the fleet host with `curl --interface 127.0.0.2` returning exit 7 (connect refused) rather than 45 (bind failed). On macOS the same command fails at the bind, which is why no test binds a real `127.0.0.2` source — it would fail for every developer on a Mac. + +## The idle reaper no longer stops a worker that just got a turn + +**What.** `reapIdle` decided a session was idle from a roster snapshot and then released it without +re-reading. A delivery landing in between made the session BUSY, and it was torn down anyway — +contrary to the method's own javadoc, which promised it never reaps a BUSY worker. The reap is now a +compare-and-release: it tears the session down only while the registry still holds the exact record +it checked. + +**On.** Always on. + +**Why it exists.** `onDelivered` flips exactly the two states the reaper accepts (READY, DONE) to +BUSY, and `bumpTurn` refreshes the activity clock — so the very act that should save a session from +the reaper is the one that raced it. The worker was killed, the turn never ran, and the release +reason said nothing about a race. It was never a silent loss: the release listener still fails a +blocked send with a reason, so the lead is told something went wrong, just not what. + +**One thing to know for maintenance.** The compare is `ConcurrentHashMap.remove(key, value)`, and +that is the linearization point — do not "simplify" it to a re-read of the state followed by a plain +remove, which shrinks the window without closing it and leaves the code looking correct. The public +`release` path stays unconditional on purpose: an explicit `fleet_stop` must not be refused because +the worker happens to have just become busy. A skipped reap logs one debug line naming the pane; +without it the race is unobservable by construction, and a reaper that quietly stops reaping is very +hard to diagnose.