Skip to content

OperatorMenuService leaks subscriptions and exposes BehaviorSubjects publicly #4529

@Yicong-Huang

Description

@Yicong-Huang

Task Summary

frontend/src/app/workspace/service/operator-menu/operator-menu.service.ts has two coupled code-quality issues that should be fixed together:

  1. 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.
  2. 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

  • Refactor / Cleanup
  • Testing / QA

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions