diff --git a/airflow-core/src/airflow/api_fastapi/common/db/dags.py b/airflow-core/src/airflow/api_fastapi/common/db/dags.py index 36283f86c55eb..cefce66279883 100644 --- a/airflow-core/src/airflow/api_fastapi/common/db/dags.py +++ b/airflow-core/src/airflow/api_fastapi/common/db/dags.py @@ -52,12 +52,12 @@ def generate_dag_with_latest_run_query(max_run_filters: list[BaseParam], order_b has_max_run_filter = True break - if has_max_run_filter or order_by.value in ( - "last_run_state", - "last_run_start_date", - "-last_run_state", - "-last_run_start_date", - ): + requested_order_by_set = set(order_by.value) if order_by.value is not None else set() + dag_run_order_by_set = set( + ["last_run_state", "last_run_start_date", "-last_run_state", "-last_run_start_date"], + ) + + if has_max_run_filter or (requested_order_by_set & dag_run_order_by_set): query = query.join( max_run_id_query, DagModel.dag_id == max_run_id_query.c.dag_id, diff --git a/airflow-core/src/airflow/api_fastapi/common/parameters.py b/airflow-core/src/airflow/api_fastapi/common/parameters.py index e8af5380f8a41..bd3534c621768 100644 --- a/airflow-core/src/airflow/api_fastapi/common/parameters.py +++ b/airflow-core/src/airflow/api_fastapi/common/parameters.py @@ -198,9 +198,11 @@ def depends_search( return depends_search -class SortParam(BaseParam[str]): +class SortParam(BaseParam[list[str]]): """Order result by the attribute.""" + MAX_SORT_PARAMS = 10 + def __init__( self, allowed_attrs: list[str], model: Base, to_replace: dict[str, str | Column] | None = None ) -> None: @@ -214,38 +216,56 @@ def to_orm(self, select: Select) -> Select: raise ValueError(f"Cannot set 'skip_none' to False on a {type(self)}") if self.value is None: - self.value = self.get_primary_key_string() - - lstriped_orderby = self.value.lstrip("-") - column: Column | None = None - if self.to_replace: - replacement = self.to_replace.get(lstriped_orderby, lstriped_orderby) - if isinstance(replacement, str): - lstriped_orderby = replacement - else: - column = replacement + self.value = [self.get_primary_key_string()] - if (self.allowed_attrs and lstriped_orderby not in self.allowed_attrs) and column is None: + order_by_values = self.value + if len(order_by_values) > self.MAX_SORT_PARAMS: raise HTTPException( 400, - f"Ordering with '{lstriped_orderby}' is disallowed or " - f"the attribute does not exist on the model", + f"Ordering with more than {self.MAX_SORT_PARAMS} parameters is not allowed. Provided: {order_by_values}", ) - if column is None: - column = getattr(self.model, lstriped_orderby) - # MySQL does not support `nullslast`, and True/False ordering depends on the - # database implementation. - nullscheck = case((column.isnot(None), 0), else_=1) + columns: list[Column] = [] + for order_by_value in order_by_values: + lstriped_orderby = order_by_value.lstrip("-") + column: Column | None = None + if self.to_replace: + replacement = self.to_replace.get(lstriped_orderby, lstriped_orderby) + if isinstance(replacement, str): + lstriped_orderby = replacement + else: + column = replacement + + if (self.allowed_attrs and lstriped_orderby not in self.allowed_attrs) and column is None: + raise HTTPException( + 400, + f"Ordering with '{lstriped_orderby}' is disallowed or " + f"the attribute does not exist on the model", + ) + if column is None: + column = getattr(self.model, lstriped_orderby) + + # MySQL does not support `nullslast`, and True/False ordering depends on the + # database implementation. + nullscheck = case((column.isnot(None), 0), else_=1) + + columns.append(nullscheck) + if order_by_value.startswith("-"): + columns.append(column.desc()) + else: + columns.append(column.asc()) # Reset default sorting select = select.order_by(None) primary_key_column = self.get_primary_key_column() + # Always add a final discriminator to enforce deterministic ordering. + if order_by_values and order_by_values[0].startswith("-"): + columns.append(primary_key_column.desc()) + else: + columns.append(primary_key_column.asc()) - if self.value[0] == "-": - return select.order_by(nullscheck, column.desc(), primary_key_column.desc()) - return select.order_by(nullscheck, column.asc(), primary_key_column.asc()) + return select.order_by(*columns) def get_primary_key_column(self) -> Column: """Get the primary key column of the model of SortParam object.""" @@ -260,8 +280,12 @@ def depends(cls, *args: Any, **kwargs: Any) -> Self: raise NotImplementedError("Use dynamic_depends, depends not implemented.") def dynamic_depends(self, default: str | None = None) -> Callable: - def inner(order_by: str = default or self.get_primary_key_string()) -> SortParam: - return self.set_value(self.get_primary_key_string() if order_by == "" else order_by) + def inner( + order_by: list[str] = Query( + default=[default] if default is not None else [self.get_primary_key_string()] + ), + ) -> SortParam: + return self.set_value(order_by) return inner diff --git a/airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml b/airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml index 4abbae3e238e5..f8289bba786ce 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml +++ b/airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml @@ -220,8 +220,11 @@ paths: in: query required: false schema: - type: string - default: dag_id + type: array + items: + type: string + default: + - dag_id title: Order By - name: is_favorite in: query @@ -485,8 +488,11 @@ paths: in: query required: false schema: - type: string - default: id + type: array + items: + type: string + default: + - id title: Order By - name: dag_id in: query @@ -560,8 +566,11 @@ paths: in: query required: false schema: - type: string - default: id + type: array + items: + type: string + default: + - id title: Order By - name: run_after_gte in: query @@ -646,8 +655,11 @@ paths: in: query required: false schema: - type: string - default: id + type: array + items: + type: string + default: + - id title: Order By - name: run_after_gte in: query 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 1bbb151cc141a..2378ec76f73b5 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 @@ -77,8 +77,11 @@ paths: in: query required: false schema: - type: string - default: id + type: array + items: + type: string + default: + - id title: Order By responses: '200': @@ -154,8 +157,11 @@ paths: in: query required: false schema: - type: string - default: id + type: array + items: + type: string + default: + - id title: Order By responses: '200': @@ -266,8 +272,11 @@ paths: in: query required: false schema: - type: string - default: timestamp + type: array + items: + type: string + default: + - timestamp title: Order By - name: asset_id in: query @@ -886,8 +895,11 @@ paths: in: query required: false schema: - type: string - default: id + type: array + items: + type: string + default: + - id title: Order By responses: '200': @@ -1418,8 +1430,11 @@ paths: in: query required: false schema: - type: string - default: id + type: array + items: + type: string + default: + - id title: Order By - name: connection_id_pattern in: query @@ -2072,8 +2087,11 @@ paths: in: query required: false schema: - type: string - default: id + type: array + items: + type: string + default: + - id title: Order By - name: run_id_pattern in: query @@ -2718,8 +2736,11 @@ paths: in: query required: false schema: - type: string - default: dag_id + type: array + items: + type: string + default: + - dag_id title: Order By responses: '200': @@ -2895,8 +2916,11 @@ paths: in: query required: false schema: - type: string - default: dag_id + type: array + items: + type: string + default: + - dag_id title: Order By - name: is_favorite in: query @@ -3465,8 +3489,11 @@ paths: in: query required: false schema: - type: string - default: id + type: array + items: + type: string + default: + - id title: Order By - name: dag_id in: query @@ -3734,8 +3761,11 @@ paths: in: query required: false schema: - type: string - default: id + type: array + items: + type: string + default: + - id title: Order By responses: '200': @@ -3837,8 +3867,11 @@ paths: in: query required: false schema: - type: string - default: id + type: array + items: + type: string + default: + - id title: Order By - name: job_state in: query @@ -4179,8 +4212,11 @@ paths: in: query required: false schema: - type: string - default: id + type: array + items: + type: string + default: + - id title: Order By - name: pool_name_pattern in: query @@ -5128,8 +5164,11 @@ paths: in: query required: false schema: - type: string - default: map_index + type: array + items: + type: string + default: + - map_index title: Order By responses: '200': @@ -5803,8 +5842,11 @@ paths: in: query required: false schema: - type: string - default: map_index + type: array + items: + type: string + default: + - map_index title: Order By responses: '200': @@ -6641,8 +6683,11 @@ paths: in: query required: false schema: - type: string - default: id + type: array + items: + type: string + default: + - id title: Order By - name: variable_key_pattern in: query @@ -7035,8 +7080,11 @@ paths: in: query required: false schema: - type: string - default: name + type: array + items: + type: string + default: + - name title: Order By - name: tag_name_pattern in: query @@ -7190,8 +7238,11 @@ paths: in: query required: false schema: - type: string - default: id + type: array + items: + type: string + default: + - id title: Order By responses: '200': @@ -7529,8 +7580,11 @@ paths: in: query required: false schema: - type: string - default: ti_id + type: array + items: + type: string + default: + - ti_id title: Order By - name: dag_id_pattern in: query diff --git a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/dag_run.py b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/dag_run.py index 00f93754baf2d..643ee1e528fd0 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/dag_run.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/dag_run.py @@ -544,7 +544,7 @@ def get_list_dag_runs_batch( ], DagRun, {"dag_run_id": "run_id"}, - ).set_value(body.order_by) + ).set_value([body.order_by] if body.order_by else None) base_query = select(DagRun).options(joinedload(DagRun.dag_model)) dag_runs_select, total_entries = paginated_select( diff --git a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/task_instances.py b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/task_instances.py index 33bafc0506b7e..07885a7a66798 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/task_instances.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/task_instances.py @@ -541,7 +541,7 @@ def get_task_instances_batch( order_by = SortParam( ["id", "state", "duration", "start_date", "end_date", "map_index"], TI, - ).set_value(body.order_by) + ).set_value([body.order_by] if body.order_by else None) query = select(TI).join(TI.dag_run) task_instance_select, total_entries = paginated_select( diff --git a/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/grid.py b/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/grid.py index f4c6d7d558cbd..80e68bd890f4b 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/grid.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/grid.py @@ -127,12 +127,12 @@ def get_dag_structure( # Retrieve, sort the previous DAG Runs base_query = select(DagRun.id).where(DagRun.dag_id == dag_id) # This comparison is to fall back to DAG timetable when no order_by is provided - if order_by.value == order_by.get_primary_key_string(): + if order_by.value == [order_by.get_primary_key_string()]: ordering = list(latest_dag.timetable.run_ordering) order_by = SortParam( allowed_attrs=ordering, model=DagRun, - ).set_value(ordering[0]) + ).set_value(ordering) dag_runs_select_filter, _ = paginated_select( statement=base_query, order_by=order_by, @@ -230,14 +230,14 @@ def get_grid_runs( ).where(DagRun.dag_id == dag_id) # This comparison is to fall back to DAG timetable when no order_by is provided - if order_by.value == order_by.get_primary_key_string(): + if order_by.value == [order_by.get_primary_key_string()]: latest_serdag = _get_latest_serdag(dag_id, session) latest_dag = latest_serdag.dag ordering = list(latest_dag.timetable.run_ordering) order_by = SortParam( allowed_attrs=ordering, model=DagRun, - ).set_value(ordering[0]) + ).set_value(ordering) dag_runs_select_filter, _ = paginated_select( statement=base_query, order_by=order_by, @@ -305,7 +305,7 @@ def get_grid_ti_summaries( ) ), filters=[], - order_by=SortParam(allowed_attrs=["task_id", "run_id"], model=TaskInstance).set_value("task_id"), + order_by=SortParam(allowed_attrs=["task_id", "run_id"], model=TaskInstance).set_value(["task_id"]), limit=None, return_total_entries=False, ) 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 837eca5e85d7e..2fefc3d5f5313 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts @@ -12,7 +12,7 @@ export const UseAssetServiceGetAssetsKeyFn = ({ dagIds, limit, namePattern, offs namePattern?: string; offset?: number; onlyActive?: boolean; - orderBy?: string; + orderBy?: string[]; uriPattern?: string; } = {}, queryKey?: Array) => [useAssetServiceGetAssetsKey, ...(queryKey ?? [{ dagIds, limit, namePattern, offset, onlyActive, orderBy, uriPattern }])]; export type AssetServiceGetAssetAliasesDefaultResponse = Awaited>; @@ -22,7 +22,7 @@ export const UseAssetServiceGetAssetAliasesKeyFn = ({ limit, namePattern, offset limit?: number; namePattern?: string; offset?: number; - orderBy?: string; + orderBy?: string[]; } = {}, queryKey?: Array) => [useAssetServiceGetAssetAliasesKey, ...(queryKey ?? [{ limit, namePattern, offset, orderBy }])]; export type AssetServiceGetAssetAliasDefaultResponse = Awaited>; export type AssetServiceGetAssetAliasQueryResult = UseQueryResult; @@ -37,7 +37,7 @@ export const UseAssetServiceGetAssetEventsKeyFn = ({ assetId, limit, offset, ord assetId?: number; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; sourceDagId?: string; sourceMapIndex?: number; sourceRunId?: string; @@ -86,7 +86,7 @@ export const UseBackfillServiceListBackfillsKeyFn = ({ dagId, limit, offset, ord dagId: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; }, queryKey?: Array) => [useBackfillServiceListBackfillsKey, ...(queryKey ?? [{ dagId, limit, offset, orderBy }])]; export type BackfillServiceGetBackfillDefaultResponse = Awaited>; export type BackfillServiceGetBackfillQueryResult = UseQueryResult; @@ -102,7 +102,7 @@ export const UseBackfillServiceListBackfillsUiKeyFn = ({ active, dagId, limit, o dagId?: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; } = {}, queryKey?: Array) => [useBackfillServiceListBackfillsUiKey, ...(queryKey ?? [{ active, dagId, limit, offset, orderBy }])]; export type ConnectionServiceGetConnectionDefaultResponse = Awaited>; export type ConnectionServiceGetConnectionQueryResult = UseQueryResult; @@ -117,7 +117,7 @@ export const UseConnectionServiceGetConnectionsKeyFn = ({ connectionIdPattern, l connectionIdPattern?: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; } = {}, queryKey?: Array) => [useConnectionServiceGetConnectionsKey, ...(queryKey ?? [{ connectionIdPattern, limit, offset, orderBy }])]; export type ConnectionServiceHookMetaDataDefaultResponse = Awaited>; export type ConnectionServiceHookMetaDataQueryResult = UseQueryResult; @@ -148,7 +148,7 @@ export const UseDagRunServiceGetDagRunsKeyFn = ({ dagId, endDateGte, endDateLte, logicalDateGte?: string; logicalDateLte?: string; offset?: number; - orderBy?: string; + orderBy?: string[]; runAfterGte?: string; runAfterLte?: string; runIdPattern?: string; @@ -223,7 +223,7 @@ export const UseDagWarningServiceListDagWarningsKeyFn = ({ dagId, limit, offset, dagId?: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; warningType?: DagWarningType; } = {}, queryKey?: Array) => [useDagWarningServiceListDagWarningsKey, ...(queryKey ?? [{ dagId, limit, offset, orderBy, warningType }])]; export type DagServiceGetDagsDefaultResponse = Awaited>; @@ -242,7 +242,7 @@ export const UseDagServiceGetDagsKeyFn = ({ dagDisplayNamePattern, dagIdPattern, lastDagRunState?: DagRunState; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; owners?: string[]; paused?: boolean; tags?: string[]; @@ -266,7 +266,7 @@ export const useDagServiceGetDagTagsKey = "DagServiceGetDagTags"; export const UseDagServiceGetDagTagsKeyFn = ({ limit, offset, orderBy, tagNamePattern }: { limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; tagNamePattern?: string; } = {}, queryKey?: Array) => [useDagServiceGetDagTagsKey, ...(queryKey ?? [{ limit, offset, orderBy, tagNamePattern }])]; export type DagServiceGetDagsUiDefaultResponse = Awaited>; @@ -282,7 +282,7 @@ export const UseDagServiceGetDagsUiKeyFn = ({ dagDisplayNamePattern, dagIdPatter lastDagRunState?: DagRunState; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; owners?: string[]; paused?: boolean; tags?: string[]; @@ -313,7 +313,7 @@ export const UseEventLogServiceGetEventLogsKeyFn = ({ after, before, dagId, even limit?: number; mapIndex?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; owner?: string; runId?: string; taskId?: string; @@ -360,7 +360,7 @@ export const UseTaskInstanceServiceGetMappedTaskInstancesKeyFn = ({ dagId, dagRu logicalDateGte?: string; logicalDateLte?: string; offset?: number; - orderBy?: string; + orderBy?: string[]; pool?: string[]; queue?: string[]; runAfterGte?: string; @@ -433,7 +433,7 @@ export const UseTaskInstanceServiceGetTaskInstancesKeyFn = ({ dagId, dagRunId, d logicalDateGte?: string; logicalDateLte?: string; offset?: number; - orderBy?: string; + orderBy?: string[]; pool?: string[]; queue?: string[]; runAfterGte?: string; @@ -502,7 +502,7 @@ export const useImportErrorServiceGetImportErrorsKey = "ImportErrorServiceGetImp export const UseImportErrorServiceGetImportErrorsKeyFn = ({ limit, offset, orderBy }: { limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; } = {}, queryKey?: Array) => [useImportErrorServiceGetImportErrorsKey, ...(queryKey ?? [{ limit, offset, orderBy }])]; export type JobServiceGetJobsDefaultResponse = Awaited>; export type JobServiceGetJobsQueryResult = UseQueryResult; @@ -517,7 +517,7 @@ export const UseJobServiceGetJobsKeyFn = ({ endDateGte, endDateLte, executorClas jobType?: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; startDateGte?: string; startDateLte?: string; } = {}, queryKey?: Array) => [useJobServiceGetJobsKey, ...(queryKey ?? [{ endDateGte, endDateLte, executorClass, hostname, isAlive, jobState, jobType, limit, offset, orderBy, startDateGte, startDateLte }])]; @@ -544,7 +544,7 @@ export const usePoolServiceGetPoolsKey = "PoolServiceGetPools"; export const UsePoolServiceGetPoolsKeyFn = ({ limit, offset, orderBy, poolNamePattern }: { limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; poolNamePattern?: string; } = {}, queryKey?: Array) => [usePoolServiceGetPoolsKey, ...(queryKey ?? [{ limit, offset, orderBy, poolNamePattern }])]; export type ProviderServiceGetProvidersDefaultResponse = Awaited>; @@ -604,7 +604,7 @@ export const useVariableServiceGetVariablesKey = "VariableServiceGetVariables"; export const UseVariableServiceGetVariablesKeyFn = ({ limit, offset, orderBy, variableKeyPattern }: { limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; variableKeyPattern?: string; } = {}, queryKey?: Array) => [useVariableServiceGetVariablesKey, ...(queryKey ?? [{ limit, offset, orderBy, variableKeyPattern }])]; export type DagVersionServiceGetDagVersionDefaultResponse = Awaited>; @@ -623,7 +623,7 @@ export const UseDagVersionServiceGetDagVersionsKeyFn = ({ bundleName, bundleVers dagId: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; versionNumber?: number; }, queryKey?: Array) => [useDagVersionServiceGetDagVersionsKey, ...(queryKey ?? [{ bundleName, bundleVersion, dagId, limit, offset, orderBy, versionNumber }])]; export type HumanInTheLoopServiceGetHitlDetailDefaultResponse = Awaited>; @@ -652,7 +652,7 @@ export const UseHumanInTheLoopServiceGetHitlDetailsKeyFn = ({ bodySearch, dagIdP dagRunId?: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; responseReceived?: boolean; state?: string[]; subjectSearch?: string; @@ -717,7 +717,7 @@ export const UseGridServiceGetDagStructureKeyFn = ({ dagId, limit, offset, order dagId: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; runAfterGte?: string; runAfterLte?: string; }, queryKey?: Array) => [useGridServiceGetDagStructureKey, ...(queryKey ?? [{ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }])]; @@ -728,7 +728,7 @@ export const UseGridServiceGetGridRunsKeyFn = ({ dagId, limit, offset, orderBy, dagId: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; runAfterGte?: string; runAfterLte?: string; }, queryKey?: Array) => [useGridServiceGetGridRunsKey, ...(queryKey ?? [{ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }])]; 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 210dcacb0acd9..357e69886687f 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts @@ -24,7 +24,7 @@ export const ensureUseAssetServiceGetAssetsData = (queryClient: QueryClient, { d namePattern?: string; offset?: number; onlyActive?: boolean; - orderBy?: string; + orderBy?: string[]; uriPattern?: string; } = {}) => queryClient.ensureQueryData({ queryKey: Common.UseAssetServiceGetAssetsKeyFn({ dagIds, limit, namePattern, offset, onlyActive, orderBy, uriPattern }), queryFn: () => AssetService.getAssets({ dagIds, limit, namePattern, offset, onlyActive, orderBy, uriPattern }) }); /** @@ -42,7 +42,7 @@ export const ensureUseAssetServiceGetAssetAliasesData = (queryClient: QueryClien limit?: number; namePattern?: string; offset?: number; - orderBy?: string; + orderBy?: string[]; } = {}) => queryClient.ensureQueryData({ queryKey: Common.UseAssetServiceGetAssetAliasesKeyFn({ limit, namePattern, offset, orderBy }), queryFn: () => AssetService.getAssetAliases({ limit, namePattern, offset, orderBy }) }); /** * Get Asset Alias @@ -76,7 +76,7 @@ export const ensureUseAssetServiceGetAssetEventsData = (queryClient: QueryClient assetId?: number; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; sourceDagId?: string; sourceMapIndex?: number; sourceRunId?: string; @@ -160,7 +160,7 @@ export const ensureUseBackfillServiceListBackfillsData = (queryClient: QueryClie dagId: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; }) => queryClient.ensureQueryData({ queryKey: Common.UseBackfillServiceListBackfillsKeyFn({ dagId, limit, offset, orderBy }), queryFn: () => BackfillService.listBackfills({ dagId, limit, offset, orderBy }) }); /** * Get Backfill @@ -188,7 +188,7 @@ export const ensureUseBackfillServiceListBackfillsUiData = (queryClient: QueryCl dagId?: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; } = {}) => queryClient.ensureQueryData({ queryKey: Common.UseBackfillServiceListBackfillsUiKeyFn({ active, dagId, limit, offset, orderBy }), queryFn: () => BackfillService.listBackfillsUi({ active, dagId, limit, offset, orderBy }) }); /** * Get Connection @@ -216,7 +216,7 @@ export const ensureUseConnectionServiceGetConnectionsData = (queryClient: QueryC connectionIdPattern?: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; } = {}) => queryClient.ensureQueryData({ queryKey: Common.UseConnectionServiceGetConnectionsKeyFn({ connectionIdPattern, limit, offset, orderBy }), queryFn: () => ConnectionService.getConnections({ connectionIdPattern, limit, offset, orderBy }) }); /** * Hook Meta Data @@ -284,7 +284,7 @@ export const ensureUseDagRunServiceGetDagRunsData = (queryClient: QueryClient, { logicalDateGte?: string; logicalDateLte?: string; offset?: number; - orderBy?: string; + orderBy?: string[]; runAfterGte?: string; runAfterLte?: string; runIdPattern?: string; @@ -415,7 +415,7 @@ export const ensureUseDagWarningServiceListDagWarningsData = (queryClient: Query dagId?: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; warningType?: DagWarningType; } = {}) => queryClient.ensureQueryData({ queryKey: Common.UseDagWarningServiceListDagWarningsKeyFn({ dagId, limit, offset, orderBy, warningType }), queryFn: () => DagWarningService.listDagWarnings({ dagId, limit, offset, orderBy, warningType }) }); /** @@ -455,7 +455,7 @@ export const ensureUseDagServiceGetDagsData = (queryClient: QueryClient, { dagDi lastDagRunState?: DagRunState; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; owners?: string[]; paused?: boolean; tags?: string[]; @@ -497,7 +497,7 @@ export const ensureUseDagServiceGetDagDetailsData = (queryClient: QueryClient, { export const ensureUseDagServiceGetDagTagsData = (queryClient: QueryClient, { limit, offset, orderBy, tagNamePattern }: { limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; tagNamePattern?: string; } = {}) => queryClient.ensureQueryData({ queryKey: Common.UseDagServiceGetDagTagsKeyFn({ limit, offset, orderBy, tagNamePattern }), queryFn: () => DagService.getDagTags({ limit, offset, orderBy, tagNamePattern }) }); /** @@ -531,7 +531,7 @@ export const ensureUseDagServiceGetDagsUiData = (queryClient: QueryClient, { dag lastDagRunState?: DagRunState; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; owners?: string[]; paused?: boolean; tags?: string[]; @@ -589,7 +589,7 @@ export const ensureUseEventLogServiceGetEventLogsData = (queryClient: QueryClien limit?: number; mapIndex?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; owner?: string; runId?: string; taskId?: string; @@ -686,7 +686,7 @@ export const ensureUseTaskInstanceServiceGetMappedTaskInstancesData = (queryClie logicalDateGte?: string; logicalDateLte?: string; offset?: number; - orderBy?: string; + orderBy?: string[]; pool?: string[]; queue?: string[]; runAfterGte?: string; @@ -829,7 +829,7 @@ export const ensureUseTaskInstanceServiceGetTaskInstancesData = (queryClient: Qu logicalDateGte?: string; logicalDateLte?: string; offset?: number; - orderBy?: string; + orderBy?: string[]; pool?: string[]; queue?: string[]; runAfterGte?: string; @@ -948,7 +948,7 @@ export const ensureUseImportErrorServiceGetImportErrorData = (queryClient: Query export const ensureUseImportErrorServiceGetImportErrorsData = (queryClient: QueryClient, { limit, offset, orderBy }: { limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; } = {}) => queryClient.ensureQueryData({ queryKey: Common.UseImportErrorServiceGetImportErrorsKeyFn({ limit, offset, orderBy }), queryFn: () => ImportErrorService.getImportErrors({ limit, offset, orderBy }) }); /** * Get Jobs @@ -979,7 +979,7 @@ export const ensureUseJobServiceGetJobsData = (queryClient: QueryClient, { endDa jobType?: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; startDateGte?: string; startDateLte?: string; } = {}) => queryClient.ensureQueryData({ queryKey: Common.UseJobServiceGetJobsKeyFn({ endDateGte, endDateLte, executorClass, hostname, isAlive, jobState, jobType, limit, offset, orderBy, startDateGte, startDateLte }), queryFn: () => JobService.getJobs({ endDateGte, endDateLte, executorClass, hostname, isAlive, jobState, jobType, limit, offset, orderBy, startDateGte, startDateLte }) }); @@ -1026,7 +1026,7 @@ export const ensureUsePoolServiceGetPoolData = (queryClient: QueryClient, { pool export const ensureUsePoolServiceGetPoolsData = (queryClient: QueryClient, { limit, offset, orderBy, poolNamePattern }: { limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; poolNamePattern?: string; } = {}) => queryClient.ensureQueryData({ queryKey: Common.UsePoolServiceGetPoolsKeyFn({ limit, offset, orderBy, poolNamePattern }), queryFn: () => PoolService.getPools({ limit, offset, orderBy, poolNamePattern }) }); /** @@ -1141,7 +1141,7 @@ export const ensureUseVariableServiceGetVariableData = (queryClient: QueryClient export const ensureUseVariableServiceGetVariablesData = (queryClient: QueryClient, { limit, offset, orderBy, variableKeyPattern }: { limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; variableKeyPattern?: string; } = {}) => queryClient.ensureQueryData({ queryKey: Common.UseVariableServiceGetVariablesKeyFn({ limit, offset, orderBy, variableKeyPattern }), queryFn: () => VariableService.getVariables({ limit, offset, orderBy, variableKeyPattern }) }); /** @@ -1179,7 +1179,7 @@ export const ensureUseDagVersionServiceGetDagVersionsData = (queryClient: QueryC dagId: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; versionNumber?: number; }) => queryClient.ensureQueryData({ queryKey: Common.UseDagVersionServiceGetDagVersionsKeyFn({ bundleName, bundleVersion, dagId, limit, offset, orderBy, versionNumber }), queryFn: () => DagVersionService.getDagVersions({ bundleName, bundleVersion, dagId, limit, offset, orderBy, versionNumber }) }); /** @@ -1237,7 +1237,7 @@ export const ensureUseHumanInTheLoopServiceGetHitlDetailsData = (queryClient: Qu dagRunId?: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; responseReceived?: boolean; state?: string[]; subjectSearch?: string; @@ -1353,7 +1353,7 @@ export const ensureUseGridServiceGetDagStructureData = (queryClient: QueryClient dagId: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; runAfterGte?: string; runAfterLte?: string; }) => queryClient.ensureQueryData({ queryKey: Common.UseGridServiceGetDagStructureKeyFn({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }), queryFn: () => GridService.getDagStructure({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }) }); @@ -1374,7 +1374,7 @@ export const ensureUseGridServiceGetGridRunsData = (queryClient: QueryClient, { dagId: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; runAfterGte?: string; runAfterLte?: string; }) => queryClient.ensureQueryData({ queryKey: Common.UseGridServiceGetGridRunsKeyFn({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }), queryFn: () => GridService.getGridRuns({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }) }); 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 bf2a3841c2ef4..3d8009ce49046 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts @@ -24,7 +24,7 @@ export const prefetchUseAssetServiceGetAssets = (queryClient: QueryClient, { dag namePattern?: string; offset?: number; onlyActive?: boolean; - orderBy?: string; + orderBy?: string[]; uriPattern?: string; } = {}) => queryClient.prefetchQuery({ queryKey: Common.UseAssetServiceGetAssetsKeyFn({ dagIds, limit, namePattern, offset, onlyActive, orderBy, uriPattern }), queryFn: () => AssetService.getAssets({ dagIds, limit, namePattern, offset, onlyActive, orderBy, uriPattern }) }); /** @@ -42,7 +42,7 @@ export const prefetchUseAssetServiceGetAssetAliases = (queryClient: QueryClient, limit?: number; namePattern?: string; offset?: number; - orderBy?: string; + orderBy?: string[]; } = {}) => queryClient.prefetchQuery({ queryKey: Common.UseAssetServiceGetAssetAliasesKeyFn({ limit, namePattern, offset, orderBy }), queryFn: () => AssetService.getAssetAliases({ limit, namePattern, offset, orderBy }) }); /** * Get Asset Alias @@ -76,7 +76,7 @@ export const prefetchUseAssetServiceGetAssetEvents = (queryClient: QueryClient, assetId?: number; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; sourceDagId?: string; sourceMapIndex?: number; sourceRunId?: string; @@ -160,7 +160,7 @@ export const prefetchUseBackfillServiceListBackfills = (queryClient: QueryClient dagId: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; }) => queryClient.prefetchQuery({ queryKey: Common.UseBackfillServiceListBackfillsKeyFn({ dagId, limit, offset, orderBy }), queryFn: () => BackfillService.listBackfills({ dagId, limit, offset, orderBy }) }); /** * Get Backfill @@ -188,7 +188,7 @@ export const prefetchUseBackfillServiceListBackfillsUi = (queryClient: QueryClie dagId?: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; } = {}) => queryClient.prefetchQuery({ queryKey: Common.UseBackfillServiceListBackfillsUiKeyFn({ active, dagId, limit, offset, orderBy }), queryFn: () => BackfillService.listBackfillsUi({ active, dagId, limit, offset, orderBy }) }); /** * Get Connection @@ -216,7 +216,7 @@ export const prefetchUseConnectionServiceGetConnections = (queryClient: QueryCli connectionIdPattern?: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; } = {}) => queryClient.prefetchQuery({ queryKey: Common.UseConnectionServiceGetConnectionsKeyFn({ connectionIdPattern, limit, offset, orderBy }), queryFn: () => ConnectionService.getConnections({ connectionIdPattern, limit, offset, orderBy }) }); /** * Hook Meta Data @@ -284,7 +284,7 @@ export const prefetchUseDagRunServiceGetDagRuns = (queryClient: QueryClient, { d logicalDateGte?: string; logicalDateLte?: string; offset?: number; - orderBy?: string; + orderBy?: string[]; runAfterGte?: string; runAfterLte?: string; runIdPattern?: string; @@ -415,7 +415,7 @@ export const prefetchUseDagWarningServiceListDagWarnings = (queryClient: QueryCl dagId?: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; warningType?: DagWarningType; } = {}) => queryClient.prefetchQuery({ queryKey: Common.UseDagWarningServiceListDagWarningsKeyFn({ dagId, limit, offset, orderBy, warningType }), queryFn: () => DagWarningService.listDagWarnings({ dagId, limit, offset, orderBy, warningType }) }); /** @@ -455,7 +455,7 @@ export const prefetchUseDagServiceGetDags = (queryClient: QueryClient, { dagDisp lastDagRunState?: DagRunState; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; owners?: string[]; paused?: boolean; tags?: string[]; @@ -497,7 +497,7 @@ export const prefetchUseDagServiceGetDagDetails = (queryClient: QueryClient, { d export const prefetchUseDagServiceGetDagTags = (queryClient: QueryClient, { limit, offset, orderBy, tagNamePattern }: { limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; tagNamePattern?: string; } = {}) => queryClient.prefetchQuery({ queryKey: Common.UseDagServiceGetDagTagsKeyFn({ limit, offset, orderBy, tagNamePattern }), queryFn: () => DagService.getDagTags({ limit, offset, orderBy, tagNamePattern }) }); /** @@ -531,7 +531,7 @@ export const prefetchUseDagServiceGetDagsUi = (queryClient: QueryClient, { dagDi lastDagRunState?: DagRunState; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; owners?: string[]; paused?: boolean; tags?: string[]; @@ -589,7 +589,7 @@ export const prefetchUseEventLogServiceGetEventLogs = (queryClient: QueryClient, limit?: number; mapIndex?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; owner?: string; runId?: string; taskId?: string; @@ -686,7 +686,7 @@ export const prefetchUseTaskInstanceServiceGetMappedTaskInstances = (queryClient logicalDateGte?: string; logicalDateLte?: string; offset?: number; - orderBy?: string; + orderBy?: string[]; pool?: string[]; queue?: string[]; runAfterGte?: string; @@ -829,7 +829,7 @@ export const prefetchUseTaskInstanceServiceGetTaskInstances = (queryClient: Quer logicalDateGte?: string; logicalDateLte?: string; offset?: number; - orderBy?: string; + orderBy?: string[]; pool?: string[]; queue?: string[]; runAfterGte?: string; @@ -948,7 +948,7 @@ export const prefetchUseImportErrorServiceGetImportError = (queryClient: QueryCl export const prefetchUseImportErrorServiceGetImportErrors = (queryClient: QueryClient, { limit, offset, orderBy }: { limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; } = {}) => queryClient.prefetchQuery({ queryKey: Common.UseImportErrorServiceGetImportErrorsKeyFn({ limit, offset, orderBy }), queryFn: () => ImportErrorService.getImportErrors({ limit, offset, orderBy }) }); /** * Get Jobs @@ -979,7 +979,7 @@ export const prefetchUseJobServiceGetJobs = (queryClient: QueryClient, { endDate jobType?: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; startDateGte?: string; startDateLte?: string; } = {}) => queryClient.prefetchQuery({ queryKey: Common.UseJobServiceGetJobsKeyFn({ endDateGte, endDateLte, executorClass, hostname, isAlive, jobState, jobType, limit, offset, orderBy, startDateGte, startDateLte }), queryFn: () => JobService.getJobs({ endDateGte, endDateLte, executorClass, hostname, isAlive, jobState, jobType, limit, offset, orderBy, startDateGte, startDateLte }) }); @@ -1026,7 +1026,7 @@ export const prefetchUsePoolServiceGetPool = (queryClient: QueryClient, { poolNa export const prefetchUsePoolServiceGetPools = (queryClient: QueryClient, { limit, offset, orderBy, poolNamePattern }: { limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; poolNamePattern?: string; } = {}) => queryClient.prefetchQuery({ queryKey: Common.UsePoolServiceGetPoolsKeyFn({ limit, offset, orderBy, poolNamePattern }), queryFn: () => PoolService.getPools({ limit, offset, orderBy, poolNamePattern }) }); /** @@ -1141,7 +1141,7 @@ export const prefetchUseVariableServiceGetVariable = (queryClient: QueryClient, export const prefetchUseVariableServiceGetVariables = (queryClient: QueryClient, { limit, offset, orderBy, variableKeyPattern }: { limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; variableKeyPattern?: string; } = {}) => queryClient.prefetchQuery({ queryKey: Common.UseVariableServiceGetVariablesKeyFn({ limit, offset, orderBy, variableKeyPattern }), queryFn: () => VariableService.getVariables({ limit, offset, orderBy, variableKeyPattern }) }); /** @@ -1179,7 +1179,7 @@ export const prefetchUseDagVersionServiceGetDagVersions = (queryClient: QueryCli dagId: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; versionNumber?: number; }) => queryClient.prefetchQuery({ queryKey: Common.UseDagVersionServiceGetDagVersionsKeyFn({ bundleName, bundleVersion, dagId, limit, offset, orderBy, versionNumber }), queryFn: () => DagVersionService.getDagVersions({ bundleName, bundleVersion, dagId, limit, offset, orderBy, versionNumber }) }); /** @@ -1237,7 +1237,7 @@ export const prefetchUseHumanInTheLoopServiceGetHitlDetails = (queryClient: Quer dagRunId?: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; responseReceived?: boolean; state?: string[]; subjectSearch?: string; @@ -1353,7 +1353,7 @@ export const prefetchUseGridServiceGetDagStructure = (queryClient: QueryClient, dagId: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; runAfterGte?: string; runAfterLte?: string; }) => queryClient.prefetchQuery({ queryKey: Common.UseGridServiceGetDagStructureKeyFn({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }), queryFn: () => GridService.getDagStructure({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }) }); @@ -1374,7 +1374,7 @@ export const prefetchUseGridServiceGetGridRuns = (queryClient: QueryClient, { da dagId: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; runAfterGte?: string; runAfterLte?: string; }) => queryClient.prefetchQuery({ queryKey: Common.UseGridServiceGetGridRunsKeyFn({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }), queryFn: () => GridService.getGridRuns({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }) }); 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 f598ce9f4237d..e26bc9fc64cc2 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts @@ -24,7 +24,7 @@ export const useAssetServiceGetAssets = , "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseAssetServiceGetAssetsKeyFn({ dagIds, limit, namePattern, offset, onlyActive, orderBy, uriPattern }, queryKey), queryFn: () => AssetService.getAssets({ dagIds, limit, namePattern, offset, onlyActive, orderBy, uriPattern }) as TData, ...options }); /** @@ -42,7 +42,7 @@ export const useAssetServiceGetAssetAliases = , "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseAssetServiceGetAssetAliasesKeyFn({ limit, namePattern, offset, orderBy }, queryKey), queryFn: () => AssetService.getAssetAliases({ limit, namePattern, offset, orderBy }) as TData, ...options }); /** * Get Asset Alias @@ -76,7 +76,7 @@ export const useAssetServiceGetAssetEvents = , "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseBackfillServiceListBackfillsKeyFn({ dagId, limit, offset, orderBy }, queryKey), queryFn: () => BackfillService.listBackfills({ dagId, limit, offset, orderBy }) as TData, ...options }); /** * Get Backfill @@ -188,7 +188,7 @@ export const useBackfillServiceListBackfillsUi = , "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseBackfillServiceListBackfillsUiKeyFn({ active, dagId, limit, offset, orderBy }, queryKey), queryFn: () => BackfillService.listBackfillsUi({ active, dagId, limit, offset, orderBy }) as TData, ...options }); /** * Get Connection @@ -216,7 +216,7 @@ export const useConnectionServiceGetConnections = , "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseConnectionServiceGetConnectionsKeyFn({ connectionIdPattern, limit, offset, orderBy }, queryKey), queryFn: () => ConnectionService.getConnections({ connectionIdPattern, limit, offset, orderBy }) as TData, ...options }); /** * Hook Meta Data @@ -284,7 +284,7 @@ export const useDagRunServiceGetDagRuns = , "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseDagWarningServiceListDagWarningsKeyFn({ dagId, limit, offset, orderBy, warningType }, queryKey), queryFn: () => DagWarningService.listDagWarnings({ dagId, limit, offset, orderBy, warningType }) as TData, ...options }); /** @@ -455,7 +455,7 @@ export const useDagServiceGetDags = = unknown[]>({ limit, offset, orderBy, tagNamePattern }: { limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; tagNamePattern?: string; } = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseDagServiceGetDagTagsKeyFn({ limit, offset, orderBy, tagNamePattern }, queryKey), queryFn: () => DagService.getDagTags({ limit, offset, orderBy, tagNamePattern }) as TData, ...options }); /** @@ -531,7 +531,7 @@ export const useDagServiceGetDagsUi = = unknown[]>({ limit, offset, orderBy }: { limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; } = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseImportErrorServiceGetImportErrorsKeyFn({ limit, offset, orderBy }, queryKey), queryFn: () => ImportErrorService.getImportErrors({ limit, offset, orderBy }) as TData, ...options }); /** * Get Jobs @@ -979,7 +979,7 @@ export const useJobServiceGetJobs = , "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseJobServiceGetJobsKeyFn({ endDateGte, endDateLte, executorClass, hostname, isAlive, jobState, jobType, limit, offset, orderBy, startDateGte, startDateLte }, queryKey), queryFn: () => JobService.getJobs({ endDateGte, endDateLte, executorClass, hostname, isAlive, jobState, jobType, limit, offset, orderBy, startDateGte, startDateLte }) as TData, ...options }); @@ -1026,7 +1026,7 @@ export const usePoolServiceGetPool = = unknown[]>({ limit, offset, orderBy, poolNamePattern }: { limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; poolNamePattern?: string; } = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UsePoolServiceGetPoolsKeyFn({ limit, offset, orderBy, poolNamePattern }, queryKey), queryFn: () => PoolService.getPools({ limit, offset, orderBy, poolNamePattern }) as TData, ...options }); /** @@ -1141,7 +1141,7 @@ export const useVariableServiceGetVariable = = unknown[]>({ limit, offset, orderBy, variableKeyPattern }: { limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; variableKeyPattern?: string; } = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseVariableServiceGetVariablesKeyFn({ limit, offset, orderBy, variableKeyPattern }, queryKey), queryFn: () => VariableService.getVariables({ limit, offset, orderBy, variableKeyPattern }) as TData, ...options }); /** @@ -1179,7 +1179,7 @@ export const useDagVersionServiceGetDagVersions = , "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseDagVersionServiceGetDagVersionsKeyFn({ bundleName, bundleVersion, dagId, limit, offset, orderBy, versionNumber }, queryKey), queryFn: () => DagVersionService.getDagVersions({ bundleName, bundleVersion, dagId, limit, offset, orderBy, versionNumber }) as TData, ...options }); /** @@ -1237,7 +1237,7 @@ export const useHumanInTheLoopServiceGetHitlDetails = , "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseGridServiceGetDagStructureKeyFn({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }, queryKey), queryFn: () => GridService.getDagStructure({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }) as TData, ...options }); @@ -1374,7 +1374,7 @@ export const useGridServiceGetGridRuns = , "queryKey" | "queryFn">) => useQuery({ queryKey: Common.UseGridServiceGetGridRunsKeyFn({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }, queryKey), queryFn: () => GridService.getGridRuns({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }) as TData, ...options }); 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 2d4773f6fa87d..e1e5d6cd1ea2f 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts @@ -24,7 +24,7 @@ export const useAssetServiceGetAssetsSuspense = , "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseAssetServiceGetAssetsKeyFn({ dagIds, limit, namePattern, offset, onlyActive, orderBy, uriPattern }, queryKey), queryFn: () => AssetService.getAssets({ dagIds, limit, namePattern, offset, onlyActive, orderBy, uriPattern }) as TData, ...options }); /** @@ -42,7 +42,7 @@ export const useAssetServiceGetAssetAliasesSuspense = , "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseAssetServiceGetAssetAliasesKeyFn({ limit, namePattern, offset, orderBy }, queryKey), queryFn: () => AssetService.getAssetAliases({ limit, namePattern, offset, orderBy }) as TData, ...options }); /** * Get Asset Alias @@ -76,7 +76,7 @@ export const useAssetServiceGetAssetEventsSuspense = , "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseBackfillServiceListBackfillsKeyFn({ dagId, limit, offset, orderBy }, queryKey), queryFn: () => BackfillService.listBackfills({ dagId, limit, offset, orderBy }) as TData, ...options }); /** * Get Backfill @@ -188,7 +188,7 @@ export const useBackfillServiceListBackfillsUiSuspense = , "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseBackfillServiceListBackfillsUiKeyFn({ active, dagId, limit, offset, orderBy }, queryKey), queryFn: () => BackfillService.listBackfillsUi({ active, dagId, limit, offset, orderBy }) as TData, ...options }); /** * Get Connection @@ -216,7 +216,7 @@ export const useConnectionServiceGetConnectionsSuspense = , "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseConnectionServiceGetConnectionsKeyFn({ connectionIdPattern, limit, offset, orderBy }, queryKey), queryFn: () => ConnectionService.getConnections({ connectionIdPattern, limit, offset, orderBy }) as TData, ...options }); /** * Hook Meta Data @@ -284,7 +284,7 @@ export const useDagRunServiceGetDagRunsSuspense = , "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseDagWarningServiceListDagWarningsKeyFn({ dagId, limit, offset, orderBy, warningType }, queryKey), queryFn: () => DagWarningService.listDagWarnings({ dagId, limit, offset, orderBy, warningType }) as TData, ...options }); /** @@ -455,7 +455,7 @@ export const useDagServiceGetDagsSuspense = = unknown[]>({ limit, offset, orderBy, tagNamePattern }: { limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; tagNamePattern?: string; } = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseDagServiceGetDagTagsKeyFn({ limit, offset, orderBy, tagNamePattern }, queryKey), queryFn: () => DagService.getDagTags({ limit, offset, orderBy, tagNamePattern }) as TData, ...options }); /** @@ -531,7 +531,7 @@ export const useDagServiceGetDagsUiSuspense = = unknown[]>({ limit, offset, orderBy }: { limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; } = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseImportErrorServiceGetImportErrorsKeyFn({ limit, offset, orderBy }, queryKey), queryFn: () => ImportErrorService.getImportErrors({ limit, offset, orderBy }) as TData, ...options }); /** * Get Jobs @@ -979,7 +979,7 @@ export const useJobServiceGetJobsSuspense = , "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseJobServiceGetJobsKeyFn({ endDateGte, endDateLte, executorClass, hostname, isAlive, jobState, jobType, limit, offset, orderBy, startDateGte, startDateLte }, queryKey), queryFn: () => JobService.getJobs({ endDateGte, endDateLte, executorClass, hostname, isAlive, jobState, jobType, limit, offset, orderBy, startDateGte, startDateLte }) as TData, ...options }); @@ -1026,7 +1026,7 @@ export const usePoolServiceGetPoolSuspense = = unknown[]>({ limit, offset, orderBy, poolNamePattern }: { limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; poolNamePattern?: string; } = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UsePoolServiceGetPoolsKeyFn({ limit, offset, orderBy, poolNamePattern }, queryKey), queryFn: () => PoolService.getPools({ limit, offset, orderBy, poolNamePattern }) as TData, ...options }); /** @@ -1141,7 +1141,7 @@ export const useVariableServiceGetVariableSuspense = = unknown[]>({ limit, offset, orderBy, variableKeyPattern }: { limit?: number; offset?: number; - orderBy?: string; + orderBy?: string[]; variableKeyPattern?: string; } = {}, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseVariableServiceGetVariablesKeyFn({ limit, offset, orderBy, variableKeyPattern }, queryKey), queryFn: () => VariableService.getVariables({ limit, offset, orderBy, variableKeyPattern }) as TData, ...options }); /** @@ -1179,7 +1179,7 @@ export const useDagVersionServiceGetDagVersionsSuspense = , "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseDagVersionServiceGetDagVersionsKeyFn({ bundleName, bundleVersion, dagId, limit, offset, orderBy, versionNumber }, queryKey), queryFn: () => DagVersionService.getDagVersions({ bundleName, bundleVersion, dagId, limit, offset, orderBy, versionNumber }) as TData, ...options }); /** @@ -1237,7 +1237,7 @@ export const useHumanInTheLoopServiceGetHitlDetailsSuspense = , "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseGridServiceGetDagStructureKeyFn({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }, queryKey), queryFn: () => GridService.getDagStructure({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }) as TData, ...options }); @@ -1374,7 +1374,7 @@ export const useGridServiceGetGridRunsSuspense = , "queryKey" | "queryFn">) => useSuspenseQuery({ queryKey: Common.UseGridServiceGetGridRunsKeyFn({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }, queryKey), queryFn: () => GridService.getGridRuns({ dagId, limit, offset, orderBy, runAfterGte, runAfterLte }) as TData, ...options }); 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 c5a8664463cb4..07e8141047d08 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 @@ -1941,7 +1941,7 @@ export type GetAssetsData = { namePattern?: string | null; offset?: number; onlyActive?: boolean; - orderBy?: string; + orderBy?: Array<(string)>; /** * SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. */ @@ -1957,7 +1957,7 @@ export type GetAssetAliasesData = { */ namePattern?: string | null; offset?: number; - orderBy?: string; + orderBy?: Array<(string)>; }; export type GetAssetAliasesResponse = AssetAliasCollectionResponse; @@ -1972,7 +1972,7 @@ export type GetAssetEventsData = { assetId?: number | null; limit?: number; offset?: number; - orderBy?: string; + orderBy?: Array<(string)>; sourceDagId?: string | null; sourceMapIndex?: number | null; sourceRunId?: string | null; @@ -2057,7 +2057,7 @@ export type ListBackfillsData = { dagId: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: Array<(string)>; }; export type ListBackfillsResponse = BackfillCollectionResponse; @@ -2103,7 +2103,7 @@ export type ListBackfillsUiData = { dagId?: string | null; limit?: number; offset?: number; - orderBy?: string; + orderBy?: Array<(string)>; }; export type ListBackfillsUiResponse = BackfillCollectionResponse; @@ -2135,7 +2135,7 @@ export type GetConnectionsData = { connectionIdPattern?: string | null; limit?: number; offset?: number; - orderBy?: string; + orderBy?: Array<(string)>; }; export type GetConnectionsResponse = ConnectionCollectionResponse; @@ -2208,7 +2208,7 @@ export type GetDagRunsData = { logicalDateGte?: string | null; logicalDateLte?: string | null; offset?: number; - orderBy?: string; + orderBy?: Array<(string)>; runAfterGte?: string | null; runAfterLte?: string | null; /** @@ -2295,7 +2295,7 @@ export type ListDagWarningsData = { dagId?: string | null; limit?: number; offset?: number; - orderBy?: string; + orderBy?: Array<(string)>; warningType?: DagWarningType | null; }; @@ -2320,7 +2320,7 @@ export type GetDagsData = { lastDagRunState?: DagRunState | null; limit?: number; offset?: number; - orderBy?: string; + orderBy?: Array<(string)>; owners?: Array<(string)>; paused?: boolean | null; tags?: Array<(string)>; @@ -2388,7 +2388,7 @@ export type UnfavoriteDagResponse = void; export type GetDagTagsData = { limit?: number; offset?: number; - orderBy?: string; + orderBy?: Array<(string)>; /** * SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. */ @@ -2413,7 +2413,7 @@ export type GetDagsUiData = { lastDagRunState?: DagRunState | null; limit?: number; offset?: number; - orderBy?: string; + orderBy?: Array<(string)>; owners?: Array<(string)>; paused?: boolean | null; tags?: Array<(string)>; @@ -2444,7 +2444,7 @@ export type GetEventLogsData = { limit?: number; mapIndex?: number | null; offset?: number; - orderBy?: string; + orderBy?: Array<(string)>; owner?: string | null; runId?: string | null; taskId?: string | null; @@ -2502,7 +2502,7 @@ export type GetMappedTaskInstancesData = { logicalDateGte?: string | null; logicalDateLte?: string | null; offset?: number; - orderBy?: string; + orderBy?: Array<(string)>; pool?: Array<(string)>; queue?: Array<(string)>; runAfterGte?: string | null; @@ -2586,7 +2586,7 @@ export type GetTaskInstancesData = { logicalDateGte?: string | null; logicalDateLte?: string | null; offset?: number; - orderBy?: string; + orderBy?: Array<(string)>; pool?: Array<(string)>; queue?: Array<(string)>; runAfterGte?: string | null; @@ -2703,7 +2703,7 @@ export type GetImportErrorResponse = ImportErrorResponse; export type GetImportErrorsData = { limit?: number; offset?: number; - orderBy?: string; + orderBy?: Array<(string)>; }; export type GetImportErrorsResponse = ImportErrorCollectionResponse; @@ -2718,7 +2718,7 @@ export type GetJobsData = { jobType?: string | null; limit?: number; offset?: number; - orderBy?: string; + orderBy?: Array<(string)>; startDateGte?: string | null; startDateLte?: string | null; }; @@ -2757,7 +2757,7 @@ export type PatchPoolResponse = PoolResponse; export type GetPoolsData = { limit?: number; offset?: number; - orderBy?: string; + orderBy?: Array<(string)>; /** * SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. */ @@ -2865,7 +2865,7 @@ export type PatchVariableResponse = VariableResponse; export type GetVariablesData = { limit?: number; offset?: number; - orderBy?: string; + orderBy?: Array<(string)>; /** * SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported. */ @@ -2905,7 +2905,7 @@ export type GetDagVersionsData = { dagId: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: Array<(string)>; versionNumber?: number; }; @@ -2959,7 +2959,7 @@ export type GetHitlDetailsData = { dagRunId?: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: Array<(string)>; responseReceived?: boolean | null; state?: Array<(string)>; /** @@ -3019,7 +3019,7 @@ export type GetDagStructureData = { dagId: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: Array<(string)>; runAfterGte?: string | null; runAfterLte?: string | null; }; @@ -3030,7 +3030,7 @@ export type GetGridRunsData = { dagId: string; limit?: number; offset?: number; - orderBy?: string; + orderBy?: Array<(string)>; runAfterGte?: string | null; runAfterLte?: string | null; }; diff --git a/airflow-core/src/airflow/ui/src/components/DagVersionSelect.tsx b/airflow-core/src/airflow/ui/src/components/DagVersionSelect.tsx index 9ea751d2ed2ee..5e386a7c484b5 100644 --- a/airflow-core/src/airflow/ui/src/components/DagVersionSelect.tsx +++ b/airflow-core/src/airflow/ui/src/components/DagVersionSelect.tsx @@ -36,7 +36,7 @@ type VersionSelected = { export const DagVersionSelect = ({ showLabel = true }: { readonly showLabel?: boolean }) => { const { t: translate } = useTranslation("components"); const { dagId = "" } = useParams(); - const { data, isLoading } = useDagVersionServiceGetDagVersions({ dagId, orderBy: "-version_number" }); + const { data, isLoading } = useDagVersionServiceGetDagVersions({ dagId, orderBy: ["-version_number"] }); const [searchParams, setSearchParams] = useSearchParams(); const selectedVersionNumber = useSelectedVersion(); const selectedVersion = data?.dag_versions.find((dv) => dv.version_number === selectedVersionNumber); diff --git a/airflow-core/src/airflow/ui/src/pages/Asset/AssetLayout.tsx b/airflow-core/src/airflow/ui/src/pages/Asset/AssetLayout.tsx index 516a03ba9ff85..51a1442fcc90b 100644 --- a/airflow-core/src/airflow/ui/src/pages/Asset/AssetLayout.tsx +++ b/airflow-core/src/airflow/ui/src/pages/Asset/AssetLayout.tsx @@ -41,7 +41,7 @@ export const AssetLayout = () => { const { setTableURLState, tableURLState } = useTableURLState(); const { pagination, sorting } = tableURLState; const [sort] = sorting; - const orderBy = sort ? `${sort.desc ? "-" : ""}${sort.id}` : "-timestamp"; + const orderBy = sort ? [`${sort.desc ? "-" : ""}${sort.id}`] : ["-timestamp"]; const { data: asset, isLoading } = useAssetServiceGetAsset( { assetId: assetId === undefined ? 0 : parseInt(assetId, 10) }, diff --git a/airflow-core/src/airflow/ui/src/pages/AssetsList/AssetsList.tsx b/airflow-core/src/airflow/ui/src/pages/AssetsList/AssetsList.tsx index b524972fc0a22..047b537bc95bc 100644 --- a/airflow-core/src/airflow/ui/src/pages/AssetsList/AssetsList.tsx +++ b/airflow-core/src/airflow/ui/src/pages/AssetsList/AssetsList.tsx @@ -103,7 +103,7 @@ export const AssetsList = () => { const { setTableURLState, tableURLState } = useTableURLState(); const { pagination, sorting } = tableURLState; const [sort] = sorting; - const orderBy = sort ? `${sort.desc ? "-" : ""}${sort.id}` : undefined; + const orderBy = sort ? [`${sort.desc ? "-" : ""}${sort.id}`] : undefined; const { data, error, isLoading } = useAssetServiceGetAssets({ limit: pagination.pageSize, diff --git a/airflow-core/src/airflow/ui/src/pages/Connections/Connections.tsx b/airflow-core/src/airflow/ui/src/pages/Connections/Connections.tsx index 5a33e52975ce7..4ff052ec3a9a3 100644 --- a/airflow-core/src/airflow/ui/src/pages/Connections/Connections.tsx +++ b/airflow-core/src/airflow/ui/src/pages/Connections/Connections.tsx @@ -135,7 +135,7 @@ export const Connections = () => { useConnectionTypeMeta(); // Pre-fetch connection type metadata const { pagination, sorting } = tableURLState; const [sort] = sorting; - const orderBy = sort ? `${sort.desc ? "-" : ""}${sort.id}` : "connection_id"; + const orderBy = sort ? [`${sort.desc ? "-" : ""}${sort.id}`] : ["connection_id"]; const { data, error, isFetching, isLoading } = useConnectionServiceGetConnections({ connectionIdPattern: connectionIdPattern ?? undefined, limit: pagination.pageSize, diff --git a/airflow-core/src/airflow/ui/src/pages/Dag/Overview/Overview.tsx b/airflow-core/src/airflow/ui/src/pages/Dag/Overview/Overview.tsx index 665b47b5da492..0a0c13c4ef251 100644 --- a/airflow-core/src/airflow/ui/src/pages/Dag/Overview/Overview.tsx +++ b/airflow-core/src/airflow/ui/src/pages/Dag/Overview/Overview.tsx @@ -50,7 +50,7 @@ export const Overview = () => { const { data: failedTasks, isLoading } = useTaskInstanceServiceGetTaskInstances({ dagId: dagId ?? "", dagRunId: "~", - orderBy: "-run_after", + orderBy: ["-run_after"], runAfterGte: startDate, runAfterLte: endDate, state: ["failed"], @@ -67,7 +67,7 @@ export const Overview = () => { const { data: gridRuns, isLoading: isLoadingRuns } = useGridRuns({ limit }); const { data: assetEventsData, isLoading: isLoadingAssetEvents } = useAssetServiceGetAssetEvents({ limit, - orderBy: assetSortBy, + orderBy: [assetSortBy], sourceDagId: dagId, timestampGte: startDate, timestampLte: endDate, diff --git a/airflow-core/src/airflow/ui/src/pages/Dag/Tasks/TaskCard.tsx b/airflow-core/src/airflow/ui/src/pages/Dag/Tasks/TaskCard.tsx index 09f7de15f6e3d..83f1635cbc355 100644 --- a/airflow-core/src/airflow/ui/src/pages/Dag/Tasks/TaskCard.tsx +++ b/airflow-core/src/airflow/ui/src/pages/Dag/Tasks/TaskCard.tsx @@ -44,7 +44,7 @@ export const TaskCard = ({ dagId, task }: Props) => { dagId, dagRunId: "~", limit: 14, - orderBy: "-run_after", + orderBy: ["-run_after"], taskId: task.task_id ?? "", }, undefined, diff --git a/airflow-core/src/airflow/ui/src/pages/DagRuns.tsx b/airflow-core/src/airflow/ui/src/pages/DagRuns.tsx index 1ea3f965a07a6..8215488a753ee 100644 --- a/airflow-core/src/airflow/ui/src/pages/DagRuns.tsx +++ b/airflow-core/src/airflow/ui/src/pages/DagRuns.tsx @@ -162,7 +162,7 @@ export const DagRuns = () => { const { setTableURLState, tableURLState } = useTableURLState(); const { pagination, sorting } = tableURLState; const [sort] = sorting; - const orderBy = sort ? `${sort.desc ? "-" : ""}${sort.id}` : "-run_after"; + const orderBy = sort ? [`${sort.desc ? "-" : ""}${sort.id}`] : ["-run_after"]; const { pageIndex, pageSize } = pagination; const filteredState = searchParams.get(STATE_PARAM); diff --git a/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/DagsFilters.tsx b/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/DagsFilters.tsx index 5a72213671f14..bb84ed99fcfd6 100644 --- a/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/DagsFilters.tsx +++ b/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/DagsFilters.tsx @@ -84,7 +84,7 @@ export const DagsFilters = () => { const { data, fetchNextPage, fetchPreviousPage } = useDagTagsInfinite({ limit: 10, - orderBy: "name", + orderBy: ["name"], tagNamePattern: pattern, }); diff --git a/airflow-core/src/airflow/ui/src/pages/DagsList/DagsList.tsx b/airflow-core/src/airflow/ui/src/pages/DagsList/DagsList.tsx index b9f3136f0b0d1..7874008f6ad56 100644 --- a/airflow-core/src/airflow/ui/src/pages/DagsList/DagsList.tsx +++ b/airflow-core/src/airflow/ui/src/pages/DagsList/DagsList.tsx @@ -250,7 +250,7 @@ export const DagsList = () => { lastDagRunState, limit: pagination.pageSize, offset: pagination.pageIndex * pagination.pageSize, - orderBy, + orderBy: [orderBy], owners, paused, tags: selectedTags, diff --git a/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/HistoricalMetrics.tsx b/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/HistoricalMetrics.tsx index 24230eaba00bd..2ccae75e91966 100644 --- a/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/HistoricalMetrics.tsx +++ b/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/HistoricalMetrics.tsx @@ -63,7 +63,7 @@ export const HistoricalMetrics = () => { const { data: assetEventsData, isLoading: isLoadingAssetEvents } = useAssetServiceGetAssetEvents({ limit: 6, - orderBy: assetSortBy, + orderBy: [assetSortBy], timestampGte: startDate, timestampLte: endDate, }); diff --git a/airflow-core/src/airflow/ui/src/pages/Events/Events.tsx b/airflow-core/src/airflow/ui/src/pages/Events/Events.tsx index f71e57b6419a1..d804ee30686e5 100644 --- a/airflow-core/src/airflow/ui/src/pages/Events/Events.tsx +++ b/airflow-core/src/airflow/ui/src/pages/Events/Events.tsx @@ -149,7 +149,7 @@ export const Events = () => { const [sort] = sorting; const { onClose, onOpen, open } = useDisclosure(); - const orderBy = sort ? `${sort.desc ? "-" : ""}${sort.id}` : "-when"; + const orderBy = sort ? [`${sort.desc ? "-" : ""}${sort.id}`] : ["-when"]; const { data, error, isFetching, isLoading } = useEventLogServiceGetEventLogs( { diff --git a/airflow-core/src/airflow/ui/src/pages/Pools/Pools.tsx b/airflow-core/src/airflow/ui/src/pages/Pools/Pools.tsx index ff1ca88c9f4a1..8ab1cbfb493c1 100644 --- a/airflow-core/src/airflow/ui/src/pages/Pools/Pools.tsx +++ b/airflow-core/src/airflow/ui/src/pages/Pools/Pools.tsx @@ -59,7 +59,7 @@ export const Pools = () => { const { setTableURLState, tableURLState } = useTableURLState(); const { pagination, sorting } = tableURLState; const [sort] = sorting; - const orderBy = sort ? `${sort.desc ? "-" : ""}${sort.id}` : "name"; + const orderBy = sort ? [`${sort.desc ? "-" : ""}${sort.id}`] : ["name"]; const { data, error, isLoading } = usePoolServiceGetPools({ limit: pagination.pageSize, diff --git a/airflow-core/src/airflow/ui/src/pages/Task/Overview/Overview.tsx b/airflow-core/src/airflow/ui/src/pages/Task/Overview/Overview.tsx index 79b39d21b9f68..492f15feb8bad 100644 --- a/airflow-core/src/airflow/ui/src/pages/Task/Overview/Overview.tsx +++ b/airflow-core/src/airflow/ui/src/pages/Task/Overview/Overview.tsx @@ -57,7 +57,7 @@ export const Overview = () => { dagId, dagRunId: "~", limit: 14, - orderBy: "-run_after", + orderBy: ["-run_after"], taskDisplayNamePattern: groupId ?? undefined, taskId: Boolean(groupId) ? undefined : taskId, }, diff --git a/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx b/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx index 13d084a5c74ac..6285253571ee5 100644 --- a/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx +++ b/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx @@ -188,7 +188,7 @@ export const TaskInstances = () => { const { setTableURLState, tableURLState } = useTableURLState(); const { pagination, sorting } = tableURLState; const [sort] = sorting; - const orderBy = sort ? `${sort.desc ? "-" : ""}${sort.id}` : "-start_date"; + const orderBy = sort ? [`${sort.desc ? "-" : ""}${sort.id}`] : ["-start_date"]; const filteredState = searchParams.getAll(STATE_PARAM); const startDate = searchParams.get(START_DATE_PARAM); diff --git a/airflow-core/src/airflow/ui/src/pages/Variables/Variables.tsx b/airflow-core/src/airflow/ui/src/pages/Variables/Variables.tsx index 052da890b3660..3e4ccc2927a5c 100644 --- a/airflow-core/src/airflow/ui/src/pages/Variables/Variables.tsx +++ b/airflow-core/src/airflow/ui/src/pages/Variables/Variables.tsx @@ -124,7 +124,7 @@ export const Variables = () => { const [selectedVariables, setSelectedVariables] = useState>({}); const { pagination, sorting } = tableURLState; const [sort] = sorting; - const orderBy = sort ? `${sort.desc ? "-" : ""}${sort.id === "value" ? "_val" : sort.id}` : "-key"; + const orderBy = sort ? [`${sort.desc ? "-" : ""}${sort.id === "value" ? "_val" : sort.id}`] : ["-key"]; const { data, error, isFetching, isLoading } = useVariableServiceGetVariables({ limit: pagination.pageSize, diff --git a/airflow-core/src/airflow/ui/src/queries/useDagTagsInfinite.ts b/airflow-core/src/airflow/ui/src/queries/useDagTagsInfinite.ts index 40a779734f5c0..d049928c0ed69 100644 --- a/airflow-core/src/airflow/ui/src/queries/useDagTagsInfinite.ts +++ b/airflow-core/src/airflow/ui/src/queries/useDagTagsInfinite.ts @@ -29,7 +29,7 @@ export const useDagTagsInfinite = ( tagNamePattern, }: { limit?: number; - orderBy?: string; + orderBy?: Array; tagNamePattern?: string; } = {}, queryKey?: Array, diff --git a/airflow-core/src/airflow/ui/src/queries/useDags.tsx b/airflow-core/src/airflow/ui/src/queries/useDags.tsx index 6cacce11e9cd8..349c12f97b5a6 100644 --- a/airflow-core/src/airflow/ui/src/queries/useDags.tsx +++ b/airflow-core/src/airflow/ui/src/queries/useDags.tsx @@ -47,7 +47,7 @@ export const useDags = ({ lastDagRunState?: DagRunState; limit?: number; offset?: number; - orderBy?: string; + orderBy?: Array; owners?: Array; paused?: boolean; tags?: Array; diff --git a/airflow-core/src/airflow/ui/src/queries/useGridRuns.ts b/airflow-core/src/airflow/ui/src/queries/useGridRuns.ts index 096630852d435..42807a9a7bc8a 100644 --- a/airflow-core/src/airflow/ui/src/queries/useGridRuns.ts +++ b/airflow-core/src/airflow/ui/src/queries/useGridRuns.ts @@ -30,7 +30,7 @@ export const useGridRuns = ({ limit }: { limit: number }) => { { dagId, limit, - orderBy: "-run_after", + orderBy: ["-run_after"], }, undefined, { diff --git a/airflow-core/src/airflow/ui/src/queries/useGridStructure.ts b/airflow-core/src/airflow/ui/src/queries/useGridStructure.ts index eaeaede6050e6..17db10fffd591 100644 --- a/airflow-core/src/airflow/ui/src/queries/useGridStructure.ts +++ b/airflow-core/src/airflow/ui/src/queries/useGridStructure.ts @@ -36,7 +36,7 @@ export const useGridStructure = ({ { dagId, limit, - orderBy: "-run_after", + orderBy: ["-run_after"], }, undefined, { diff --git a/airflow-core/tests/unit/api_fastapi/common/db/test_dags.py b/airflow-core/tests/unit/api_fastapi/common/db/test_dags.py index 051ffa965cc7e..41065fbd4fc8f 100644 --- a/airflow-core/tests/unit/api_fastapi/common/db/test_dags.py +++ b/airflow-core/tests/unit/api_fastapi/common/db/test_dags.py @@ -114,7 +114,7 @@ def test_includes_queued_run_without_start_date(self, dag_with_queued_run, sessi dag_model, _ = dag_with_queued_run query = generate_dag_with_latest_run_query( max_run_filters=[], - order_by=SortParam(allowed_attrs=["dag_id"], model=DagModel).set_value("dag_id"), + order_by=SortParam(allowed_attrs=["dag_id"], model=DagModel).set_value(["dag_id"]), ) # Also fetch joined DagRun's state and start_date @@ -134,7 +134,9 @@ def test_includes_queued_run_when_ordering_by_state( query = generate_dag_with_latest_run_query( max_run_filters=[], - order_by=SortParam(allowed_attrs=["last_run_state"], model=DagModel).set_value("last_run_state"), + order_by=SortParam(allowed_attrs=["last_run_state"], model=DagModel).set_value( + ["last_run_state"] + ), ) extended_query = query.add_columns(DagRun.state, DagRun.start_date) result = session.execute(extended_query).fetchall() @@ -159,7 +161,7 @@ def test_includes_queued_run_when_ordering_by_start_date( query = generate_dag_with_latest_run_query( max_run_filters=[], order_by=SortParam(allowed_attrs=["last_run_start_date"], model=DagModel).set_value( - "last_run_start_date" + ["last_run_start_date"] ), ) extended_query = query.add_columns(DagRun.state, DagRun.start_date) @@ -207,7 +209,9 @@ def test_latest_queued_run_without_start_date_is_included(self, session): session.commit() query = generate_dag_with_latest_run_query( max_run_filters=[], - order_by=SortParam(allowed_attrs=["last_run_state"], model=DagModel).set_value("last_run_state"), + order_by=SortParam(allowed_attrs=["last_run_state"], model=DagModel).set_value( + ["last_run_state"] + ), ) extended_query = query.add_columns(DagRun.state, DagRun.start_date) result = session.execute(extended_query).fetchall() @@ -231,7 +235,9 @@ def test_queued_runs_with_null_start_date_are_properly_joined( running_dag_model, _ = dag_with_running_run query = generate_dag_with_latest_run_query( max_run_filters=[], - order_by=SortParam(allowed_attrs=["last_run_state"], model=DagModel).set_value("last_run_state"), + order_by=SortParam(allowed_attrs=["last_run_state"], model=DagModel).set_value( + ["last_run_state"] + ), ) extended_query = query.add_columns(DagRun.state, DagRun.start_date) diff --git a/airflow-core/tests/unit/api_fastapi/common/test_parameters.py b/airflow-core/tests/unit/api_fastapi/common/test_parameters.py new file mode 100644 index 0000000000000..cd77ded8acef9 --- /dev/null +++ b/airflow-core/tests/unit/api_fastapi/common/test_parameters.py @@ -0,0 +1,40 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +from __future__ import annotations + +import re + +import pytest +from fastapi import HTTPException + +from airflow.api_fastapi.common.parameters import SortParam + + +class TestSortParam: + def test_sort_param_max_number_of_filers(self): + param = SortParam([], None, None) + n_filters = param.MAX_SORT_PARAMS + 1 + param.value = [f"filter_{i}" for i in range(n_filters)] + + with pytest.raises( + HTTPException, + match=re.escape( + f"400: Ordering with more than {param.MAX_SORT_PARAMS} parameters is not allowed. Provided: {param.value}" + ), + ): + param.to_orm(None) diff --git a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_dags.py b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_dags.py index 84dbf60c2256d..60302878dba90 100644 --- a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_dags.py +++ b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_dags.py @@ -248,6 +248,11 @@ class TestGetDags(TestDagEndpoint): 3, [DAG3_ID, DAG1_ID, DAG2_ID], ), + ( + {"order_by": ["next_dagrun", "-dag_display_name"], "exclude_stale": False}, + 3, + [DAG3_ID, DAG2_ID, DAG1_ID], + ), # Search ({"dag_id_pattern": "1"}, 1, [DAG1_ID]), ({"dag_display_name_pattern": "test_dag2"}, 1, [DAG2_ID]),