vatsrahul1001 opened a new pull request, #67720:
URL: https://github.com/apache/airflow/pull/67720
Closes #67714.
## What was broken
Open `@task_group` rendered with vertically-stacked internals and edges
crossing the boundary in confusing ways whenever an internal task had a direct
dependency on a node outside the group (an "escape edge" that bypassed the
group's entry/exit interface). Dag execution was unaffected — purely a UI
rendering issue.
The reporter's minimal repro: with only `entry`/`exit` wired across the
group boundary, Graph view rendered correctly. Adding two lines like
`group_result["a2"] >> final_task_result` made the group's children stack
vertically and dependency edges wrap around the boundary.
## Root cause
Two interacting bugs in the ELK graph-layout refactor from #65031:
1. **`hasUniformExternalConnectivity` was too lenient.** It fired whenever
externally-connected children separately shared the same external *sources* OR
the same external *targets*, instead of the canonical fan-in/fan-out pattern
where every child has the same full `(sources, targets)` profile. The
reporter's group had `a1` as an "entry" (external source `{start}`) and
`a2`/`a3`/`group_done` as "exits" (external target `{final_task}`) — different
profiles per child. The lenient check still returned `true`, triggering the
collapse path on a group where the author had deliberately wired explicit
escape edges.
2. **`rewriteGroupEdges` was tuned for closed groups.** When the collapse
path fired on an *open* group, it dropped all of the group's internal edges —
leaving ELK with no internal-layout information for the children. That's what
produced the vertical stacking.
## Fix
* Tighten `hasUniformExternalConnectivity` to require every
externally-connected child to share the same full `(sources, targets)` profile.
Mixed entry/exit shapes (like the reporter's repro) now fall back to rendering
individual crossing edges, preserving the author's explicit dependency intent.
The canonical "cleanup group" fan-in/fan-out pattern that the optimization was
designed for (every child has same upstream AND same downstream) still triggers
the collapse.
* Add a `preserveInternal` option to `rewriteGroupEdges`. The open-group
call site sets it so the collapse optimization preserves internal edges for the
subsequent extraction loop; the closed-group call site keeps the default (drop
internals — they're not laid out when the group is collapsed).
## Tests
New `elkGraphUtils.test.ts` covers:
- `hasUniformExternalConnectivity` — vanilla TaskGroup, mixed-profile #67714
trigger, canonical fan-in/fan-out
- `generateElkGraph` for the #67714 repro: internal edges preserved AND
escape edges rendered individually
- `generateElkGraph` for the canonical fan-in/fan-out shape: collapse still
fires, internal edges kept (exercises `preserveInternal: true`)
- `generateElkGraph` regression guards: simple open TaskGroup, closed
TaskGroup
Verified the new tests fail against `main` without the fix and pass with it.
## Risk
Targeted change to one file plus its new test. No API or schema changes.
Behaviour change boundary is `hasUniformExternalConnectivity`'s return value on
mixed-profile groups, which previously collapsed to a group-level edge and now
renders individual edges. Closed groups and canonical fan-in/fan-out groups
behave identically to before.
cc @bbovenzi (author of #65031, original Graph-layout refactor)
--
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]