Skip to content

Commit 13f3e26

Browse files
authored
Unique run_id across manually triggered Dags with schedules (#59477)
* run id no longer collides in manual runs * ruff format;
1 parent d10138d commit 13f3e26

2 files changed

Lines changed: 36 additions & 4 deletions

File tree

  • airflow-core

airflow-core/src/airflow/api_fastapi/core_api/datamodels/dag_run.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,7 @@ def validate_context(self, dag: SerializedDAG) -> dict:
126126
end=timezone.coerce_datetime(self.data_interval_end),
127127
)
128128
else:
129-
data_interval = dag.timetable.infer_manual_data_interval(
130-
run_after=coerced_logical_date or timezone.coerce_datetime(run_after)
131-
)
132-
run_after = data_interval.end
129+
data_interval = dag.timetable.infer_manual_data_interval(run_after=coerced_logical_date)
133130

134131
run_id = self.dag_run_id or dag.timetable.generate_run_id(
135132
run_type=DagRunType.MANUAL,

airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_dag_run.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1892,6 +1892,41 @@ def test_should_respond_200_with_null_logical_date(self, test_client):
18921892
"partition_key": None,
18931893
}
18941894

1895+
@pytest.mark.usefixtures("configure_git_connection_for_dag_bundle")
1896+
def test_should_generate_unique_run_id_for_scheduled_dag(self, dag_maker, test_client, session):
1897+
"Ensure manual triggers on scheduled DAGs don't conflict on run_id"
1898+
scheduled_dag_id = "test_scheduled_dag"
1899+
with dag_maker(
1900+
dag_id=scheduled_dag_id,
1901+
schedule="@daily",
1902+
start_date=START_DATE1,
1903+
session=session,
1904+
serialized=True,
1905+
):
1906+
EmptyOperator(task_id="test_task")
1907+
1908+
session.commit()
1909+
1910+
response_1 = test_client.post(
1911+
f"/dags/{scheduled_dag_id}/dagRuns",
1912+
json={
1913+
"logical_date": "2025-12-11T16:00:00+00:00",
1914+
"run_after": "2025-12-11T16:00:00+00:00",
1915+
},
1916+
)
1917+
assert response_1.status_code == 200
1918+
1919+
response_2 = test_client.post(
1920+
f"/dags/{scheduled_dag_id}/dagRuns",
1921+
json={
1922+
"logical_date": "2025-12-11T16:01:00+00:00",
1923+
"run_after": "2025-12-11T16:01:00+00:00",
1924+
},
1925+
)
1926+
assert response_2.status_code == 200
1927+
1928+
assert response_1.json()["dag_run_id"] != response_2.json()["dag_run_id"]
1929+
18951930
@time_machine.travel("2025-10-02 12:00:00", tick=False)
18961931
@pytest.mark.usefixtures("custom_timetable_plugin")
18971932
def test_custom_timetable_generate_run_id_for_manual_trigger(self, dag_maker, test_client, session):

0 commit comments

Comments
 (0)