From e3dc30a946fca52a6e7c5ebd839b9edb4dd7e93e Mon Sep 17 00:00:00 2001 From: Wei Lee Date: Wed, 17 Sep 2025 16:32:06 +0900 Subject: [PATCH] feat(hitl): add map_index filter to get_hitl_details endpoint --- .../src/airflow/api_fastapi/common/parameters.py | 10 ++++++++++ .../core_api/openapi/v2-rest-api-generated.yaml | 8 ++++++++ .../api_fastapi/core_api/routes/public/hitl.py | 9 +++++++-- .../src/airflow/ui/openapi-gen/queries/common.ts | 5 +++-- .../ui/openapi-gen/queries/ensureQueryData.ts | 6 ++++-- .../src/airflow/ui/openapi-gen/queries/prefetch.ts | 6 ++++-- .../src/airflow/ui/openapi-gen/queries/queries.ts | 6 ++++-- .../src/airflow/ui/openapi-gen/queries/suspense.ts | 6 ++++-- .../airflow/ui/openapi-gen/requests/services.gen.ts | 2 ++ .../src/airflow/ui/openapi-gen/requests/types.gen.ts | 1 + .../api_fastapi/core_api/routes/public/test_hitl.py | 12 ++++++++---- 11 files changed, 55 insertions(+), 16 deletions(-) diff --git a/airflow-core/src/airflow/api_fastapi/common/parameters.py b/airflow-core/src/airflow/api_fastapi/common/parameters.py index cc7ae250cba66..e801d2d9e79df 100644 --- a/airflow-core/src/airflow/api_fastapi/common/parameters.py +++ b/airflow-core/src/airflow/api_fastapi/common/parameters.py @@ -1007,6 +1007,16 @@ def _optional_boolean(value: bool | None) -> bool | None: ) ), ] +QueryHITLDetailMapIndexFilter = Annotated[ + FilterParam[int | None], + Depends( + filter_param_factory( + TaskInstance.map_index, + int | None, + filter_name="map_index", + ) + ), +] QueryHITLDetailSubjectSearch = Annotated[ _SearchParam, Depends( diff --git a/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml b/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml index 80c8d485df994..f1722ea5ecd16 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml +++ b/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml @@ -8220,6 +8220,14 @@ paths: title: Task Id Pattern description: "SQL LIKE expression \u2014 use `%` / `_` wildcards (e.g. `%customer_%`).\ \ Regular expressions are **not** supported." + - name: map_index + in: query + required: false + schema: + anyOf: + - type: integer + - type: 'null' + title: Map Index - name: state in: query required: false diff --git a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/hitl.py b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/hitl.py index e3f4b59c448be..7aa430ae63074 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/hitl.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/hitl.py @@ -29,6 +29,7 @@ from airflow.api_fastapi.common.parameters import ( QueryHITLDetailBodySearch, QueryHITLDetailDagIdPatternSearch, + QueryHITLDetailMapIndexFilter, QueryHITLDetailRespondedUserIdFilter, QueryHITLDetailRespondedUserNameFilter, QueryHITLDetailResponseReceivedFilter, @@ -226,11 +227,13 @@ def get_hitl_details( ), ], session: SessionDep, - # ti related filter + # permission filter readable_ti_filter: ReadableTIFilterDep, + # ti related filter dag_id_pattern: QueryHITLDetailDagIdPatternSearch, task_id: QueryHITLDetailTaskIdFilter, task_id_pattern: QueryHITLDetailTaskIdPatternSearch, + map_index: QueryHITLDetailMapIndexFilter, ti_state: QueryTIStateFilter, # hitl detail related filter response_received: QueryHITLDetailResponseReceivedFilter, @@ -258,11 +261,13 @@ def get_hitl_details( hitl_detail_select, total_entries = paginated_select( statement=query, filters=[ - # ti related filter + # permission filter readable_ti_filter, + # ti related filter dag_id_pattern, task_id, task_id_pattern, + map_index, ti_state, # hitl detail related filter response_received, diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts b/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts index dd46ddb015add..7ec7d3201c27e 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts @@ -567,7 +567,7 @@ export const UseTaskInstanceServiceGetHitlDetailKeyFn = ({ dagId, dagRunId, mapI export type TaskInstanceServiceGetHitlDetailsDefaultResponse = Awaited>; export type TaskInstanceServiceGetHitlDetailsQueryResult = UseQueryResult; export const useTaskInstanceServiceGetHitlDetailsKey = "TaskInstanceServiceGetHitlDetails"; -export const UseTaskInstanceServiceGetHitlDetailsKeyFn = ({ bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }: { +export const UseTaskInstanceServiceGetHitlDetailsKeyFn = ({ bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, mapIndex, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }: { bodySearch?: string; createdAtGt?: string; createdAtGte?: string; @@ -577,6 +577,7 @@ export const UseTaskInstanceServiceGetHitlDetailsKeyFn = ({ bodySearch, createdA dagIdPattern?: string; dagRunId: string; limit?: number; + mapIndex?: number; offset?: number; orderBy?: string[]; respondedByUserId?: string[]; @@ -586,7 +587,7 @@ export const UseTaskInstanceServiceGetHitlDetailsKeyFn = ({ bodySearch, createdA subjectSearch?: string; taskId?: string; taskIdPattern?: string; -}, queryKey?: Array) => [useTaskInstanceServiceGetHitlDetailsKey, ...(queryKey ?? [{ bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }])]; +}, queryKey?: Array) => [useTaskInstanceServiceGetHitlDetailsKey, ...(queryKey ?? [{ bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, mapIndex, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }])]; export type ImportErrorServiceGetImportErrorDefaultResponse = Awaited>; export type ImportErrorServiceGetImportErrorQueryResult = UseQueryResult; export const useImportErrorServiceGetImportErrorKey = "ImportErrorServiceGetImportError"; diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts b/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts index ed45244bdbf1e..411f9e07a8708 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts @@ -1083,6 +1083,7 @@ export const ensureUseTaskInstanceServiceGetHitlDetailData = (queryClient: Query * @param data.dagIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. * @param data.taskId * @param data.taskIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. +* @param data.mapIndex * @param data.state * @param data.responseReceived * @param data.respondedByUserId @@ -1096,7 +1097,7 @@ export const ensureUseTaskInstanceServiceGetHitlDetailData = (queryClient: Query * @returns HITLDetailCollection Successful Response * @throws ApiError */ -export const ensureUseTaskInstanceServiceGetHitlDetailsData = (queryClient: QueryClient, { bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }: { +export const ensureUseTaskInstanceServiceGetHitlDetailsData = (queryClient: QueryClient, { bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, mapIndex, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }: { bodySearch?: string; createdAtGt?: string; createdAtGte?: string; @@ -1106,6 +1107,7 @@ export const ensureUseTaskInstanceServiceGetHitlDetailsData = (queryClient: Quer dagIdPattern?: string; dagRunId: string; limit?: number; + mapIndex?: number; offset?: number; orderBy?: string[]; respondedByUserId?: string[]; @@ -1115,7 +1117,7 @@ export const ensureUseTaskInstanceServiceGetHitlDetailsData = (queryClient: Quer subjectSearch?: string; taskId?: string; taskIdPattern?: string; -}) => queryClient.ensureQueryData({ queryKey: Common.UseTaskInstanceServiceGetHitlDetailsKeyFn({ bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }), queryFn: () => TaskInstanceService.getHitlDetails({ bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }) }); +}) => queryClient.ensureQueryData({ queryKey: Common.UseTaskInstanceServiceGetHitlDetailsKeyFn({ bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, mapIndex, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }), queryFn: () => TaskInstanceService.getHitlDetails({ bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, mapIndex, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }) }); /** * Get Import Error * Get an import error. diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts b/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts index 595733362cf70..ec223f57f5a0f 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts @@ -1083,6 +1083,7 @@ export const prefetchUseTaskInstanceServiceGetHitlDetail = (queryClient: QueryCl * @param data.dagIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. * @param data.taskId * @param data.taskIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. +* @param data.mapIndex * @param data.state * @param data.responseReceived * @param data.respondedByUserId @@ -1096,7 +1097,7 @@ export const prefetchUseTaskInstanceServiceGetHitlDetail = (queryClient: QueryCl * @returns HITLDetailCollection Successful Response * @throws ApiError */ -export const prefetchUseTaskInstanceServiceGetHitlDetails = (queryClient: QueryClient, { bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }: { +export const prefetchUseTaskInstanceServiceGetHitlDetails = (queryClient: QueryClient, { bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, mapIndex, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }: { bodySearch?: string; createdAtGt?: string; createdAtGte?: string; @@ -1106,6 +1107,7 @@ export const prefetchUseTaskInstanceServiceGetHitlDetails = (queryClient: QueryC dagIdPattern?: string; dagRunId: string; limit?: number; + mapIndex?: number; offset?: number; orderBy?: string[]; respondedByUserId?: string[]; @@ -1115,7 +1117,7 @@ export const prefetchUseTaskInstanceServiceGetHitlDetails = (queryClient: QueryC subjectSearch?: string; taskId?: string; taskIdPattern?: string; -}) => queryClient.prefetchQuery({ queryKey: Common.UseTaskInstanceServiceGetHitlDetailsKeyFn({ bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }), queryFn: () => TaskInstanceService.getHitlDetails({ bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }) }); +}) => queryClient.prefetchQuery({ queryKey: Common.UseTaskInstanceServiceGetHitlDetailsKeyFn({ bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, mapIndex, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }), queryFn: () => TaskInstanceService.getHitlDetails({ bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, mapIndex, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }) }); /** * Get Import Error * Get an import error. diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts b/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts index b664457a66eaf..556d7932d60e7 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts @@ -1083,6 +1083,7 @@ export const useTaskInstanceServiceGetHitlDetail = = unknown[]>({ bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }: { +export const useTaskInstanceServiceGetHitlDetails = = unknown[]>({ bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, mapIndex, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }: { bodySearch?: string; createdAtGt?: string; createdAtGte?: string; @@ -1106,6 +1107,7 @@ export const useTaskInstanceServiceGetHitlDetails = , "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseTaskInstanceServiceGetHitlDetailsKeyFn({ bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }, queryKey), queryFn: () => TaskInstanceService.getHitlDetails({ bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }) as TData, ...options }); +}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseTaskInstanceServiceGetHitlDetailsKeyFn({ bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, mapIndex, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }, queryKey), queryFn: () => TaskInstanceService.getHitlDetails({ bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, mapIndex, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }) as TData, ...options }); /** * Get Import Error * Get an import error. diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts b/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts index 295371b0385aa..433fad2caa606 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts @@ -1083,6 +1083,7 @@ export const useTaskInstanceServiceGetHitlDetailSuspense = = unknown[]>({ bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }: { +export const useTaskInstanceServiceGetHitlDetailsSuspense = = unknown[]>({ bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, mapIndex, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }: { bodySearch?: string; createdAtGt?: string; createdAtGte?: string; @@ -1106,6 +1107,7 @@ export const useTaskInstanceServiceGetHitlDetailsSuspense = , "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseTaskInstanceServiceGetHitlDetailsKeyFn({ bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }, queryKey), queryFn: () => TaskInstanceService.getHitlDetails({ bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }) as TData, ...options }); +}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseTaskInstanceServiceGetHitlDetailsKeyFn({ bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, mapIndex, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }, queryKey), queryFn: () => TaskInstanceService.getHitlDetails({ bodySearch, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId, dagIdPattern, dagRunId, limit, mapIndex, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }) as TData, ...options }); /** * Get Import Error * Get an import error. diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts b/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts index 2b161775d455f..6d674b9fa5ec0 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts @@ -2792,6 +2792,7 @@ export class TaskInstanceService { * @param data.dagIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. * @param data.taskId * @param data.taskIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. + * @param data.mapIndex * @param data.state * @param data.responseReceived * @param data.respondedByUserId @@ -2820,6 +2821,7 @@ export class TaskInstanceService { dag_id_pattern: data.dagIdPattern, task_id: data.taskId, task_id_pattern: data.taskIdPattern, + map_index: data.mapIndex, state: data.state, response_received: data.responseReceived, responded_by_user_id: data.respondedByUserId, diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts index 96911409ea21e..dd896f566d689 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts @@ -2869,6 +2869,7 @@ export type GetHitlDetailsData = { dagIdPattern?: string | null; dagRunId: string; limit?: number; + mapIndex?: number | null; offset?: number; orderBy?: Array<(string)>; respondedByUserId?: Array<(string)>; diff --git a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_hitl.py b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_hitl.py index 9a431565e7d9c..22371bf1c2587 100644 --- a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_hitl.py +++ b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_hitl.py @@ -135,7 +135,7 @@ def sample_tis(create_task_instance: CreateTaskInstance) -> list[TaskInstance]: dag_id=f"hitl_dag_{i}", run_id=f"hitl_run_{i}", task_id=f"hitl_task_{i}", - state=TaskInstanceState.RUNNING, + state=TaskInstanceState.DEFERRED, ) for i in range(5) ] @@ -542,7 +542,9 @@ def test_should_respond_200_with_existing_response( ({"dag_id_pattern": "other_Dag_"}, 3), ({"task_id": "hitl_task_0"}, 1), ({"task_id_pattern": "another_hitl"}, 3), - ({"state": "running"}, 5), + ({"map_index": -1}, 8), + ({"map_index": 1}, 0), + ({"state": "deferred"}, 5), ({"state": "success"}, 3), # hitl detail related filter ({"subject_search": "This is subject"}, 5), @@ -570,9 +572,11 @@ def test_should_respond_200_with_existing_response( ids=[ "dag_id_pattern_hitl_dag", "dag_id_pattern_other_dag", - "task_id_pattern", "task_id", - "ti_state_running", + "task_id_pattern", + "map_index_none", + "map_index_1", + "ti_state_deferred", "ti_state_success", "subject", "body",