test(sort): fix flaky active_worker_limit_caps_then_reactivates - #646
Conversation
`active_worker_limit_caps_then_reactivates` reads `per_thread_step_counts` as soon as it has drained the compress result channel, but that channel closing does not mean the counters are up to date. A worker sends the job's result — and drops the job, closing its sender — inside `handle_compress_job`, i.e. inside `execute_step`. The counter is incremented by `record_step` only after `execute_step` returns. So the main thread can observe every result, join the submit thread, and read the counters while the last worker is still between the send and the increment, leaving the sum one short. That is what CI hit: `599` vs `600`, per-worker counts [231, 129, 57, 17, 134, 31]. Confirmed by inserting a 200us sleep between `execute_step` returning Success and `record_step`, which makes the test fail every run (298 vs 300); with this change it passes with that sleep still in place. The counters are stats-only and are read after `shutdown()` joins the workers in production, so this is a test synchronization defect, not a pool bug — the fix is to wait for the counters to settle rather than to reorder the worker. Full fgumi-sort suite: 559 passed.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughThe worker pool test now waits for cumulative ChangesWorker counter synchronization
Estimated code review effort: 2 (Simple) | ~10 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Codecov Report❌ Patch coverage is
❌ Your patch check has failed because the patch coverage (80.00%) is below the target coverage (90.00%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## main #646 +/- ##
==========================================
- Coverage 93.53% 93.49% -0.05%
==========================================
Files 175 175
Lines 105806 105820 +14
==========================================
- Hits 98969 98939 -30
- Misses 6837 6881 +44 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
active_worker_limit_caps_then_reactivates(added in #614) is flaky and is failing CI on unrelated PRs — it turned up on #616, whose diff is along_aboutstring incodec.rsand cannot reachfgumi-sort:Root cause
The test drains the compress result channel, joins the submit thread, and then reads
per_thread_step_counts. Draining that channel does not mean the counters are up to date.A worker sends the job's result — and drops the job, which closes that job's sender — inside
handle_compress_job, i.e. insideexecute_step. The counter is incremented afterwards, byrecord_step, onceexecute_stephas returned:So
result_rx.recv()returnsErr— the loop the test uses to know the batch is done — as soon as the last job's sender is dropped, which is strictly before that job's counter increment. The main thread can then read the counters while a worker is still in the gap, and the sum comes up short by one per worker caught mid-gap. The counts in the CI failure sum to exactly 599.Evidence
Not inferred from reading alone. Inserting a 200µs sleep at precisely that gap — between
execute_stepreturningSuccessandrecord_step— makes the test fail on every run:With this change in place and that sleep still inserted, the test passes. The sleep was then removed.
(The window is narrow enough that the test passed 180/180 unmodified runs locally, including 120 under 8-way CPU contention, which is why widening the window was necessary to demonstrate it rather than fish for a failure.)
Fix
Wait for the counters to settle instead of reading a value that is still in flight: after draining the results, poll until the summed counters reach the cumulative job total, with a 30s deadline that fails with the observed per-worker counts if they never do.
The counters are stats-only, and in production they are read after
shutdown()has joined the workers — so this is a test synchronization defect, not a pool bug. Reorderingrecord_stepbefore the send to suit the test would change production behaviour (and the recorded duration would then exclude the send) for no benefit, so the fix stays in the test.cargo nextest run -p fgumi-sort: 559 passed.cargo ci-fmt,cargo ci-lintclean.Summary by CodeRabbit