aglinxinyuan opened a new issue, #7321: URL: https://github.com/apache/texera/issues/7321
### Task Summary `ClusterListener` (34 lines) is the last file in the engine at **0%** coverage, and it has no spec. It is worth covering because the count it maintains is what the frontend's cluster badge renders: `updateClusterStatus` recomputes `numWorkerNodesInCluster` on every membership event and pushes a `ClusterStatusUpdateEvent` to every open session. A listener that stops subscribing, or stops fanning out, leaves every client showing a stale node count with nothing failing. It is testable without a second JVM. `AmberRuntime.pekkoConfig` selects the cluster provider with artery bound on port 0, so joining the node to itself makes it the leader and produces genuine `MemberUp` events. That is not a convenience — `Member` is `private[cluster]` and cannot be synthesized, so a real join is the only way to reach the event path at all. Three things to be careful about, each of which produced a failing draft before it was understood: 1. **The catch-all arm needs `TestActorRef.receive`, not `!`.** With a normal send, an exception from `receive` is taken by the supervisor and the actor is restarted — and a restarted listener answers the next request exactly like one that never failed. A draft written with `!` stayed green with the catch-all replaced by a `throw`. 2. **Listeners must be stopped at the end of each case.** One left running stays subscribed and keeps iterating `SessionState.getAllSessionStates` on every membership event. 3. **A mock session must be removed inside the case that created it.** ScalaMock scopes expectations per test while the `SessionState` registry is JVM-global, so a leftover session gets called by a later test's listener against an expired mock. Points 2 and 3 both stem from a **real production race worth fixing separately**: `SessionState`'s registry is a plain unsynchronized `mutable.HashMap`, and `ClusterListener.updateClusterStatus` iterates it from the cluster-event thread while websocket open/close mutate it from container threads. A node joining or leaving while a user opens a tab can throw `ConcurrentModificationException` inside the listener. Out of scope: the `MemberRemoved` recovery arm, which walks every live execution and calls `notifyNodeFailure` or `forcefullyStop`, so it needs real Amber clients. ### Task Type - [ ] Refactor / Cleanup - [ ] DevOps / Deployment / CI - [x] Testing / QA - [ ] Documentation - [ ] Performance - [ ] Other -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
