Task Summary
frontend/src/app/workspace/service/operator-menu/operator-menu.service.ts has two coupled code-quality issues that should be fixed together:
-
Five merge(...).subscribe(...) blocks (lines 82-91, 93-100, 145-157, 161-178, 181-199) lack untilDestroyed / takeUntilDestroyed.
- Today the service is
providedIn: "root" so leaks are not observable in production, but during HMR these subscriptions retain references to old JointGraphWrapper / TexeraGraph instances, producing ghost handlers that can manifest as button-state flicker during dev.
- If the scope is ever changed to component / feature-module level, all five subscriptions immediately leak.
-
highlightedOperators and highlightedCommentBoxes are public mutable BehaviorSubjects (lines 57-58).
- Any external code can
.next() and corrupt service state, bypassing the highlight logic that should be authoritative inside the service.
- Three downstream handlers (lines 145, 161, 181) also subscribe to
highlightedOperators, so a single user highlight action causes a 4× fan-out: block A updates the BehaviorSubject → blocks C, D, E all re-fire. This shows up as extra CPU on multi-select.
Proposal
- Make the two
BehaviorSubjects private; expose readonly Observables (or asObservable()) for consumers.
- Replace the three handlers'
merge(this.highlightedOperators, ...) with reading internal state directly in a single update method invoked from blocks A and B — eliminates the fan-out.
- Add
takeUntilDestroyed() (or untilDestroyed(this) to keep consistent with the rest of the codebase) to all five subscriptions.
- Add unit tests covering disable / view-result / reuse-result button state transitions.
Priority
P2 – Medium (no user-visible bug, but unblocks OnPush adoption, removes a hidden 4× fan-out, prevents future regressions).
Task Type
Task Summary
frontend/src/app/workspace/service/operator-menu/operator-menu.service.tshas two coupled code-quality issues that should be fixed together:Five
merge(...).subscribe(...)blocks (lines 82-91, 93-100, 145-157, 161-178, 181-199) lackuntilDestroyed/takeUntilDestroyed.providedIn: "root"so leaks are not observable in production, but during HMR these subscriptions retain references to oldJointGraphWrapper/TexeraGraphinstances, producing ghost handlers that can manifest as button-state flicker during dev.highlightedOperatorsandhighlightedCommentBoxesare public mutableBehaviorSubjects (lines 57-58)..next()and corrupt service state, bypassing the highlight logic that should be authoritative inside the service.highlightedOperators, so a single user highlight action causes a 4× fan-out: block A updates the BehaviorSubject → blocks C, D, E all re-fire. This shows up as extra CPU on multi-select.Proposal
BehaviorSubjectsprivate; exposereadonlyObservables (orasObservable()) for consumers.merge(this.highlightedOperators, ...)with reading internal state directly in a single update method invoked from blocks A and B — eliminates the fan-out.takeUntilDestroyed()(oruntilDestroyed(this)to keep consistent with the rest of the codebase) to all five subscriptions.Priority
P2 – Medium (no user-visible bug, but unblocks
OnPushadoption, removes a hidden 4× fan-out, prevents future regressions).Task Type