sjyangkevin opened a new pull request, #74548:
URL: https://github.com/apache/airflow/pull/74548

   ### Why
   
   closes: #73710
   
   Clearing a task instance in a specific Dag run with both **Upstream** and 
**Downstream** enabled (the Clear dialog toggles, or `POST 
/api/v2/dags/{dag_id}/clearTaskInstances` with a `dag_run_id`) also selected 
tasks that are neither upstream nor downstream of the selected task.
   
   For a specific Dag run, `post_clear_task_instances` resolves relatives one 
direction at a time with `find_relevant_relatives`, and each pass added its 
results to the selection immediately. The upstream pass ran first and grew the 
selection, so the downstream pass started from the selected task **and its 
upstream tasks**, and returned every descendant of those upstream tasks.
   
   With the Dag from the issue (`root >> a >> b`, `root >> other`), clearing 
`a` with both options:
   
   | | upstream pass | downstream pass | selected |
   |---|---|---|---|
   | `main` | from `{a}` → `root` | from `{a, root}` → `a, b, other` | `a, b, 
other, root` |
   | this PR | from `{a}` → `root` | from `{a}` → `b` | `a, b, root` |
   
   As a result:
   
   - When the Dag's branches share a root task, clearing any task this way 
selects the whole Dag run.
   - For a mapped task, selecting a single map index (`a[0]`) also selected 
**every** map index of `a`, because the downstream pass from `root` returned 
`a` as a whole task, which replaces the specific map index.
   
   Clearing with only Upstream or only Downstream was not affected.
   
   ### Approach
   
   Both passes now start from the tasks in the request, and their results are 
merged into the selection only after both have run. This gives the same result 
as clearing without a `dag_run_id` (`partial_subset(include_upstream=..., 
include_downstream=...)`) and as marking a task success/failed with upstream 
and downstream. `find_relevant_relatives` itself is unchanged.
   
   ### Why this does not introduce a regression
   
   - **Single-direction clears are unchanged.** With one option set there is 
still exactly one `find_relevant_relatives` call with the same, unmodified 
input; only the place where its result is merged moved.
   - **With both options the selection can only shrink.** Before: `selected ∪ 
up(selected) ∪ down(selected ∪ up(selected))`. After: `selected ∪ up(selected) 
∪ down(selected)`. The tasks dropped are exactly descendants of upstream tasks 
that are not relatives of the selected task.
   - **Nothing that has to be cleared is dropped.** Setup/teardown handling 
never relied on the old seeding: the upstream pass already includes the 
teardowns of upstream setups (`get_upstreams_follow_setups`), and the 
downstream pass adds the setups/teardowns of downstream tasks 
(`partial_subset`). Map index resolution in `find_relevant_relatives` is 
untouched.
   - **No API surface change.** Request/response models, the generated OpenAPI 
spec, the path without `dag_run_id` and the UI code are unchanged.
   
   ### Testing
   
   **Unit tests**
   
   - Added `test_clear_with_upstream_and_downstream_excludes_unrelated_tasks`, 
parametrized for an unmapped selection (`a`) and a mapped one (`a[0]`). On 
`main` both fail (extra `other`; extra `a[1]`, `a[2]` and `other`); with this 
change both pass.
   - Ran the selection from `breeze verify` in Breeze (Python 3.11, SQLite), 
one suite at a time:
     - Core `API` DB tests: 3743 passed, 10 skipped
     - Core `Always` DB tests: 1891 passed, 3 skipped
     - Core non-DB tests: 4823 passed, 11 skipped, 2 xfailed
     - `fab` provider: 407 DB and 296 non-DB tests passed, 5 skipped
     - `common.compat` provider: 283 passed, 11 skipped
   - Static checks through prek on the changed files: ruff, ruff-format, mypy 
(`airflow-core`, `devel-common`) and OpenAPI spec generation (spec unchanged).
   
   **Manual testing in Breeze** (`breeze start-airflow --dev-mode`), Clear 
dialog with Upstream + Downstream enabled (screenshots below):
   
   - Issue's Dag (`root >> a >> b`, `root >> other`), clearing `a`: selects `a, 
b, root`.
   - `start` fanning out to three `extract >> transform >> load` pipelines, 
clearing `transform_sales`: selects only the four `sales`-pipeline tasks 
(`start`, `extract_sales`, `transform_sales`, `load_sales`) instead of the 
whole run.
   - Issue's Dag with `a` mapped over 3 inputs, clearing `a[0]`: selects `a[0], 
b, root`.
   
   The same three Dags were also checked through the REST API (dry run) against 
a running API server: with both options the results match the above, and 
Upstream-only and Downstream-only results are identical to `main`.
   
   <img width="1273" height="664" alt="Screenshot from 2026-10-10 16-05-09" 
src="https://github.com/user-attachments/assets/5e878cf4-f249-4da6-b729-83d20a8d5671";
 />
   
   <img width="1273" height="664" alt="Screenshot from 2026-10-10 16-06-35" 
src="https://github.com/user-attachments/assets/289b5b2f-beff-4103-937c-c77c74f59876";
 />
   
   <img width="1273" height="664" alt="Screenshot from 2026-10-10 16-07-40" 
src="https://github.com/user-attachments/assets/3406b78d-d94e-4946-b9ec-7831db5800b3";
 />
   
   ---
   
   ##### Was generative AI tooling used to co-author this PR?
   
   - [X] Yes (please specify the tool below)
   
   Generated-by: Claude Code (Opus 5.5) following [the 
guidelines](https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions)
   
   ---
   
   * Read the **[Pull Request 
Guidelines](https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#pull-request-guidelines)**
 for more information. Note: commit author/co-author name and email in commits 
become permanently public when merged.
   * For fundamental code changes, an Airflow Improvement Proposal 
([AIP](https://cwiki.apache.org/confluence/display/AIRFLOW/Airflow+Improvement+Proposals))
 is needed.
   * When adding dependency, check compliance with the [ASF 3rd Party License 
Policy](https://www.apache.org/legal/resolved.html#category-x).
   * For significant user-facing changes create newsfragment: 
`{pr_number}.significant.rst`, in 
[airflow-core/newsfragments](https://github.com/apache/airflow/tree/main/airflow-core/newsfragments).
 You can add this file in a follow-up commit after the PR is created so you 
know the PR number.
   


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