This is an automated email from the ASF dual-hosted git repository.

pierrejeambrun pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 2d959316012 Tidy taskgroup topo-sort tests; note why grid group_dict 
is uncached (#70590)
2d959316012 is described below

commit 2d9593160121039725376b6ca69783f7640cb0bf
Author: Jason(Zhe-You) Liu <[email protected]>
AuthorDate: Wed Jul 29 22:04:02 2026 +0800

    Tidy taskgroup topo-sort tests; note why grid group_dict is uncached 
(#70590)
---
 .../src/airflow/api_fastapi/core_api/routes/ui/grid.py        |  5 +++++
 airflow-core/tests/unit/utils/test_task_group.py              | 11 ++++++-----
 2 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/grid.py 
b/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/grid.py
index 2425f67bcc3..13326f68a33 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/grid.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/grid.py
@@ -200,6 +200,11 @@ def get_dag_structure(
     run_ids = list(session.scalars(dag_runs_select_filter))
 
     task_group_sort = get_task_group_children_getter()
+    # Built once per render and passed down, intentionally not 
memoized/LRU-cached: it is a
+    # derived view of a mutable task-group tree, so a cache would go stale 
with no invalidation
+    # and would pin the whole map for the group's lifetime, fighting the 
streaming/expunge below.
+    # It is released when the request returns (explicitly del-eted after the 
latest serdag is
+    # merged on the main path).
     latest_group_dict = latest_dag.task_group.get_task_group_dict()
     if not run_ids:
         nodes = [
diff --git a/airflow-core/tests/unit/utils/test_task_group.py 
b/airflow-core/tests/unit/utils/test_task_group.py
index 04b233a37b3..ea704a2af59 100644
--- a/airflow-core/tests/unit/utils/test_task_group.py
+++ b/airflow-core/tests/unit/utils/test_task_group.py
@@ -1240,8 +1240,8 @@ def test_topological_group_dep_list_syntax():
         groups >> tg_a  # list-based dep — previously produced the wrong order
 
     order = [node.node_id for node in dag.task_group.topological_sort()]
-    a_idx = order.index("a")
-    assert all(order.index(f"b_{x}") < a_idx for x in range(3)), (
+    pos = {node_id: i for i, node_id in enumerate(order)}
+    assert all(pos[f"b_{x}"] < pos["a"] for x in range(3)), (
         f"Expected all b_x before a in topological order, got: {order!r}"
     )
 
@@ -1262,8 +1262,8 @@ def 
test_topological_sort_serialized_list_dep_between_groups():
 
     serialized = create_scheduler_dag(dag)
     order = [node.node_id for node in serialized.task_group.topological_sort()]
-    a_idx = order.index("a")
-    assert all(order.index(f"b_{x}") < a_idx for x in range(3)), (
+    pos = {node_id: i for i, node_id in enumerate(order)}
+    assert all(pos[f"b_{x}"] < pos["a"] for x in range(3)), (
         f"Expected all b_x before a in topological order, got: {order!r}"
     )
 
@@ -1289,8 +1289,9 @@ def 
test_topological_sort_serialized_task_level_cross_group_dep():
 
     serialized = create_scheduler_dag(dag)
     order = [node.node_id for node in serialized.task_group.topological_sort()]
+    pos = {node_id: i for i, node_id in enumerate(order)}
 
-    assert order.index("stage_b") < order.index("stage_a")
+    assert pos["stage_b"] < pos["stage_a"]
 
 
 def 
test_topological_sort_serialized_padded_reverse_chain_uses_pass_numbering(monkeypatch):

Reply via email to