Skip to content

Restoring include_downstream_dags logic to clear downstream Dags#65314

Open
jroachgolf84 wants to merge 11 commits into
apache:mainfrom
jroachgolf84:issue-61451
Open

Restoring include_downstream_dags logic to clear downstream Dags#65314
jroachgolf84 wants to merge 11 commits into
apache:mainfrom
jroachgolf84:issue-61451

Conversation

@jroachgolf84

@jroachgolf84 jroachgolf84 commented Apr 15, 2026

Copy link
Copy Markdown
Collaborator

Description

Restoring behavior to clear downstream DAGs when a Task state is cleared (if applicable).

closes: #61451

Testing

Unit-tests were added/updated to test these changes. The changes were also tested E2E.

Unit Tests

The unit-tests added/updated as part of this effort can be found in these files:

  • airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_task_instances.py
  • airflow-core/tests/unit/serialization/definitions/test_dag.py

These tests can be executed using the commands below:

breeze testing core-tests airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_task_instances.py

breeze testing core-tests airflow-core/tests/unit/serialization/definitions/test_dag.py

E2E Testing

The DAG below was used to test the changes int his PR. This DAG is made up of a parent and child DAG. The ExternalTaskMarker Operator is cleared in the parent DAG, the downstream Tasks in the child DAG are also cleared. That's showed in the video below.

from airflow.providers.standard.operators.bash import BashOperator
from airflow.providers.standard.sensors.external_task import ExternalTaskMarker, ExternalTaskSensor
from airflow.sdk import DAG

from datetime import datetime


with DAG(
    dag_id="parent_dag_61451",
    start_date=datetime(2026, 1, 18),
    schedule="@daily",
    catchup=False,
    tags=["issue-61451"],
) as parent_dag:
    parent_echo = BashOperator(
        task_id="parent_echo",
        bash_command="echo parent_dag_61451",
    )

    trigger_child = ExternalTaskMarker(
        task_id="trigger_child",
        external_dag_id="child_dag_61451",
        external_task_id="receive_call_from_parent",
    )

    parent_echo >> trigger_child

with DAG(
    dag_id="child_dag_61451",
    start_date=datetime(2026, 1, 18),
    schedule="@daily",
    catchup=False,
    tags=["issue-61451"],
) as child_dag:
    receive_call_from_parent = ExternalTaskSensor(
        task_id="receive_call_from_parent",
        external_dag_id="parent_dag_61451",
        external_task_id="trigger_child",
        poke_interval=5,
    )

    child_echo = BashOperator(
        task_id="child_echo",
        bash_command="echo DONE",
    )

    receive_call_from_parent >> child_echo

Video

issue-61451-include-downstream-tasks.mov

@LinasData

Copy link
Copy Markdown

Hey, any updates on this?

@jroachgolf84

Copy link
Copy Markdown
Collaborator Author

@jason810496 - can you take a look at this one for me?

@jroachgolf84

Copy link
Copy Markdown
Collaborator Author

@bugraoz93 - do you mind taking a look at this one?

Comment thread airflow-core/src/airflow/serialization/definitions/dag.py
Comment thread airflow-core/src/airflow/serialization/definitions/dag.py Outdated
Comment thread airflow-core/src/airflow/serialization/definitions/dag.py Outdated
Comment thread airflow-core/src/airflow/serialization/definitions/dag.py Outdated
@kaxil kaxil changed the title issue-61451: Restoring include_downstream_dags logic Restoring include_downstream_dags logic to clear downstream Dags Jun 26, 2026
@jroachgolf84
jroachgolf84 requested a review from henry3260 as a code owner July 6, 2026 13:29
@jroachgolf84
jroachgolf84 requested a review from kaxil July 6, 2026 13:29
@jroachgolf84

Copy link
Copy Markdown
Collaborator Author

@kaxil - do you mind taking another look?

@eladkal eladkal added this to the Airflow 3.4.0 milestone Jul 17, 2026
@eladkal eladkal added the type:improvement Changelog: Improvements label Jul 17, 2026

@eladkal eladkal left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Overall LGTM
but needs 2nd eye from @kaxil

Comment thread airflow-core/src/airflow/serialization/definitions/dag.py
Comment thread airflow-core/src/airflow/api_fastapi/core_api/routes/public/task_instances.py Outdated
Comment thread airflow-core/src/airflow/serialization/definitions/dag.py
@github-actions

github-actions Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

uv.lock on main just moved via #70217 ("[main] Upgrade important CI environment"), commit 97515b5 and this PR currently conflicts.

Quickest fix:

git fetch upstream main && git rebase upstream/main
rm uv.lock && uv lock
git add uv.lock && git rebase --continue
git push --force-with-lease

Automated nudge — ignore if you're not ready to rebase. This comment is updated in place on future uv.lock bumps.

Comment thread airflow-core/newsfragments/65314.improvement.rst Outdated
@jroachgolf84
jroachgolf84 requested a review from XD-DENG as a code owner July 22, 2026 03:08
@jroachgolf84
jroachgolf84 requested a review from kaxil July 22, 2026 03:09
@jroachgolf84

Copy link
Copy Markdown
Collaborator Author

@kaxil - feedback implemented. Do you mind taking another look? Thanks!

@Lee-W Lee-W left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Mostly nits, but overall this looks good. The CI failure is unrelated—rebasing on the main branch should fix it.

Comment thread airflow-core/src/airflow/api_fastapi/core_api/datamodels/task_instances.py Outdated
Comment thread airflow-core/src/airflow/api_fastapi/core_api/routes/public/task_instances.py Outdated
Comment thread airflow-core/src/airflow/api_fastapi/core_api/routes/public/task_instances.py Outdated
Comment thread airflow-core/src/airflow/api_fastapi/core_api/routes/public/task_instances.py Outdated
Comment thread airflow-core/src/airflow/api_fastapi/core_api/routes/public/task_instances.py Outdated
Comment thread airflow-core/tests/unit/serialization/definitions/test_dag.py Outdated
Comment thread airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_task_instances.py Outdated
Comment thread airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_task_instances.py Outdated
)

assert response.status_code == 404
assert "child_dag" in response.json()["detail"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

let's check the full message

@mock.patch("airflow.serialization.definitions.dag.SerializedDAG.clear")
def test_invalid_external_task_marker_logical_date_returns_400(self, mock_clear, test_client, session):
"""A non-ISO logical_date rendered from an ExternalTaskMarker template must return 400, not 500."""
from pendulum.parsing.exceptions import ParserError

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

let's move it to the top

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

@Lee-W - do you mean the import?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yep

jroachgolf84 and others added 2 commits July 22, 2026 23:22
Co-authored-by: Wei Lee <hello@wei-lee.me>
Co-authored-by: Wei Lee <hello@wei-lee.me>
raise HTTPException(status.HTTP_404_NOT_FOUND, str(e)) from e

if include_dependent_dags:
# Ensure proper access to downstream dags/tasks with dag.clear and include_dependent_dags

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
# Ensure proper access to downstream dags/tasks with dag.clear and include_dependent_dags
# Ensure proper access to downstream Dags/tasks with dag.clear and include_dependent_dags



def test_clear_raises_when_recursion_depth_exceeded(dag_maker, session):
"""AirflowException is raised when the dependency chain depth exceeds recursion_depth."""

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should it be MaxRecursionDepthError instead?

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

Labels

area:API Airflow's REST/HTTP API area:DAG-processing ready for maintainer review Set after triaging when all criteria pass. type:improvement Changelog: Improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

I am upgrading from Airflow 2.11.0 to Airflow 3.1.6 and noticed a change in behavior regarding the ExternalTaskMarker

5 participants