fix(amber): tolerate in-flight RPC acks when EndWorker terminates a worker#6892
Open
aglinxinyuan wants to merge 3 commits into
Open
fix(amber): tolerate in-flight RPC acks when EndWorker terminates a worker#6892aglinxinyuan wants to merge 3 commits into
aglinxinyuan wants to merge 3 commits into
Conversation
…orker Loop e2e tests failed intermittently (~1 in 10 runs): region termination raced with the coordinator's ReturnInvocation acks for the worker's own fire-and-forget RPCs (workerExecutionCompleted / portCompleted). The very RPC that makes the coordinator decide to end the worker is the one whose ack is still in flight, so the race is inherent -- but the worker never awaits those acks, so an ack-only backlog carries no work. Loops amplify the race because every iteration terminates and re-executes regions, and the suite's single retry does not save runs where it strikes twice (same fail-fast as apache#5614's DataProcessingSpec flake). Scala EndHandler: succeed with a warning when everything queued is a ReturnInvocation; keep the fail-fast for anything else (control invocations, data, ECMs, actor commands) so the region execution manager's retry lets the worker drain real work. Python EndWorkerHandler: mirror the same semantics, and fix two latent defects -- the old handler consumed one message as a side effect of logging it (silently swallowing real work on the failure path) and its bare assert crashed on a two-ack backlog. Non-ack messages are now put back on the queue before failing. Tests: EndHandlerSpec gains ack-only (succeeds) and ack+work (still fails) cases; new test_end_worker_handler.py pins the same two behaviors plus that real work survives a failed EndWorker.
Contributor
Automated Reviewer SuggestionsBased on the
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #6892 +/- ##
============================================
- Coverage 78.70% 78.54% -0.17%
+ Complexity 3740 3737 -3
============================================
Files 1161 1161
Lines 46084 46073 -11
Branches 5110 5106 -4
============================================
- Hits 36269 36186 -83
- Misses 8206 8268 +62
- Partials 1609 1619 +10
*This pull request uses carry forward flags. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Contributor
|
| config | throughput | MB/s | latency | max Δ latest / 7d | |
|---|---|---|---|---|---|
| 🔴 | bs=10 sw=10 sl=64 | 374 | 0.228 | 25,715/37,701/37,701 us | 🔴 +22.1% / 🔴 +130.3% |
| ⚪ | bs=100 sw=10 sl=64 | 820 | 0.501 | 122,649/140,824/140,824 us | ⚪ within ±5% / 🔴 +28.8% |
| ⚪ | bs=1000 sw=10 sl=64 | 920 | 0.562 | 1,087,967/1,126,454/1,126,454 us | ⚪ within ±5% / 🔴 +8.0% |
Baseline details
Latest main f521750 from same runner
| config | metric | PR | latest main | 7d avg | Δ latest | Δ 7d |
|---|---|---|---|---|---|---|
| bs=10 sw=10 sl=64 | throughput | 374 tuples/sec | 449 tuples/sec | 759.72 tuples/sec | -16.7% | -50.8% |
| bs=10 sw=10 sl=64 | MB/s | 0.228 MB/s | 0.274 MB/s | 0.464 MB/s | -16.8% | -50.8% |
| bs=10 sw=10 sl=64 | p50 | 25,715 us | 21,065 us | 12,653 us | +22.1% | +103.2% |
| bs=10 sw=10 sl=64 | p95 | 37,701 us | 33,233 us | 16,371 us | +13.4% | +130.3% |
| bs=10 sw=10 sl=64 | p99 | 37,701 us | 33,233 us | 19,941 us | +13.4% | +89.1% |
| bs=100 sw=10 sl=64 | throughput | 820 tuples/sec | 827 tuples/sec | 966.78 tuples/sec | -0.8% | -15.2% |
| bs=100 sw=10 sl=64 | MB/s | 0.501 MB/s | 0.505 MB/s | 0.59 MB/s | -0.8% | -15.1% |
| bs=100 sw=10 sl=64 | p50 | 122,649 us | 119,407 us | 103,654 us | +2.7% | +18.3% |
| bs=100 sw=10 sl=64 | p95 | 140,824 us | 134,875 us | 109,308 us | +4.4% | +28.8% |
| bs=100 sw=10 sl=64 | p99 | 140,824 us | 134,875 us | 116,369 us | +4.4% | +21.0% |
| bs=1000 sw=10 sl=64 | throughput | 920 tuples/sec | 914 tuples/sec | 997.95 tuples/sec | +0.7% | -7.8% |
| bs=1000 sw=10 sl=64 | MB/s | 0.562 MB/s | 0.558 MB/s | 0.609 MB/s | +0.7% | -7.7% |
| bs=1000 sw=10 sl=64 | p50 | 1,087,967 us | 1,093,249 us | 1,007,348 us | -0.5% | +8.0% |
| bs=1000 sw=10 sl=64 | p95 | 1,126,454 us | 1,130,191 us | 1,050,149 us | -0.3% | +7.3% |
| bs=1000 sw=10 sl=64 | p99 | 1,126,454 us | 1,130,191 us | 1,079,497 us | -0.3% | +4.3% |
Raw CSV
config_idx,batch_size,schema_width,string_len,num_batches,total_ms,total_tuples,total_bytes,tuples_per_sec,mb_per_sec,lat_p50_us,lat_p95_us,lat_p99_us
0,10,10,64,20,534.45,200,128000,374,0.228,25715.14,37700.55,37700.55
1,100,10,64,20,2438.83,2000,1280000,820,0.501,122648.69,140824.20,140824.20
2,1000,10,64,20,21733.59,20000,12800000,920,0.562,1087967.06,1126454.32,1126454.32Resolves the overlap with apache#6522 (stop EndWorker from consuming straggler messages): keep apache#6522's size()-based check and never-drop guarantee, layer the ack-only leniency on top (all-ReturnInvocation backlog completes with a warning; anything else is re-queued and fails the RPC). Test file is the union: apache#6522's five straggler cases plus the two ack-leniency cases.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changes were proposed in this PR?
Fixes the ~1-in-10
LoopIntegrationSpecflake inamber-integration. Region termination logs:Root cause. The "unprocessed" message is always a
ReturnInvocation— the coordinator's ack for an RPC the worker itself sent fire-and-forget (workerExecutionCompleted/portCompleted). The race is inherent: that very RPC is what makes the coordinator decide to end the worker, so the ack andEndWorkerare concurrently in flight:The worker never awaits these acks, so an ack-only backlog carries no work. Loops amplify the race because every iteration terminates and re-executes regions — and the suite's single retry doesn't save runs where it strikes twice (same fail-fast previously seen in the
DataProcessingSpecflake, #5614).Fix (both sides of the engine, mirrored):
EndHandlerEndWorkerHandlerassert empty(crashed on 2 queued acks; silently swallowed real work)Scope note. Since #5737 (terminate-with-retry), this race usually self-heals on the retry — so its steady-state cost is termination latency, log noise, and the residual risk of repeated collisions across a loop's many terminations, rather than a guaranteed test failure. This PR removes the spurious failure mode at the source; if
amber-integrationflakes persist after it, the next suspect is a separate silent region-transition hang (a region's last worker completes but the region is never terminated, no EndHandler warning) that has been observed independently and is not addressed here.Any related issues, documentation, discussions?
Closes #6891. Related: #5614 (the same fail-fast race in
DataProcessingSpec) and #6522 (ports fail-and-retry semantics to the Python handler; the Python change here subsumes its non-destructive re-queue and additionally adds the ack-leniency on both sides).How was this PR tested?
EndHandlerSpec(Scala): new cases — ack-only backlog succeeds; ack + real work still fails. Existing cases (empty queue succeeds; control message / actor command fail) unchanged and passing.test_end_worker_handler.py(Python, new): ack-only backlog succeeds; empty queue succeeds; ack + control invocation fails and the control invocation survives in the queue (pins the old swallow-one bug).scalafmtCheckAll,scalafixAll --check, ruff format+check, and the loop-adjacent Python suite (68 tests) all green (Java 17).amber-integrationlogs on subsequent runs.Was this PR authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Fable 5)