The GitHub Actions job "Required Checks" on texera.git/gh-readonly-queue/main/pr-7609-3245f8c5df1ff75ba5d7b20fe779e195a906f6b9 has failed. Run started by GitHub user aglinxinyuan (triggered by aglinxinyuan).
Head commit for run: 0ff8dcf252ff51c7b2a5f43b206acb1984ba8461 / Eugene Gu <[email protected]> test(amber): cover the worker StartChannelHandler (#7609) ### What changes were proposed in this PR? This PR adds `StartChannelHandlerSpec`, the first unit coverage for `amber/src/main/scala/org/apache/texera/amber/engine/architecture/worker/promisehandlers/StartChannelHandler.scala`. The handler was last changed by #6913, which adjusted the boundary-state emission but added only integration coverage (`LoopIntegrationSpec`) and Python-side unit tests, so the Scala handler's state-emission and exception paths were unasserted at the unit level. No production code is changed; this is a test-only PR. The spec drives a real `DataProcessor` and asserts on the worker's outgoing messages, so the marker and the emitted state are checked as the wire payloads a downstream worker would actually receive rather than as mocked calls. The 15 tests pin the handler's three steps and the order between them: - the input port is resolved from the channel the ECM arrived on, and that port is what `produceStateOnStart` receives; - the unaligned START_CHANNEL marker reaches every data channel and no control channel, after the pending output is flushed; - the operator's boundary state is emitted to every data channel with the "no loop" envelope, an empty-but-present state is still emitted, and no state is emitted when the operator produces none; - every marker precedes every state, and the marker still goes out first when the operator throws; - a sink worker with no data channels emits nothing at all yet still replies successfully, and a second invocation repeats the whole sequence because the handler has no once-only guard; - an operator exception, an operator `Error`, and a failure raised inside `emitState` are all swallowed, reported through `handleExecutorException`, and answered with a successful reply, while a `ControlThrowable` escapes and an unassigned port fails the RPC outright. Four of these record current behavior that a reader may find surprising, and each says so in a comment rather than implying endorsement. `ErrorUtils.safely` swallows `java.lang.Error` because its `OutOfMemoryError` guard is a commented-out line, the port resolution sits before the `try` so an unassigned port escapes as an RPC failure instead of being reported like every other failure one line later, and the RPC replies successfully even after the operator fails because the failure is surfaced out of band. If any of these is later changed deliberately, the corresponding test turns red and forces that decision to be explicit, which is the point of pinning them. ### Any related issues, documentation, discussions? Closes #7606 ### How was this PR tested? The 15 new tests were run locally, together with the three pre-existing specs in the same package and the wider worker package: ``` sbt "WorkflowExecutionService/testOnly org.apache.texera.amber.engine.architecture.worker.promisehandlers.StartChannelHandlerSpec" -> Tests: succeeded 15, failed 0 sbt "WorkflowExecutionService/testOnly org.apache.texera.amber.engine.architecture.worker.promisehandlers.*" -> Suites: completed 4, Tests: succeeded 31, failed 0 sbt "WorkflowExecutionService/testOnly org.apache.texera.amber.engine.architecture.worker.*" -> Suites: completed 14, Tests: succeeded 112, failed 0 sbt "WorkflowExecutionService/Test/scalafmtCheck" -> success ``` Both positive and negative directions are covered, along with the empty and boundary cases: a produced state and no produced state, an empty-but-present state, zero downstream data channels, a never-registered input channel, and a repeated invocation. The assertions were mutation-checked rather than assumed to be meaningful. Fifteen mutations were applied to the production code one at a time and every one of them turned the spec red, including flipping `NO_ALIGNMENT` to `PORT_ALIGNMENT`, swapping `METHOD_START_CHANNEL` for `METHOD_END_CHANNEL`, inverting `isDefined`, deleting the `emitState` call, passing a constant port to `produceStateOnStart`, sending the marker after the `try` block instead of before it, dropping the `handleExecutorException` call, restricting the marker to the first data channel only, deleting the `outputManager.flush()` that precedes the marker, hoisting `emitState` out of the `try`, adding an idempotence guard, and pausing with a different `PauseType`. The production files were restored and verified byte-identical to `HEAD` afterwards. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Code (Claude Opus 5) Report URL: https://github.com/apache/texera/actions/runs/31666224092 With regards, GitHub Actions via GitBox
