ZhiyaD opened a new issue, #73710:
URL: https://github.com/apache/airflow/issues/73710

   ### Apache Airflow version
   
   3.3.1
   
   ### What happened?
   
   When clearing a task instance for a specific Dag run with **both** 
`include_upstream` and `include_downstream` enabled (the "Upstream" + 
"Downstream" toggles in the Clear Task Instance dialog, or `POST 
/api/v2/dags/{dag_id}/clearTaskInstances` with a `dag_run_id`), Airflow also 
selects tasks that are neither upstream nor downstream of the selected task.
   
   The downstream traversal starts from the selected task **plus all of its 
upstream tasks**, so it picks up every descendant of those ancestors. In a Dag 
where all branches hang off a shared root task, selecting both options on any 
task selects every task instance in the run. On a large Dag (~1,300 tasks) this 
made the dialog propose clearing the entire run instead of one branch.
   
   Selecting only Upstream, or only Downstream, returns the expected set.
   
   ### What you think should happen instead?
   
   Upstream + Downstream should return the union of the task's own ancestors 
and the task's own descendants (the Airflow 2 behaviour), not the descendants 
of its ancestors.
   
   ### How to reproduce
   
   ```python
   from airflow.sdk import DAG
   from airflow.providers.standard.operators.empty import EmptyOperator
   
   with DAG("clear_repro", schedule=None):
       root = EmptyOperator(task_id="root")
       a = EmptyOperator(task_id="a")
       b = EmptyOperator(task_id="b")
       other = EmptyOperator(task_id="other")
       root >> a >> b
       root >> other
   ```
   
   Trigger a run (`run1`), then dry-run a clear of task `a`:
   
   ```
   POST /api/v2/dags/clear_repro/clearTaskInstances
   {"dag_run_id": "run1", "task_ids": ["a"], "include_upstream": ..., 
"include_downstream": ...,
    "only_failed": false, "dry_run": true}
   ```
   
   Result on 3.3.1:
   
   | include_upstream | include_downstream | returned task_ids | expected |
   |---|---|---|---|
   | true | false | a, root | a, root |
   | false | true | a, b | a, b |
   | true | true | **a, b, other, root** | a, b, root |
   
   `other` is neither upstream nor downstream of `a`.
   
   ### Operating System
   
   Debian (official `apache/airflow:slim-3.3.1-python3.12` image); reproduced 
locally on macOS with SQLite.
   
   ### Versions of Apache Airflow Providers
   
   apache-airflow-providers-standard 1.18.0 (not relevant to the bug)
   
   ### Deployment
   
   Other Docker-based deployment (Kubernetes, KubernetesExecutor)
   
   ### Deployment details
   
   _No response_
   
   ### Anything else?
   
   It looks like this comes from the `dag_run_id` branch of 
`post_clear_task_instances` 
(`airflow/api_fastapi/core_api/routes/public/task_instances.py`):
   
   ```python
   if upstream:
       _collect_relatives(dag_run_id, "upstream")
   if downstream:
       _collect_relatives(dag_run_id, "downstream")
   ```
   
   Both calls update `normal_task_ids` in place, so the downstream pass starts 
from the set that already contains the upstream tasks. Before #57758 (3.1.4), a 
single `dag.partial_subset(include_upstream=..., include_downstream=...)` 
computed both directions from the original task. The code on `main` looks the 
same.
   
   A possible fix: run both directions from a copy of the original seed set and 
union the results, plus a test that enables both flags together.
   
   Workaround: clear twice, once with Upstream only and once with Downstream 
only.
   
   ### Are you willing to submit PR?
   
   - [ ] Yes I am willing to submit a PR!
   
   ### Code of Conduct
   
   - [x] I agree to follow this project's Code of Conduct
   


-- 
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]

Reply via email to