Skip to content

Commit 8538a72

Browse files
authored
Rewrite recursion into iteration (#26175)
This helps to avoid RecursionError when viewing the graph view of a dag with many tasks
1 parent 55928b9 commit 8538a72

File tree

2 files changed

+30
-4
lines changed

2 files changed

+30
-4
lines changed

airflow/www/views.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -597,11 +597,16 @@ def collect_edges(task_group):
597597
edges = set()
598598

599599
def get_downstream(task):
600-
for child in task.downstream_list:
601-
edge = (task.task_id, child.task_id)
602-
if edge not in edges:
600+
tasks_to_trace = task.downstream_list
601+
while tasks_to_trace:
602+
tasks_to_trace_next: Set[str] = set()
603+
for child in tasks_to_trace:
604+
edge = (task.task_id, child.task_id)
605+
if edge in edges:
606+
continue
607+
tasks_to_trace_next.update(child.downstream_list)
603608
edges.add(edge)
604-
get_downstream(child)
609+
tasks_to_trace = tasks_to_trace_next
605610

606611
for root in dag.roots:
607612
get_downstream(root)

tests/www/views/test_views_tasks.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -970,3 +970,24 @@ def test_task_fail_duration(app, admin_client, dag_maker, session):
970970
assert resp.status_code == 200
971971
assert sorted(item["key"] for item in cumulative_chart) == ["fail", "success"]
972972
assert sorted(item["key"] for item in line_chart) == ["fail", "success"]
973+
974+
975+
def test_graph_view_doesnt_fail_on_recursion_error(app, dag_maker, admin_client):
976+
"""Test that the graph view doesn't fail on a recursion error."""
977+
from airflow.utils.helpers import chain
978+
979+
with dag_maker('test_fails_with_recursion') as dag:
980+
981+
tasks = [
982+
BashOperator(
983+
task_id=f"task_{i}",
984+
bash_command="echo test",
985+
)
986+
for i in range(1, 1000 + 1)
987+
]
988+
chain(*tasks)
989+
with unittest.mock.patch.object(app, 'dag_bag') as mocked_dag_bag:
990+
mocked_dag_bag.get_dag.return_value = dag
991+
url = f'/dags/{dag.dag_id}/graph'
992+
resp = admin_client.get(url, follow_redirects=True)
993+
assert resp.status_code == 200

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy