Skip to content

fix(ui): drop nodeDepth partitioning so ELK derives lineage layers from edges#29224

Open
chirag-madlani wants to merge 9 commits into
mainfrom
fix-lineage-layout
Open

fix(ui): drop nodeDepth partitioning so ELK derives lineage layers from edges#29224
chirag-madlani wants to merge 9 commits into
mainfrom
fix-lineage-layout

Conversation

@chirag-madlani

@chirag-madlani chirag-madlani commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

Describe your changes:

Fixes #29225

I dropped the nodeDepth-based ELK partitioning in the lineage graph and let ELK's layered algorithm derive layers from edge topology (with BRANDES_KOEPF node placement) because pinning each node to its single backend nodeDepth forced a multi-branch node into the column of its first depth while its other edges fanned out to different columns, producing a visually misaligned graph. The result is a cleaner, less rigid horizontal flow, and it also removes the partition-on-cyclic-graph crash source.

Type of change:

  • Bug fix

High-level design:

N/A — small change (3 files): removed the per-node elk.partitioning.partition hint in getELKLayoutedElements, and removed elk.partitioning.activate while switching elk.layered.nodePlacement.strategy from SIMPLE to BRANDES_KOEPF in ELKUtil. Focus/root centering is unaffected — it is handled separately by centerNodePosition, not by partitioning.

Tests:

Use cases covered

  • A lineage node reachable at multiple depths is placed at the layer that best fits all its edges instead of being locked to its first backend depth.

Unit tests

  • Updated ELKUtil.test.ts to match the new layout options (19/19 pass).

Backend integration tests

  • Not applicable (no backend API changes).

Ingestion integration tests

  • Not applicable (no ingestion changes).

Playwright (UI) tests

  • Not applicable (layout-only change to existing graph).

Manual testing performed

  1. Verified ELKUtil unit suite passes.
  2. Reviewed the lineage layout flow to confirm partitioning was the only consumer of nodeDepth in layout and that focus centering is independent.

UI screen recording / screenshots:

Issue:

Screen.Recording.2026-06-22.at.5.50.17.PM.mov

Fix:

Screen.Recording.2026-06-22.at.5.50.57.PM.mov

Checklist:

  • I have read the CONTRIBUTING document.
  • I have commented on my code, particularly in hard-to-understand areas.
  • I have added/updated tests and listed them above.

Greptile Summary

This PR removes ELK's nodeDepth-based partitioning from the lineage graph layout and replaces it with topology-driven layer assignment using the BRANDES_KOEPF node placement strategy with BALANCED alignment. The fix addresses misalignment when a node is reachable at multiple depths and also eliminates a potential crash when partitioning is applied to cyclic graphs.

  • ELKUtil.ts: Swaps SIMPLE + elk.partitioning.activate for BRANDES_KOEPF + elk.layered.nodePlacement.bk.fixedAlignment: BALANCED; well-commented with rationale.
  • EntityLineageLayoutUtils.ts: Removes the per-node elk.partitioning.partition hint derived from node.data.nodeDepth, so nodeDepth is now unused in layout computation (the backend data still flows in harmlessly).
  • ELKUtil.test.ts: Unit tests updated in full (19/19) to match the new layout options; snapshot updated to reflect the changed graph positions.

Confidence Score: 5/5

Safe to merge — a focused, well-reasoned swap of ELK layout options with no behavioral regressions expected.

The change is minimal and surgical: two ELK options removed, two added, one dead variable dropped. The new BRANDES_KOEPF + BALANCED configuration is a well-established ELK layered-algorithm setting, the fix is correctly motivated, inline comments explain the why, unit tests cover the exact options changed, and the Playwright snapshot is updated. No data paths, API contracts, or backend interactions are touched.

No files require special attention.

Important Files Changed

Filename Overview
openmetadata-ui/src/main/resources/ui/src/utils/Lineage/Layout/ELKUtil/ELKUtil.ts Replaces SIMPLE + partitioning with BRANDES_KOEPF + BALANCED alignment; well-commented and correct.
openmetadata-ui/src/main/resources/ui/src/utils/EntityLineageLayoutUtils.ts Removes per-node elk.partitioning.partition hint and nodeDepth read; nodeDepth data still flows from backend but is now safely unused in layout.
openmetadata-ui/src/main/resources/ui/src/utils/Lineage/Layout/ELKUtil/ELKUtil.test.ts Unit tests fully updated to match new layout options; adds assertion for bk.fixedAlignment and verifies partitioning is absent.
openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/snapshots/LineageExportPNGSnapshot.spec.ts-snapshots/lineage-export-with-edges.png Playwright visual snapshot updated to reflect the new ELK layout output; expected change given the algorithm swap.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[getELKLayoutedElements] --> B[Map nodes to ElkNode]
    A --> C[Map edges to ElkExtendedEdge]
    B --> D[ELKLayout.layoutGraph]
    C --> D
    D --> E[ELK layered algorithm]
    E --> F{Node Placement Strategy}
    F -->|BEFORE removed| G[SIMPLE plus partitioning per nodeDepth]
    F -->|AFTER this PR| H[BRANDES_KOEPF plus BALANCED alignment]
    G --> I[Misaligned graph or cyclic crash]
    H --> J[Clean topology-driven layout]
    J --> K[updatedNodes with x/y positions]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[getELKLayoutedElements] --> B[Map nodes to ElkNode]
    A --> C[Map edges to ElkExtendedEdge]
    B --> D[ELKLayout.layoutGraph]
    C --> D
    D --> E[ELK layered algorithm]
    E --> F{Node Placement Strategy}
    F -->|BEFORE removed| G[SIMPLE plus partitioning per nodeDepth]
    F -->|AFTER this PR| H[BRANDES_KOEPF plus BALANCED alignment]
    G --> I[Misaligned graph or cyclic crash]
    H --> J[Clean topology-driven layout]
    J --> K[updatedNodes with x/y positions]
Loading

Reviews (7): Last reviewed commit: "Merge branch 'main' into fix-lineage-lay..." | Re-trigger Greptile

…om edges

Pinning each node to its backend nodeDepth via elk.partitioning forced a
multi-branch node into the column of its first depth, misaligning its other
edges. Let ELK's layered algorithm derive layers from edge topology and use
BRANDES_KOEPF node placement for a cleaner, less rigid horizontal flow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@chirag-madlani chirag-madlani requested a review from a team as a code owner June 19, 2026 13:47
@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

✅ PR checks passed

The linked issue has a description and all required Shipping project fields set. Thanks!

@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Jest test Coverage

UI tests summary

Lines Statements Branches Functions
Coverage: 62%
62.5% (66998/107188) 44.47% (37705/84786) 45.54% (11255/24712)

@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

🔴 Playwright Results — 1 failure(s), 11 flaky

✅ 4018 passed · ❌ 1 failed · 🟡 11 flaky · ⏭️ 84 skipped

Shard Passed Failed Flaky Skipped
✅ Shard 1 0 0 0 0
🟡 Shard 2 813 0 2 9
🔴 Shard 3 817 1 0 8
🟡 Shard 4 865 0 4 12
🟡 Shard 5 732 0 1 47
🟡 Shard 6 791 0 4 8

Genuine Failures (failed on all attempts)

Features/LineageExportPNGSnapshot.spec.ts › exported PNG includes edge lines between nodes (shard 3)
Error: �[2mexpect(�[22m�[31mBuffer�[39m�[2m).�[22mtoMatchSnapshot�[2m(�[22m�[32mexpected�[39m�[2m)�[22m failed

  Expected an image 6786px by 2520px, received 4986px by 2697px. 

  Snapshot: lineage-export-with-edges.png

🟡 11 flaky test(s) (passed on retry)
  • Features/ColumnBulkOperations.spec.ts › should not reset stats to zero while search request is loading (shard 2, 1 retry)
  • Features/DataQuality/ColumnLevelTests.spec.ts › Column Values To Be Not In Set (shard 2, 1 retry)
  • Pages/CustomProperties.spec.ts › Timestamp (shard 4, 1 retry)
  • Pages/CustomProperties.spec.ts › Entity Reference (shard 4, 2 retries)
  • Pages/CustomProperties.spec.ts › Set enum custom property on column and verify in UI (shard 4, 2 retries)
  • Pages/Domains.spec.ts › Verify domain data products count includes subdomain data products (shard 4, 1 retry)
  • Pages/ExplorePageRightPanel_KnowledgeCenter.spec.ts › Should remove user owner for knowledgeCenter (shard 5, 1 retry)
  • Pages/Lineage/DataAssetLineage.spec.ts › Column lineage for table -> container (shard 6, 1 retry)
  • Pages/Lineage/DataAssetLineage.spec.ts › Column lineage for searchIndex -> container (shard 6, 1 retry)
  • Pages/Lineage/LineageFilters.spec.ts › Verify lineage schema filter selection (shard 6, 1 retry)
  • Pages/UserDetails.spec.ts › Admin user can get all the roles hierarchy and edit roles (shard 6, 1 retry)

📦 Download artifacts

How to debug locally
# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip    # view trace

BRANDES_KOEPF aligned a node to one child (top-biased), so a source with
children Y and Z sat parallel to Y instead of vertically centered. Switch
node placement to NETWORK_SIMPLEX, which assigns cross-axis coordinates by
minimizing weighted edge deviation, keeping a source balanced between its
children.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
NETWORK_SIMPLEX (and bare Brandes-Köpf) resolve a symmetric source's
placement to a top-aligned corner because all alignments tie on edge length,
so the source did not sit centered between its upstream/downstream branches.
Setting elk.layered.nodePlacement.bk.fixedAlignment to BALANCED averages the
four extreme alignments into a centroid, restoring vertical centering while
keeping edge-aware, straight-segment placement.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ulixius9
ulixius9 previously approved these changes Jun 22, 2026
Rohit0301
Rohit0301 previously approved these changes Jun 22, 2026
chirag-madlani and others added 3 commits June 23, 2026 12:16
The new BALANCED Brandes-Köpf placement repositions nodes (source nodes now
sit vertically centered among their children), so the exported lineage PNG no
longer matches the old reference. Updated the snapshot to the new layout;
edges remain present, so the regression guard for Issue #29124 still holds.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@chirag-madlani chirag-madlani dismissed stale reviews from ulixius9 and Rohit0301 via 7aff489 June 23, 2026 06:49
@gitar-bot

gitar-bot Bot commented Jun 23, 2026

Copy link
Copy Markdown
Code Review ✅ Approved

Removes ELK partitioning to resolve visual lineage graph misalignment and cyclic graph crashes, transitioning to topology-driven layering with the BRANDES_KOEPF placement strategy. Updated unit tests confirm the new layout configuration is correctly implemented.

Options

Display: compact → Showing less information.

Comment with these commands to change:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

safe to test Add this label to run secure Github workflows on PRs To release Will cherry-pick this PR into the release branch UI UI specific issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

UI - enhance lineage rendering to show lineage without crossing edges

3 participants