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]

Reply via email to