test(amber): cover AdvanceRegionExecutionsHandler - #7648
Conversation
Add AdvanceRegionExecutionsHandlerSpec with six tests: the advance is delegated to the workflow execution manager with the coordinator's own actor service, the reply is produced without awaiting that advance (both directly and through the real RPC dispatch), a failed advance is reported to the client as a FatalError carrying the related worker id for a WorkflowRuntimeException and None otherwise, and a successful advance notifies the client of nothing. The advance is stubbed with a WorkflowExecutionManager subclass that records its calls and returns a promise the test controls; the coordinator processor, RPC server, RPC client and output gateway are real. No production code is changed.
Automated Reviewer SuggestionsBased on the
|
|
| config | throughput | MB/s | latency | max Δ latest / 7d | |
|---|---|---|---|---|---|
| 🔴 | bs=10 sw=10 sl=64 | 395 | 0.241 | 26,163/31,928/31,928 us | 🔴 +9.3% / 🔴 +105.8% |
| 🟢 | bs=100 sw=10 sl=64 | 813 | 0.496 | 118,927/152,463/152,463 us | 🟢 -7.7% / 🔴 +43.2% |
| ⚪ | bs=1000 sw=10 sl=64 | 901 | 0.55 | 1,113,986/1,167,106/1,167,106 us | ⚪ within ±5% / 🔴 +14.2% |
Baseline details
Latest main f5017f7 from same runner
| config | metric | PR | latest main | 7d avg | Δ latest | Δ 7d |
|---|---|---|---|---|---|---|
| bs=10 sw=10 sl=64 | throughput | 395 tuples/sec | 434 tuples/sec | 779.28 tuples/sec | -9.0% | -49.3% |
| bs=10 sw=10 sl=64 | MB/s | 0.241 MB/s | 0.265 MB/s | 0.476 MB/s | -9.1% | -49.3% |
| bs=10 sw=10 sl=64 | p50 | 26,163 us | 23,943 us | 12,712 us | +9.3% | +105.8% |
| bs=10 sw=10 sl=64 | p95 | 31,928 us | 30,986 us | 16,345 us | +3.0% | +95.3% |
| bs=10 sw=10 sl=64 | p99 | 31,928 us | 30,986 us | 19,050 us | +3.0% | +67.6% |
| bs=100 sw=10 sl=64 | throughput | 813 tuples/sec | 815 tuples/sec | 1,017 tuples/sec | -0.2% | -20.1% |
| bs=100 sw=10 sl=64 | MB/s | 0.496 MB/s | 0.498 MB/s | 0.621 MB/s | -0.4% | -20.1% |
| bs=100 sw=10 sl=64 | p50 | 118,927 us | 119,084 us | 100,048 us | -0.1% | +18.9% |
| bs=100 sw=10 sl=64 | p95 | 152,463 us | 165,242 us | 106,477 us | -7.7% | +43.2% |
| bs=100 sw=10 sl=64 | p99 | 152,463 us | 165,242 us | 114,739 us | -7.7% | +32.9% |
| bs=1000 sw=10 sl=64 | throughput | 901 tuples/sec | 912 tuples/sec | 1,048 tuples/sec | -1.2% | -14.0% |
| bs=1000 sw=10 sl=64 | MB/s | 0.55 MB/s | 0.556 MB/s | 0.639 MB/s | -1.1% | -14.0% |
| bs=1000 sw=10 sl=64 | p50 | 1,113,986 us | 1,093,168 us | 976,350 us | +1.9% | +14.1% |
| bs=1000 sw=10 sl=64 | p95 | 1,167,106 us | 1,151,383 us | 1,022,084 us | +1.4% | +14.2% |
| bs=1000 sw=10 sl=64 | p99 | 1,167,106 us | 1,151,383 us | 1,053,520 us | +1.4% | +10.8% |
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,506.38,200,128000,395,0.241,26162.55,31928.07,31928.07
1,100,10,64,20,2459.97,2000,1280000,813,0.496,118927.20,152462.66,152462.66
2,1000,10,64,20,22208.18,20000,12800000,901,0.550,1113986.45,1167106.06,1167106.06There was a problem hiding this comment.
Pull request overview
Adds the first direct unit test coverage for the coordinator-side AdvanceRegionExecutionsHandler in Amber, asserting its key behavioral contracts (delegation target, non-blocking reply semantics, and client notification behavior on failure).
Changes:
- Introduces
AdvanceRegionExecutionsHandlerSpecwith a controllableWorkflowExecutionManagerstub to observe delegation and async failure paths deterministically. - Verifies the handler replies immediately (does not await the advance) and is dispatchable via the real
AsyncRPCServerunderMETHOD_COORDINATOR_INITIATE_ADVANCE_REGION_EXECUTIONS. - Verifies
FatalErrorclient notification behavior forWorkflowRuntimeException(with related worker id) vs other failures (no worker id), and no notification on success.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7648 +/- ##
============================================
- Coverage 90.14% 89.78% -0.37%
- Complexity 4415 4416 +1
============================================
Files 1176 1176
Lines 47133 46924 -209
Branches 5285 5265 -20
============================================
- Hits 42487 42129 -358
- Misses 2879 3023 +144
- Partials 1767 1772 +5
*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:
|
What changes were proposed in this PR?
This adds
AdvanceRegionExecutionsHandlerSpec, the first direct coverage ofAdvanceRegionExecutionsHandler(added in #6960). The handler is four lines long but carries three distinct contracts, none of which was asserted anywhere: it delegates the advance to the workflow execution manager with the coordinator's own actor service, it replies to the requesting round without awaiting that advance (the whole point of routing the advance through its own control round), and on failure it notifies the client with aFatalErrorthat carries the related worker id when the cause is aWorkflowRuntimeExceptionandNoneotherwise.Six tests, test-only — no production file is touched:
should advance the region executions with the coordinator's own actor service— asserts the forwardedPekkoActorServiceis the coordinator's own instance (reference equality, plus a non-null guard so a vacuousnull == nullcannot pass).should reply immediately instead of awaiting the advance— the reply is defined while the advance's promise is still unsatisfied. Deterministic, not timing-based: the handler'sEmptyReturn()becomes an already-satisfied future throughreturnAsFuture, while the stubbed advance never completes. No sleeps or polling anywhere in the spec.should reply to the requesting round while the advance is still running— delivers the request throughprocessDCMand the realAsyncRPCServer, so it also pins that the handler is dispatchable underMETHOD_COORDINATOR_INITIATE_ADVANCE_REGION_EXECUTIONS, the wire namePortCompletedHandleractually sends.should notify the client of a failed advance with the related worker idshould notify the client of a failed advance without a worker id for other failuresshould not notify the client when the advance succeedsThe fixture pattern is reused from the sibling handler specs (
TestKit+RegionExecutionManagerTestSupport.createCoordinatorHarness()+ a realCoordinatorProcessorandCoordinatorAsyncRPCHandlerInitializer, as inPortCompletedHandlerSpecandEmbeddedControlMessageHandlerSpec). The only new piece is aWorkflowExecutionManagersubclass that records advance calls and hands back a promise the test controls: driving the real manager into an async failure requires staging a full region launch/termination, and the causes it produces there areIllegalStateExceptions or the bareThrowablefromErrorUtils.reconstructThrowable— never aWorkflowRuntimeExceptioncarrying a worker id, which is the case test 4 exists to pin. Only the advance is stubbed; the coordinator processor, RPC server dispatch, RPC client and output gateway are all real.Note on test 4: the
WorkflowRuntimeExceptionarm currently pins intent rather than today-observable behavior. The two production subclasses that do carry a worker id,StateManager.InvalidStateExceptionandInvalidTransitionException(StateManager.scala:31-35), are thrown worker-side, and a failed worker RPC reaches the coordinator throughErrorUtils.reconstructThrowable, which always rebuilds a plainThrowableand so drops the type; every other production site constructs aWorkflowRuntimeExceptionwith a message only, leavingrelatedWorkerIdempty. Both arms would therefore behave identically at present. The branch is in the handler and documented as intended, so the test guards it against regression.Any related issues, documentation, discussions?
Closes #7646
The handler was introduced by #6960 (backported as #7096).
How was this PR tested?
sbt "WorkflowExecutionService/testOnly *AdvanceRegionExecutionsHandlerSpec"— 6 tests, all passing. No regressions in the neighbourhood:*coordinator.promisehandlers.* *scheduling.*runs 20 suites / 166 tests / 0 failures.WorkflowExecutionService/Test/scalafmtCheckis clean.Each test was mutation-checked: the production handler was temporarily broken, the suite re-run, and the handler reverted. Every behavior-changing mutant is caught, and each test is the sole killer of at least one:
FatalError(err, err.relatedWorkerId)→FatalError(err, None)FatalError(err, Some(COORDINATOR))— wrong but non-empty worker id.onFailureblock.onFailure { case _ => () }(swallow the failure).onSuccessinsteadFatalErrortwice.map(_ => EmptyReturn()))Future.Unitin place of the call)advanceRegionExecutions(null)instead ofcp.actorServiceadvanceRegionExecutionstwiceThe only surviving mutant,
EmptyReturn()→Future.value(EmptyReturn()), is semantically equivalent (returnAsFutureis an eagerFuture.apply), so there is nothing to catch.Was this PR authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Claude Opus 5)