Skip to content

Commit 4811f41

Browse files
hkc-8010claude
andcommitted
Use min(start_date) for the task-reschedules start_date route
ti_run now returns the earliest reschedule start date via min(start_date). Use the same definition in GET /task-reschedules/{ti_id}/start_date instead of picking the first row by id, so the two cannot drift apart. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 65a9a8c commit 4811f41

2 files changed

Lines changed: 28 additions & 9 deletions

File tree

‎airflow-core/src/airflow/api_fastapi/execution_api/routes/task_reschedules.py‎

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from uuid import UUID
2121

2222
from fastapi import APIRouter, Security, status
23-
from sqlalchemy import select
23+
from sqlalchemy import func, select
2424

2525
from airflow.api_fastapi.common.db.common import AsyncSessionDep
2626
from airflow.api_fastapi.common.types import UtcDateTime
@@ -42,11 +42,6 @@
4242
@router.get("/{task_instance_id}/start_date")
4343
async def get_start_date(task_instance_id: UUID, session: AsyncSessionDep) -> UtcDateTime | None:
4444
"""Get the first reschedule date if found, None if no records exist."""
45-
start_date = await session.scalar(
46-
select(TaskReschedule.start_date)
47-
.where(TaskReschedule.ti_id == task_instance_id)
48-
.order_by(TaskReschedule.id.asc())
49-
.limit(1)
45+
return await session.scalar(
46+
select(func.min(TaskReschedule.start_date)).where(TaskReschedule.ti_id == task_instance_id)
5047
)
51-
52-
return start_date

‎airflow-core/tests/unit/api_fastapi/execution_api/versions/head/test_task_instances.py‎

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
import re
2121
from contextlib import nullcontext
22-
from datetime import datetime
22+
from datetime import datetime, timedelta
2323
from types import SimpleNamespace
2424
from typing import TYPE_CHECKING
2525
from unittest import mock
@@ -3932,6 +3932,30 @@ def test_get_start_date(self, client, session, create_task_instance):
39323932
assert response.status_code == 200
39333933
assert response.json() == "2024-01-01T00:00:00Z"
39343934

3935+
def test_get_start_date_returns_earliest_not_first_inserted(self, client, session, create_task_instance):
3936+
ti = create_task_instance(
3937+
task_id="test_get_start_date_returns_earliest_not_first_inserted",
3938+
state=State.RUNNING,
3939+
start_date=timezone.datetime(2024, 1, 1),
3940+
session=session,
3941+
)
3942+
# Insert the later reschedule first so that ordering by id and by start_date disagree
3943+
for start_date in (timezone.datetime(2024, 1, 2), timezone.datetime(2024, 1, 1)):
3944+
session.add(
3945+
TaskReschedule(
3946+
ti_id=ti.id,
3947+
start_date=start_date,
3948+
end_date=start_date + timedelta(hours=1),
3949+
reschedule_date=start_date + timedelta(hours=2),
3950+
)
3951+
)
3952+
session.flush()
3953+
session.commit()
3954+
3955+
response = client.get(f"/execution/task-reschedules/{ti.id}/start_date")
3956+
assert response.status_code == 200
3957+
assert response.json() == "2024-01-01T00:00:00Z"
3958+
39353959
def test_get_start_date_not_found(self, client):
39363960
ti_id = "0182e924-0f1e-77e6-ab50-e977118bc139"
39373961
response = client.get(f"/execution/task-reschedules/{ti_id}/start_date")

0 commit comments

Comments
 (0)