kaxil commented on code in PR #72811:
URL: https://github.com/apache/airflow/pull/72811#discussion_r3972719248


##########
airflow-core/src/airflow/api_fastapi/execution_api/routes/task_instances.py:
##########
@@ -1213,7 +1213,7 @@ def get_previous_task_instance(
     query = (
         select(TI)
         .join(DR, (TI.dag_id == DR.dag_id) & (TI.run_id == DR.run_id))
-        .options(joinedload(TI.dag_run))
+        .options(contains_eager(TI.dag_run))

Review Comment:
   Since the response only reads `ti.dag_run.logical_date`, 
`contains_eager(TI.dag_run).load_only(DR.logical_date)` trims this further. 
Compiling all three shapes locally: the dag_run side goes from 28 columns 
(including the undeferred `conf` JSON) down to 2, and the whole SELECT from 66 
columns to 40. Same shape the scheduler uses in 
[scheduler_job_runner.py#L826-L830](https://github.com/apache/airflow/blob/251cd91bb24a335f9ec320ec1b3f2929f9e4577c/airflow-core/src/airflow/jobs/scheduler_job_runner.py#L826-L830).



##########
airflow-core/tests/unit/api_fastapi/execution_api/versions/head/test_task_instances.py:
##########
@@ -3884,6 +3886,32 @@ def test_get_previous_ti_with_all_filters(self, client, 
session, create_task_ins
         assert data["run_id"] == "target_run_1"
         assert data["state"] == State.SUCCESS
 
+    def test_get_previous_ti_joins_dag_run_once(self, client, session, 
create_task_instance):
+        """The eager-load of ``TI.dag_run`` must reuse the explicit ORDER BY 
join, not add a
+        second parallel ``JOIN dag_run AS dag_run_1``."""
+        for i in range(3):
+            create_task_instance(
+                task_id="test_task",
+                state=State.SUCCESS,
+                logical_date=timezone.datetime(2025, 1, i + 1),
+                run_id=f"run{i + 1}",
+            )
+        session.commit()
+
+        with capture_orm_selects("task_instance") as statements:
+            response = client.get(
+                "/execution/task-instances/previous/dag/test_task",
+                params={"logical_date": "2025-01-03T00:00:00Z"},
+            )
+
+        assert response.status_code == 200

Review Comment:
   The compiled shape is data-independent, so this passes even when the lookup 
returns `null`, and the three TIs above aren't contributing to the assertion. 
`logical_date` is the one response field sourced from the eager-loaded 
`dag_run`, so asserting it here would cover the half of the change the SQL text 
can't see.



##########
airflow-core/tests/unit/api_fastapi/execution_api/versions/head/test_task_instances.py:
##########
@@ -3884,6 +3886,32 @@ def test_get_previous_ti_with_all_filters(self, client, 
session, create_task_ins
         assert data["run_id"] == "target_run_1"
         assert data["state"] == State.SUCCESS
 
+    def test_get_previous_ti_joins_dag_run_once(self, client, session, 
create_task_instance):

Review Comment:
   This branch is based on 428e873c, before #72699, so the new test lands 
exactly where `test_get_previous_ti_query_is_bounded` sits on main and `git 
merge-tree upstream/main` conflicts on this file (the route file auto-merges 
cleanly, `.limit(1)` and the loader option are different lines). Worth deciding 
on the rebase whether the join-count assert folds into that test, since the 
setup and the `capture_orm_selects` call are identical.



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