Skip to content

Commit bd19bf8

Browse files
rawwarephraimbuddy
andauthored
include limit and offset in request body schema for List task instances (batch) endpoint (#43479)
* include limit and offset in request body schema for List task instances (batch) endpoint (#42870) * add offset and limit * add offset and limit * add offset and limit * add tests * add test for default offset and limit * fix * Update airflow/api_connexion/endpoints/task_instance_endpoint.py Co-authored-by: Ephraim Anierobi <[email protected]> * Update tests/api_connexion/endpoints/test_task_instance_endpoint.py Co-authored-by: Ephraim Anierobi <[email protected]> * fix test --------- Co-authored-by: Ephraim Anierobi <[email protected]> (cherry picked from commit 7b85d4e) Signed-off-by: kalyanr <[email protected]> * remove spaces --------- Signed-off-by: kalyanr <[email protected]> Co-authored-by: Ephraim Anierobi <[email protected]>
1 parent 72947cb commit bd19bf8

File tree

4 files changed

+67
-0
lines changed

4 files changed

+67
-0
lines changed

airflow/api_connexion/endpoints/task_instance_endpoint.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,7 @@ def get_task_instances_batch(session: Session = NEW_SESSION) -> APIResponse:
453453
ti_query = base_query.options(
454454
joinedload(TI.rendered_task_instance_fields), joinedload(TI.task_instance_note)
455455
)
456+
ti_query = ti_query.offset(data["page_offset"]).limit(data["page_limit"])
456457
# using execute because we want the SlaMiss entity. Scalars don't return None for missing entities
457458
task_instances = session.execute(ti_query).all()
458459

airflow/api_connexion/openapi/v1.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5097,6 +5097,15 @@ components:
50975097
ListTaskInstanceForm:
50985098
type: object
50995099
properties:
5100+
page_offset:
5101+
type: integer
5102+
minimum: 0
5103+
description: The number of items to skip before starting to collect the result set.
5104+
page_limit:
5105+
type: integer
5106+
minimum: 1
5107+
default: 100
5108+
description: The numbers of items to return.
51005109
dag_ids:
51015110
type: array
51025111
items:

airflow/www/static/js/types/api-generated.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2233,6 +2233,13 @@ export interface components {
22332233
end_date_lte?: string;
22342234
};
22352235
ListTaskInstanceForm: {
2236+
/** @description The number of items to skip before starting to collect the result set. */
2237+
page_offset?: number;
2238+
/**
2239+
* @description The numbers of items to return.
2240+
* @default 100
2241+
*/
2242+
page_limit?: number;
22362243
/**
22372244
* @description Return objects with specific DAG IDs.
22382245
* The value can be repeated to retrieve multiple matching values (OR condition).

tests/api_connexion/endpoints/test_task_instance_endpoint.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,56 @@ def test_should_raise_400_for_naive_and_bad_datetime(self, payload, expected, se
11061106
assert response.status_code == 400
11071107
assert expected in response.json["detail"]
11081108

1109+
def test_should_respond_200_for_pagination(self, session):
1110+
dag_id = "example_python_operator"
1111+
1112+
self.create_task_instances(
1113+
session,
1114+
task_instances=[
1115+
{"start_date": DEFAULT_DATETIME_1 + dt.timedelta(minutes=(i + 1))} for i in range(10)
1116+
],
1117+
dag_id=dag_id,
1118+
)
1119+
1120+
# First 5 items
1121+
response_batch1 = self.client.post(
1122+
"/api/v1/dags/~/dagRuns/~/taskInstances/list",
1123+
environ_overrides={"REMOTE_USER": "test"},
1124+
json={"page_limit": 5, "page_offset": 0},
1125+
)
1126+
assert response_batch1.status_code == 200, response_batch1.json
1127+
num_entries_batch1 = len(response_batch1.json["task_instances"])
1128+
assert num_entries_batch1 == 5
1129+
assert len(response_batch1.json["task_instances"]) == 5
1130+
1131+
# 5 items after that
1132+
response_batch2 = self.client.post(
1133+
"/api/v1/dags/~/dagRuns/~/taskInstances/list",
1134+
environ_overrides={"REMOTE_USER": "test"},
1135+
json={"page_limit": 5, "page_offset": 5},
1136+
)
1137+
assert response_batch2.status_code == 200, response_batch2.json
1138+
num_entries_batch2 = len(response_batch2.json["task_instances"])
1139+
assert num_entries_batch2 > 0
1140+
assert len(response_batch2.json["task_instances"]) > 0
1141+
1142+
# Match
1143+
ti_count = 9
1144+
assert response_batch1.json["total_entries"] == response_batch2.json["total_entries"] == ti_count
1145+
assert (num_entries_batch1 + num_entries_batch2) == ti_count
1146+
assert response_batch1 != response_batch2
1147+
1148+
# default limit and offset
1149+
response_batch3 = self.client.post(
1150+
"/api/v1/dags/~/dagRuns/~/taskInstances/list",
1151+
environ_overrides={"REMOTE_USER": "test"},
1152+
json={},
1153+
)
1154+
1155+
num_entries_batch3 = len(response_batch3.json["task_instances"])
1156+
assert num_entries_batch3 == ti_count
1157+
assert len(response_batch3.json["task_instances"]) == ti_count
1158+
11091159

11101160
class TestPostClearTaskInstances(TestTaskInstanceEndpoint):
11111161
@pytest.mark.parametrize(

0 commit comments

Comments
 (0)