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 | 390 | 0.238 | 25,798/29,136/29,136 us | 🔴 +18.7% / 🔴 +102.5% |
| ⚪ | bs=100 sw=10 sl=64 | 810 | 0.494 | 121,556/156,252/156,252 us | ⚪ within ±5% / 🔴 +45.2% |
| 🔴 | bs=1000 sw=10 sl=64 | 913 | 0.557 | 1,083,808/1,169,067/1,169,067 us | 🔴 +7.0% / 🔴 +12.8% |
Baseline details
Latest main 4013ca7 from same runner
| config | metric | PR | latest main | 7d avg | Δ latest | Δ 7d |
|---|---|---|---|---|---|---|
| bs=10 sw=10 sl=64 | throughput | 390 tuples/sec | 434 tuples/sec | 774.89 tuples/sec | -10.1% | -49.7% |
| bs=10 sw=10 sl=64 | MB/s | 0.238 MB/s | 0.265 MB/s | 0.473 MB/s | -10.2% | -49.7% |
| bs=10 sw=10 sl=64 | p50 | 25,798 us | 21,740 us | 12,738 us | +18.7% | +102.5% |
| bs=10 sw=10 sl=64 | p95 | 29,136 us | 34,544 us | 16,348 us | -15.7% | +78.2% |
| bs=10 sw=10 sl=64 | p99 | 29,136 us | 34,544 us | 18,848 us | -15.7% | +54.6% |
| bs=100 sw=10 sl=64 | throughput | 810 tuples/sec | 816 tuples/sec | 1,005 tuples/sec | -0.7% | -19.4% |
| bs=100 sw=10 sl=64 | MB/s | 0.494 MB/s | 0.498 MB/s | 0.613 MB/s | -0.8% | -19.4% |
| bs=100 sw=10 sl=64 | p50 | 121,556 us | 119,174 us | 100,970 us | +2.0% | +20.4% |
| bs=100 sw=10 sl=64 | p95 | 156,252 us | 158,112 us | 107,605 us | -1.2% | +45.2% |
| bs=100 sw=10 sl=64 | p99 | 156,252 us | 158,112 us | 116,429 us | -1.2% | +34.2% |
| bs=1000 sw=10 sl=64 | throughput | 913 tuples/sec | 945 tuples/sec | 1,030 tuples/sec | -3.4% | -11.4% |
| bs=1000 sw=10 sl=64 | MB/s | 0.557 MB/s | 0.577 MB/s | 0.629 MB/s | -3.5% | -11.4% |
| bs=1000 sw=10 sl=64 | p50 | 1,083,808 us | 1,054,845 us | 991,433 us | +2.7% | +9.3% |
| bs=1000 sw=10 sl=64 | p95 | 1,169,067 us | 1,092,578 us | 1,036,668 us | +7.0% | +12.8% |
| bs=1000 sw=10 sl=64 | p99 | 1,169,067 us | 1,092,578 us | 1,070,470 us | +7.0% | +9.2% |
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,512.32,200,128000,390,0.238,25798.02,29135.68,29135.68
1,100,10,64,20,2469.25,2000,1280000,810,0.494,121555.90,156252.35,156252.35
2,1000,10,64,20,21898.62,20000,12800000,913,0.557,1083807.65,1169066.52,1169066.52There 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 89.68% 89.67% -0.02%
Complexity 4399 4399
============================================
Files 1175 1176 +1
Lines 46979 46992 +13
Branches 5265 5268 +3
============================================
+ Hits 42133 42138 +5
- Misses 3082 3089 +7
- Partials 1764 1765 +1
*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)