Skip to content

Fix bugs in flow canvas delete handlers#2962

Merged
ThaminduDilshan merged 1 commit into
thunder-id:mainfrom
Dilusha-Madushan:fix/resolve-bugs-console-flow-builder
May 28, 2026
Merged

Fix bugs in flow canvas delete handlers#2962
ThaminduDilshan merged 1 commit into
thunder-id:mainfrom
Dilusha-Madushan:fix/resolve-bugs-console-flow-builder

Conversation

@Dilusha-Madushan
Copy link
Copy Markdown
Contributor

@Dilusha-Madushan Dilusha-Madushan commented May 24, 2026

Purpose

Fixes four bugs in the flow canvas when deleting nodes and edges involving execution steps:

  1. Stale edge reconnect — When a middle node was deleted, reconnect edges were computed from a stale getEdges() snapshot instead of the live edge state, causing incorrect or missing reconnections.
  2. Incorrect cascade delete of shared execution nodes — Deleting one edge to an execution node would remove the node even when other incoming edges still existed.
  3. Ghost edges after cascade delete — Edges incident to a cascade-deleted execution node were left in the canvas.
  4. Cross-node component pollution — When multiple action nodes shared the same component IDs, removing a component from one node incorrectly removed it from others.

Approach

useVisualFlowHandlers.ts — stale edge snapshot fix

Switched handleNodesDelete from a direct setEdges(reduce(..., currentEdges)) call (using a snapshot captured at call time) to the functional setter form setEdges((latestEdges) => reduce(..., latestEdges)). All graph queries (getIncomers, getOutgoers, getConnectedEdges) now operate on the running accumulator acc inside the reducer, so each deleted node sees the already-updated edge state from prior iterations.

useDeleteExecutionResource.ts — cascade and cleanup fixes

Rewrote deleteComponentAndNode with the following changes:

  • Computes remainingEdges (current edges minus deleted ones) upfront. An execution node is only cascade-deleted when no remaining edge still targets it, preventing premature removal of shared nodes.
  • Uses setNodes + setEdges to remove both the orphaned execution node and all its incident edges, eliminating ghost edges.
  • Replaces the flat shared actionComponentIds array with a Map<string, string[]> keyed by source node ID, so component removal is scoped per node and cannot bleed across unrelated action nodes.
  • Tightens the NEXT handle guard from a truthy check to sourceHandle?.endsWith('_NEXT'), preventing non-NEXT edges from triggering cascade logic.

Related Issues

Summary by CodeRabbit

  • Bug Fixes
    • Node deletion now reliably removes related edges and preserves nodes when alternative connections exist.
    • Deleting an intermediate node in a chain correctly reconnects predecessor to successor with a single reconnect edge.
    • Reconnect edges inherit the configured visual style and arrow markers.
    • Deletion handling refined to use the latest flow state so reconnections and removals reflect up-to-date edges.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 24, 2026

📝 Walkthrough

Walkthrough

Refactors node deletion to use functional setEdges updates for reconnect logic and removes onEdgeDelete plugin registration from useDeleteExecutionResource; tests updated to validate reconnect edges and to drop edge-delete plugin assertions.

Changes

Edge handling in flow operations

Layer / File(s) Summary
Functional edge updater in node deletion
frontend/apps/console/src/features/flows/hooks/useVisualFlowHandlers.ts
handleNodesDelete now calls setEdges with a functional updater and computes incomers/outgoers/connected edges from the reducer accumulator (acc) starting from latestEdges instead of using a captured currentEdges.
handleNodesDelete reconnect tests
frontend/apps/console/src/features/flows/hooks/__tests__/useVisualFlowHandlers.test.tsx
Adds tests to assert deleting the middle node in A→B→C creates one A→C reconnect edge with expected id/marker, verifies reconnect computation uses the live edges passed into the functional setEdges setter, and ensures reconnect edge type follows FlowConfigContext edgeStyle.
Remove onEdgeDelete registration in execution-resource hook
frontend/apps/console/src/features/flows/hooks/useDeleteExecutionResource.ts
useDeleteExecutionResource no longer destructures or registers onEdgeDelete; it only registers onNodeDelete and onNodeElementDelete effects.
Adjust execution-resource tests for removed edge plugin behavior
frontend/apps/console/src/features/flows/hooks/__tests__/useDeleteExecutionResource.test.tsx
Test mocks changed so onEdgeDelete is a plain mock; removed handler-registration/unsubscribe assertions and updated mocked edge sourceHandle format in affected tests.

Sequence Diagram

sequenceDiagram
  participant handleNodesDelete
  participant setEdges as setEdges(functionalUpdater)
  participant reducer as reducer(acc)
  participant getIncomers as getIncomers/Outgoers

  handleNodesDelete->>setEdges: call with functional updater
  setEdges->>reducer: invoke with latestEdges
  loop for each deleted node
    reducer->>getIncomers: query using acc (evolving edges)
    getIncomers->>reducer: return connected edges from acc
    reducer->>reducer: accumulate reconnect edges into acc
  end
  reducer->>setEdges: return final edge set
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • thunder-id/thunderid#2433: Updates the same flow hooks (useDeleteExecutionResource.ts and useVisualFlowHandlers.ts) in a related feature context addressing different aspects of edge cascade and plugin wiring logic.

Suggested labels

Type/Improvement

Suggested reviewers

  • brionmario
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fix bugs in flow canvas delete handlers' is concise, clear, and directly reflects the main objective of the pull request: fixing multiple bugs in the delete handlers for flow canvas nodes and edges.
Description check ✅ Passed The PR description is comprehensive and well-structured. It clearly outlines the purpose (four specific bugs), detailed approach for each fix with technical implementation details, and references the related issue. While some optional template sections like manual testing and documentation checkboxes are not filled, the critical content sections (Purpose and Approach) are thorough and informative.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

frontend/apps/console/src/features/flows/hooks/__tests__/useDeleteExecutionResource.test.tsx

ESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox.

frontend/apps/console/src/features/flows/hooks/__tests__/useVisualFlowHandlers.test.tsx

ESLint skipped: the ESLint configuration for this file references a package that is not available in the sandbox.

frontend/apps/console/src/features/flows/hooks/useDeleteExecutionResource.ts

ESLint skipped: the ESLint configuration for this file references a package that is not available in the sandbox.

  • 1 others

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 24, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@Dilusha-Madushan
Copy link
Copy Markdown
Contributor Author

Dilusha-Madushan commented May 25, 2026

Re-create issue scenario:

Screen.Recording.2026-05-25.at.11.38.54.mp4

@Dilusha-Madushan
Copy link
Copy Markdown
Contributor Author

Re-create the issue - #2644

Dilusha.Madushan_s.Video.-.May.25.2026.mp4

@Dilusha-Madushan Dilusha-Madushan force-pushed the fix/resolve-bugs-console-flow-builder branch from f9335b3 to 6ff444e Compare May 25, 2026 08:53
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
frontend/apps/console/src/features/flows/hooks/__tests__/useDeleteExecutionResource.test.tsx (1)

73-73: ⚡ Quick win

Remove unused onEdgeDelete mock from mockFlowPlugins.

onEdgeDelete is no longer exercised by this hook test suite, so this leftover mock is dead test scaffolding and can be dropped to keep intent clear.

Proposed cleanup
 const mockFlowPlugins = {
   onPropertyChange: vi.fn().mockReturnValue(vi.fn()),
   emitPropertyChange: vi.fn().mockReturnValue(true),
   onPropertyPanelOpen: vi.fn().mockReturnValue(vi.fn()),
   emitPropertyPanelOpen: vi.fn().mockReturnValue(true),
   onElementFilter: vi.fn().mockReturnValue(vi.fn()),
   emitElementFilter: vi.fn().mockReturnValue(true),
-  onEdgeDelete: vi.fn().mockReturnValue(vi.fn()),
   emitEdgeDelete: vi.fn().mockReturnValue(true),
   onNodeDelete: mockOnNodeDelete,

As per coding guidelines, **/*.{go,ts,tsx,js,jsx}: Delete dead code cleanly. No // removed or // deprecated placeholder comments. No renaming unused variables to _ prefixed names — remove them entirely unless required by an interface, callback, or framework signature.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@frontend/apps/console/src/features/flows/hooks/__tests__/useDeleteExecutionResource.test.tsx`
at line 73, Remove the dead mock property onEdgeDelete from the mockFlowPlugins
object in the test file useDeleteExecutionResource.test.tsx: locate the
mockFlowPlugins definition and delete the line "onEdgeDelete:
vi.fn().mockReturnValue(vi.fn())," (and any trailing comma adjustments) so the
mock no longer contains that unused property.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@frontend/apps/console/src/features/flows/hooks/__tests__/useDeleteExecutionResource.test.tsx`:
- Line 73: Remove the dead mock property onEdgeDelete from the mockFlowPlugins
object in the test file useDeleteExecutionResource.test.tsx: locate the
mockFlowPlugins definition and delete the line "onEdgeDelete:
vi.fn().mockReturnValue(vi.fn())," (and any trailing comma adjustments) so the
mock no longer contains that unused property.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4e39c31a-6adc-4e74-97c8-85c981c9903c

📥 Commits

Reviewing files that changed from the base of the PR and between f9335b3 and 6ff444e.

📒 Files selected for processing (4)
  • frontend/apps/console/src/features/flows/hooks/__tests__/useDeleteExecutionResource.test.tsx
  • frontend/apps/console/src/features/flows/hooks/__tests__/useVisualFlowHandlers.test.tsx
  • frontend/apps/console/src/features/flows/hooks/useDeleteExecutionResource.ts
  • frontend/apps/console/src/features/flows/hooks/useVisualFlowHandlers.ts

Copy link
Copy Markdown
Member

@ThaminduDilshan ThaminduDilshan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Content LGTM. Not clear on the removals

@ThaminduDilshan ThaminduDilshan added this pull request to the merge queue May 28, 2026
Merged via the queue into thunder-id:main with commit 251ac38 May 28, 2026
25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Flow Builder Connection Deletion Issue Flow Builder UI, deleting next executor when the entering link to it is deleted

3 participants