This is an automated email from the ASF dual-hosted git repository.
dheerajturaga pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new 51972109907 UI: Add Run ID filter to the Grid view (#70150)
51972109907 is described below
commit 51972109907ca274bbfa52aff3e2c71c7b02bcab
Author: Dheeraj Turaga <[email protected]>
AuthorDate: Mon Jul 27 13:08:22 2026 -0500
UI: Add Run ID filter to the Grid view (#70150)
The Dag Runs list page lets users narrow runs by Run ID, but the Grid
view's filter bar offered no equivalent, forcing users to eyeball run
columns to locate a specific run. Expose the same Run ID search on the
Grid so both surfaces filter consistently.
The pill exposes the same substring/prefix advanced-search toggle used
elsewhere; the Grid query hooks route the value through
``useAdvancedSearchArg`` so the toggle chooses between the substring
``run_id_pattern`` and the index-friendly ``run_id_prefix_pattern``
variant on each request.
---
.../api_fastapi/core_api/openapi/_private_ui.yaml | 52 ++++++++++++++++++++++
.../airflow/api_fastapi/core_api/routes/ui/grid.py | 34 +++++++++++++-
.../src/airflow/ui/openapi-gen/queries/common.ts | 12 +++--
.../ui/openapi-gen/queries/ensureQueryData.ts | 16 +++++--
.../src/airflow/ui/openapi-gen/queries/prefetch.ts | 16 +++++--
.../src/airflow/ui/openapi-gen/queries/queries.ts | 16 +++++--
.../src/airflow/ui/openapi-gen/queries/suspense.ts | 16 +++++--
.../ui/openapi-gen/requests/services.gen.ts | 12 ++++-
.../airflow/ui/openapi-gen/requests/types.gen.ts | 16 +++++++
.../ui/src/layouts/Details/DetailsLayout.tsx | 5 +++
.../airflow/ui/src/layouts/Details/Gantt/Gantt.tsx | 4 ++
.../airflow/ui/src/layouts/Details/Grid/Grid.tsx | 4 ++
.../airflow/ui/src/layouts/Details/GridFilters.tsx | 1 +
.../src/airflow/ui/src/queries/useGridRuns.ts | 14 ++++++
.../src/airflow/ui/src/queries/useGridStructure.ts | 14 ++++++
.../api_fastapi/core_api/routes/ui/test_grid.py | 33 ++++++++++++++
16 files changed, 241 insertions(+), 24 deletions(-)
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 94489a199e9..f16b2bbc9fe 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
@@ -1282,6 +1282,32 @@ paths:
title: Triggering User Prefix
description: Case-sensitive, index-friendly prefix match. See
"Filtering with
pattern parameters".
+ - name: run_id_pattern
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: "Case-insensitive substring match (SQL `ILIKE`). Slower
than\
+ \ `run_id_prefix_pattern` on large tables \u2014 see \"Filtering
with\
+ \ pattern parameters\"."
+ title: Run Id Pattern
+ description: "Case-insensitive substring match (SQL `ILIKE`). Slower
than\
+ \ `run_id_prefix_pattern` on large tables \u2014 see \"Filtering
with pattern\
+ \ parameters\"."
+ - name: run_id_prefix_pattern
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: Case-sensitive, index-friendly prefix match. See
"Filtering
+ with pattern parameters".
+ title: Run Id Prefix Pattern
+ description: Case-sensitive, index-friendly prefix match. See
"Filtering with
+ pattern parameters".
responses:
'200':
description: Successful Response
@@ -1437,6 +1463,32 @@ paths:
title: Triggering User Prefix
description: Case-sensitive, index-friendly prefix match. See
"Filtering with
pattern parameters".
+ - name: run_id_pattern
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: "Case-insensitive substring match (SQL `ILIKE`). Slower
than\
+ \ `run_id_prefix_pattern` on large tables \u2014 see \"Filtering
with\
+ \ pattern parameters\"."
+ title: Run Id Pattern
+ description: "Case-insensitive substring match (SQL `ILIKE`). Slower
than\
+ \ `run_id_prefix_pattern` on large tables \u2014 see \"Filtering
with pattern\
+ \ parameters\"."
+ - name: run_id_prefix_pattern
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ description: Case-sensitive, index-friendly prefix match. See
"Filtering
+ with pattern parameters".
+ title: Run Id Prefix Pattern
+ description: Case-sensitive, index-friendly prefix match. See
"Filtering with
+ pattern parameters".
responses:
'200':
description: Successful Response
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 8a0c55d315e..9cd5b6e60d9 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
@@ -42,7 +42,11 @@ from airflow.api_fastapi.common.parameters import (
QueryOffset,
RangeFilter,
SortParam,
+ _PrefixSearchParam,
+ _SearchParam,
datetime_range_filter_factory,
+ prefix_search_param_factory,
+ search_param_factory,
)
from airflow.api_fastapi.common.router import AirflowRouter
from airflow.api_fastapi.core_api.datamodels.ui.common import (
@@ -144,6 +148,11 @@ def get_dag_structure(
state: QueryDagRunStateFilter,
triggering_user: QueryDagRunTriggeringUserSearch,
triggering_user_prefix: QueryDagRunTriggeringUserPrefixSearch,
+ run_id_pattern: Annotated[_SearchParam,
Depends(search_param_factory(DagRun.run_id, "run_id_pattern"))],
+ run_id_prefix_pattern: Annotated[
+ _PrefixSearchParam,
+ Depends(prefix_search_param_factory(DagRun.run_id,
"run_id_prefix_pattern")),
+ ],
include_upstream: QueryIncludeUpstream = False,
include_downstream: QueryIncludeDownstream = False,
depth: int | None = None,
@@ -177,7 +186,15 @@ def get_dag_structure(
statement=base_query,
order_by=order_by,
offset=offset,
- filters=[run_after, run_type, state, triggering_user,
triggering_user_prefix],
+ filters=[
+ run_after,
+ run_type,
+ state,
+ triggering_user,
+ triggering_user_prefix,
+ run_id_pattern,
+ run_id_prefix_pattern,
+ ],
limit=limit,
)
run_ids = list(session.scalars(dag_runs_select_filter))
@@ -282,6 +299,11 @@ def get_grid_runs(
state: QueryDagRunStateFilter,
triggering_user: QueryDagRunTriggeringUserSearch,
triggering_user_prefix: QueryDagRunTriggeringUserPrefixSearch,
+ run_id_pattern: Annotated[_SearchParam,
Depends(search_param_factory(DagRun.run_id, "run_id_pattern"))],
+ run_id_prefix_pattern: Annotated[
+ _PrefixSearchParam,
+ Depends(prefix_search_param_factory(DagRun.run_id,
"run_id_prefix_pattern")),
+ ],
) -> list[GridRunsResponse]:
"""Get info about a run for the grid."""
# Retrieve, sort the previous Dag Runs
@@ -330,7 +352,15 @@ def get_grid_runs(
statement=base_query,
order_by=order_by,
offset=offset,
- filters=[run_after, run_type, state, triggering_user,
triggering_user_prefix],
+ filters=[
+ run_after,
+ run_type,
+ state,
+ triggering_user,
+ triggering_user_prefix,
+ run_id_pattern,
+ run_id_prefix_pattern,
+ ],
limit=limit,
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 4f485202973..05a4b47ec1b 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts
@@ -991,7 +991,7 @@ export const UseStructureServiceStructureDataKeyFn = ({
dagId, depth, externalDe
export type GridServiceGetDagStructureDefaultResponse =
Awaited<ReturnType<typeof GridService.getDagStructure>>;
export type GridServiceGetDagStructureQueryResult<TData =
GridServiceGetDagStructureDefaultResponse, TError = unknown> =
UseQueryResult<TData, TError>;
export const useGridServiceGetDagStructureKey = "GridServiceGetDagStructure";
-export const UseGridServiceGetDagStructureKeyFn = ({ dagId, depth,
includeDownstream, includeUpstream, limit, offset, orderBy, root, runAfterGt,
runAfterGte, runAfterLt, runAfterLte, runType, state, triggeringUser,
triggeringUserPrefix }: {
+export const UseGridServiceGetDagStructureKeyFn = ({ dagId, depth,
includeDownstream, includeUpstream, limit, offset, orderBy, root, runAfterGt,
runAfterGte, runAfterLt, runAfterLte, runIdPattern, runIdPrefixPattern,
runType, state, triggeringUser, triggeringUserPrefix }: {
dagId: string;
depth?: number;
includeDownstream?: boolean;
@@ -1004,15 +1004,17 @@ export const UseGridServiceGetDagStructureKeyFn = ({
dagId, depth, includeDownst
runAfterGte?: string;
runAfterLt?: string;
runAfterLte?: string;
+ runIdPattern?: string;
+ runIdPrefixPattern?: string;
runType?: string[];
state?: string[];
triggeringUser?: string;
triggeringUserPrefix?: string;
-}, queryKey?: Array<unknown>) => [useGridServiceGetDagStructureKey,
...(queryKey ?? [{ dagId, depth, includeDownstream, includeUpstream, limit,
offset, orderBy, root, runAfterGt, runAfterGte, runAfterLt, runAfterLte,
runType, state, triggeringUser, triggeringUserPrefix }])];
+}, queryKey?: Array<unknown>) => [useGridServiceGetDagStructureKey,
...(queryKey ?? [{ dagId, depth, includeDownstream, includeUpstream, limit,
offset, orderBy, root, runAfterGt, runAfterGte, runAfterLt, runAfterLte,
runIdPattern, runIdPrefixPattern, runType, state, triggeringUser,
triggeringUserPrefix }])];
export type GridServiceGetGridRunsDefaultResponse = Awaited<ReturnType<typeof
GridService.getGridRuns>>;
export type GridServiceGetGridRunsQueryResult<TData =
GridServiceGetGridRunsDefaultResponse, TError = unknown> =
UseQueryResult<TData, TError>;
export const useGridServiceGetGridRunsKey = "GridServiceGetGridRuns";
-export const UseGridServiceGetGridRunsKeyFn = ({ dagId, limit, offset,
orderBy, runAfterGt, runAfterGte, runAfterLt, runAfterLte, runType, state,
triggeringUser, triggeringUserPrefix }: {
+export const UseGridServiceGetGridRunsKeyFn = ({ dagId, limit, offset,
orderBy, runAfterGt, runAfterGte, runAfterLt, runAfterLte, runIdPattern,
runIdPrefixPattern, runType, state, triggeringUser, triggeringUserPrefix }: {
dagId: string;
limit?: number;
offset?: number;
@@ -1021,11 +1023,13 @@ export const UseGridServiceGetGridRunsKeyFn = ({ dagId,
limit, offset, orderBy,
runAfterGte?: string;
runAfterLt?: string;
runAfterLte?: string;
+ runIdPattern?: string;
+ runIdPrefixPattern?: string;
runType?: string[];
state?: string[];
triggeringUser?: string;
triggeringUserPrefix?: string;
-}, queryKey?: Array<unknown>) => [useGridServiceGetGridRunsKey, ...(queryKey
?? [{ dagId, limit, offset, orderBy, runAfterGt, runAfterGte, runAfterLt,
runAfterLte, runType, state, triggeringUser, triggeringUserPrefix }])];
+}, queryKey?: Array<unknown>) => [useGridServiceGetGridRunsKey, ...(queryKey
?? [{ dagId, limit, offset, orderBy, runAfterGt, runAfterGte, runAfterLt,
runAfterLte, runIdPattern, runIdPrefixPattern, runType, state, triggeringUser,
triggeringUserPrefix }])];
export type GridServiceGetGridTiSummariesStreamDefaultResponse =
Awaited<ReturnType<typeof GridService.getGridTiSummariesStream>>;
export type GridServiceGetGridTiSummariesStreamQueryResult<TData =
GridServiceGetGridTiSummariesStreamDefaultResponse, TError = unknown> =
UseQueryResult<TData, TError>;
export const useGridServiceGetGridTiSummariesStreamKey =
"GridServiceGetGridTiSummariesStream";
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 8f3fcea0d76..f16710ae81d 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts
@@ -1921,10 +1921,12 @@ export const ensureUseStructureServiceStructureDataData
= (queryClient: QueryCli
* @param data.state
* @param data.triggeringUser Case-insensitive substring match (SQL `ILIKE`).
Slower than `triggering_user` on large tables — see "Filtering with pattern
parameters".
* @param data.triggeringUserPrefix Case-sensitive, index-friendly prefix
match. See "Filtering with pattern parameters".
+* @param data.runIdPattern Case-insensitive substring match (SQL `ILIKE`).
Slower than `run_id_prefix_pattern` on large tables — see "Filtering with
pattern parameters".
+* @param data.runIdPrefixPattern Case-sensitive, index-friendly prefix match.
See "Filtering with pattern parameters".
* @returns GridNodeResponse Successful Response
* @throws ApiError
*/
-export const ensureUseGridServiceGetDagStructureData = (queryClient:
QueryClient, { dagId, depth, includeDownstream, includeUpstream, limit, offset,
orderBy, root, runAfterGt, runAfterGte, runAfterLt, runAfterLte, runType,
state, triggeringUser, triggeringUserPrefix }: {
+export const ensureUseGridServiceGetDagStructureData = (queryClient:
QueryClient, { dagId, depth, includeDownstream, includeUpstream, limit, offset,
orderBy, root, runAfterGt, runAfterGte, runAfterLt, runAfterLte, runIdPattern,
runIdPrefixPattern, runType, state, triggeringUser, triggeringUserPrefix }: {
dagId: string;
depth?: number;
includeDownstream?: boolean;
@@ -1937,11 +1939,13 @@ export const ensureUseGridServiceGetDagStructureData =
(queryClient: QueryClient
runAfterGte?: string;
runAfterLt?: string;
runAfterLte?: string;
+ runIdPattern?: string;
+ runIdPrefixPattern?: string;
runType?: string[];
state?: string[];
triggeringUser?: string;
triggeringUserPrefix?: string;
-}) => queryClient.ensureQueryData({ queryKey:
Common.UseGridServiceGetDagStructureKeyFn({ dagId, depth, includeDownstream,
includeUpstream, limit, offset, orderBy, root, runAfterGt, runAfterGte,
runAfterLt, runAfterLte, runType, state, triggeringUser, triggeringUserPrefix
}), queryFn: () => GridService.getDagStructure({ dagId, depth,
includeDownstream, includeUpstream, limit, offset, orderBy, root, runAfterGt,
runAfterGte, runAfterLt, runAfterLte, runType, state, triggeringUser, triggeri
[...]
+}) => queryClient.ensureQueryData({ queryKey:
Common.UseGridServiceGetDagStructureKeyFn({ dagId, depth, includeDownstream,
includeUpstream, limit, offset, orderBy, root, runAfterGt, runAfterGte,
runAfterLt, runAfterLte, runIdPattern, runIdPrefixPattern, runType, state,
triggeringUser, triggeringUserPrefix }), queryFn: () =>
GridService.getDagStructure({ dagId, depth, includeDownstream, includeUpstream,
limit, offset, orderBy, root, runAfterGt, runAfterGte, runAfterLt, runAfterLte,
runIdP [...]
/**
* Get Grid Runs
* Get info about a run for the grid.
@@ -1958,10 +1962,12 @@ export const ensureUseGridServiceGetDagStructureData =
(queryClient: QueryClient
* @param data.state
* @param data.triggeringUser Case-insensitive substring match (SQL `ILIKE`).
Slower than `triggering_user` on large tables — see "Filtering with pattern
parameters".
* @param data.triggeringUserPrefix Case-sensitive, index-friendly prefix
match. See "Filtering with pattern parameters".
+* @param data.runIdPattern Case-insensitive substring match (SQL `ILIKE`).
Slower than `run_id_prefix_pattern` on large tables — see "Filtering with
pattern parameters".
+* @param data.runIdPrefixPattern Case-sensitive, index-friendly prefix match.
See "Filtering with pattern parameters".
* @returns GridRunsResponse Successful Response
* @throws ApiError
*/
-export const ensureUseGridServiceGetGridRunsData = (queryClient: QueryClient,
{ dagId, limit, offset, orderBy, runAfterGt, runAfterGte, runAfterLt,
runAfterLte, runType, state, triggeringUser, triggeringUserPrefix }: {
+export const ensureUseGridServiceGetGridRunsData = (queryClient: QueryClient,
{ dagId, limit, offset, orderBy, runAfterGt, runAfterGte, runAfterLt,
runAfterLte, runIdPattern, runIdPrefixPattern, runType, state, triggeringUser,
triggeringUserPrefix }: {
dagId: string;
limit?: number;
offset?: number;
@@ -1970,11 +1976,13 @@ export const ensureUseGridServiceGetGridRunsData =
(queryClient: QueryClient, {
runAfterGte?: string;
runAfterLt?: string;
runAfterLte?: string;
+ runIdPattern?: string;
+ runIdPrefixPattern?: string;
runType?: string[];
state?: string[];
triggeringUser?: string;
triggeringUserPrefix?: string;
-}) => queryClient.ensureQueryData({ queryKey:
Common.UseGridServiceGetGridRunsKeyFn({ dagId, limit, offset, orderBy,
runAfterGt, runAfterGte, runAfterLt, runAfterLte, runType, state,
triggeringUser, triggeringUserPrefix }), queryFn: () =>
GridService.getGridRuns({ dagId, limit, offset, orderBy, runAfterGt,
runAfterGte, runAfterLt, runAfterLte, runType, state, triggeringUser,
triggeringUserPrefix }) });
+}) => queryClient.ensureQueryData({ queryKey:
Common.UseGridServiceGetGridRunsKeyFn({ dagId, limit, offset, orderBy,
runAfterGt, runAfterGte, runAfterLt, runAfterLte, runIdPattern,
runIdPrefixPattern, runType, state, triggeringUser, triggeringUserPrefix }),
queryFn: () => GridService.getGridRuns({ dagId, limit, offset, orderBy,
runAfterGt, runAfterGte, runAfterLt, runAfterLte, runIdPattern,
runIdPrefixPattern, runType, state, triggeringUser, triggeringUserPrefix }) });
/**
* Get Grid Ti Summaries Stream
* Stream TI summaries for multiple Dag runs as NDJSON (one JSON line per run).
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 9af03e88a16..e0199a66938 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts
@@ -1921,10 +1921,12 @@ export const prefetchUseStructureServiceStructureData =
(queryClient: QueryClien
* @param data.state
* @param data.triggeringUser Case-insensitive substring match (SQL `ILIKE`).
Slower than `triggering_user` on large tables — see "Filtering with pattern
parameters".
* @param data.triggeringUserPrefix Case-sensitive, index-friendly prefix
match. See "Filtering with pattern parameters".
+* @param data.runIdPattern Case-insensitive substring match (SQL `ILIKE`).
Slower than `run_id_prefix_pattern` on large tables — see "Filtering with
pattern parameters".
+* @param data.runIdPrefixPattern Case-sensitive, index-friendly prefix match.
See "Filtering with pattern parameters".
* @returns GridNodeResponse Successful Response
* @throws ApiError
*/
-export const prefetchUseGridServiceGetDagStructure = (queryClient:
QueryClient, { dagId, depth, includeDownstream, includeUpstream, limit, offset,
orderBy, root, runAfterGt, runAfterGte, runAfterLt, runAfterLte, runType,
state, triggeringUser, triggeringUserPrefix }: {
+export const prefetchUseGridServiceGetDagStructure = (queryClient:
QueryClient, { dagId, depth, includeDownstream, includeUpstream, limit, offset,
orderBy, root, runAfterGt, runAfterGte, runAfterLt, runAfterLte, runIdPattern,
runIdPrefixPattern, runType, state, triggeringUser, triggeringUserPrefix }: {
dagId: string;
depth?: number;
includeDownstream?: boolean;
@@ -1937,11 +1939,13 @@ export const prefetchUseGridServiceGetDagStructure =
(queryClient: QueryClient,
runAfterGte?: string;
runAfterLt?: string;
runAfterLte?: string;
+ runIdPattern?: string;
+ runIdPrefixPattern?: string;
runType?: string[];
state?: string[];
triggeringUser?: string;
triggeringUserPrefix?: string;
-}) => queryClient.prefetchQuery({ queryKey:
Common.UseGridServiceGetDagStructureKeyFn({ dagId, depth, includeDownstream,
includeUpstream, limit, offset, orderBy, root, runAfterGt, runAfterGte,
runAfterLt, runAfterLte, runType, state, triggeringUser, triggeringUserPrefix
}), queryFn: () => GridService.getDagStructure({ dagId, depth,
includeDownstream, includeUpstream, limit, offset, orderBy, root, runAfterGt,
runAfterGte, runAfterLt, runAfterLte, runType, state, triggeringUser,
triggering [...]
+}) => queryClient.prefetchQuery({ queryKey:
Common.UseGridServiceGetDagStructureKeyFn({ dagId, depth, includeDownstream,
includeUpstream, limit, offset, orderBy, root, runAfterGt, runAfterGte,
runAfterLt, runAfterLte, runIdPattern, runIdPrefixPattern, runType, state,
triggeringUser, triggeringUserPrefix }), queryFn: () =>
GridService.getDagStructure({ dagId, depth, includeDownstream, includeUpstream,
limit, offset, orderBy, root, runAfterGt, runAfterGte, runAfterLt, runAfterLte,
runIdPat [...]
/**
* Get Grid Runs
* Get info about a run for the grid.
@@ -1958,10 +1962,12 @@ export const prefetchUseGridServiceGetDagStructure =
(queryClient: QueryClient,
* @param data.state
* @param data.triggeringUser Case-insensitive substring match (SQL `ILIKE`).
Slower than `triggering_user` on large tables — see "Filtering with pattern
parameters".
* @param data.triggeringUserPrefix Case-sensitive, index-friendly prefix
match. See "Filtering with pattern parameters".
+* @param data.runIdPattern Case-insensitive substring match (SQL `ILIKE`).
Slower than `run_id_prefix_pattern` on large tables — see "Filtering with
pattern parameters".
+* @param data.runIdPrefixPattern Case-sensitive, index-friendly prefix match.
See "Filtering with pattern parameters".
* @returns GridRunsResponse Successful Response
* @throws ApiError
*/
-export const prefetchUseGridServiceGetGridRuns = (queryClient: QueryClient, {
dagId, limit, offset, orderBy, runAfterGt, runAfterGte, runAfterLt,
runAfterLte, runType, state, triggeringUser, triggeringUserPrefix }: {
+export const prefetchUseGridServiceGetGridRuns = (queryClient: QueryClient, {
dagId, limit, offset, orderBy, runAfterGt, runAfterGte, runAfterLt,
runAfterLte, runIdPattern, runIdPrefixPattern, runType, state, triggeringUser,
triggeringUserPrefix }: {
dagId: string;
limit?: number;
offset?: number;
@@ -1970,11 +1976,13 @@ export const prefetchUseGridServiceGetGridRuns =
(queryClient: QueryClient, { da
runAfterGte?: string;
runAfterLt?: string;
runAfterLte?: string;
+ runIdPattern?: string;
+ runIdPrefixPattern?: string;
runType?: string[];
state?: string[];
triggeringUser?: string;
triggeringUserPrefix?: string;
-}) => queryClient.prefetchQuery({ queryKey:
Common.UseGridServiceGetGridRunsKeyFn({ dagId, limit, offset, orderBy,
runAfterGt, runAfterGte, runAfterLt, runAfterLte, runType, state,
triggeringUser, triggeringUserPrefix }), queryFn: () =>
GridService.getGridRuns({ dagId, limit, offset, orderBy, runAfterGt,
runAfterGte, runAfterLt, runAfterLte, runType, state, triggeringUser,
triggeringUserPrefix }) });
+}) => queryClient.prefetchQuery({ queryKey:
Common.UseGridServiceGetGridRunsKeyFn({ dagId, limit, offset, orderBy,
runAfterGt, runAfterGte, runAfterLt, runAfterLte, runIdPattern,
runIdPrefixPattern, runType, state, triggeringUser, triggeringUserPrefix }),
queryFn: () => GridService.getGridRuns({ dagId, limit, offset, orderBy,
runAfterGt, runAfterGte, runAfterLt, runAfterLte, runIdPattern,
runIdPrefixPattern, runType, state, triggeringUser, triggeringUserPrefix }) });
/**
* Get Grid Ti Summaries Stream
* Stream TI summaries for multiple Dag runs as NDJSON (one JSON line per run).
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 5d746b71921..cbd1e141960 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts
@@ -1921,10 +1921,12 @@ export const useStructureServiceStructureData = <TData
= Common.StructureService
* @param data.state
* @param data.triggeringUser Case-insensitive substring match (SQL `ILIKE`).
Slower than `triggering_user` on large tables — see "Filtering with pattern
parameters".
* @param data.triggeringUserPrefix Case-sensitive, index-friendly prefix
match. See "Filtering with pattern parameters".
+* @param data.runIdPattern Case-insensitive substring match (SQL `ILIKE`).
Slower than `run_id_prefix_pattern` on large tables — see "Filtering with
pattern parameters".
+* @param data.runIdPrefixPattern Case-sensitive, index-friendly prefix match.
See "Filtering with pattern parameters".
* @returns GridNodeResponse Successful Response
* @throws ApiError
*/
-export const useGridServiceGetDagStructure = <TData =
Common.GridServiceGetDagStructureDefaultResponse, TError = unknown, TQueryKey
extends Array<unknown> = unknown[]>({ dagId, depth, includeDownstream,
includeUpstream, limit, offset, orderBy, root, runAfterGt, runAfterGte,
runAfterLt, runAfterLte, runType, state, triggeringUser, triggeringUserPrefix
}: {
+export const useGridServiceGetDagStructure = <TData =
Common.GridServiceGetDagStructureDefaultResponse, TError = unknown, TQueryKey
extends Array<unknown> = unknown[]>({ dagId, depth, includeDownstream,
includeUpstream, limit, offset, orderBy, root, runAfterGt, runAfterGte,
runAfterLt, runAfterLte, runIdPattern, runIdPrefixPattern, runType, state,
triggeringUser, triggeringUserPrefix }: {
dagId: string;
depth?: number;
includeDownstream?: boolean;
@@ -1937,11 +1939,13 @@ export const useGridServiceGetDagStructure = <TData =
Common.GridServiceGetDagSt
runAfterGte?: string;
runAfterLt?: string;
runAfterLte?: string;
+ runIdPattern?: string;
+ runIdPrefixPattern?: string;
runType?: string[];
state?: string[];
triggeringUser?: string;
triggeringUserPrefix?: string;
-}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>,
"queryKey" | "queryFn">) => useQuery<TData, TError>({ queryKey:
Common.UseGridServiceGetDagStructureKeyFn({ dagId, depth, includeDownstream,
includeUpstream, limit, offset, orderBy, root, runAfterGt, runAfterGte,
runAfterLt, runAfterLte, runType, state, triggeringUser, triggeringUserPrefix
}, queryKey), queryFn: () => GridService.getDagStructure({ dagId, depth,
includeDownstream, includeUpstream, limit, offset, order [...]
+}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>,
"queryKey" | "queryFn">) => useQuery<TData, TError>({ queryKey:
Common.UseGridServiceGetDagStructureKeyFn({ dagId, depth, includeDownstream,
includeUpstream, limit, offset, orderBy, root, runAfterGt, runAfterGte,
runAfterLt, runAfterLte, runIdPattern, runIdPrefixPattern, runType, state,
triggeringUser, triggeringUserPrefix }, queryKey), queryFn: () =>
GridService.getDagStructure({ dagId, depth, includeDownstream, inc [...]
/**
* Get Grid Runs
* Get info about a run for the grid.
@@ -1958,10 +1962,12 @@ export const useGridServiceGetDagStructure = <TData =
Common.GridServiceGetDagSt
* @param data.state
* @param data.triggeringUser Case-insensitive substring match (SQL `ILIKE`).
Slower than `triggering_user` on large tables — see "Filtering with pattern
parameters".
* @param data.triggeringUserPrefix Case-sensitive, index-friendly prefix
match. See "Filtering with pattern parameters".
+* @param data.runIdPattern Case-insensitive substring match (SQL `ILIKE`).
Slower than `run_id_prefix_pattern` on large tables — see "Filtering with
pattern parameters".
+* @param data.runIdPrefixPattern Case-sensitive, index-friendly prefix match.
See "Filtering with pattern parameters".
* @returns GridRunsResponse Successful Response
* @throws ApiError
*/
-export const useGridServiceGetGridRuns = <TData =
Common.GridServiceGetGridRunsDefaultResponse, TError = unknown, TQueryKey
extends Array<unknown> = unknown[]>({ dagId, limit, offset, orderBy,
runAfterGt, runAfterGte, runAfterLt, runAfterLte, runType, state,
triggeringUser, triggeringUserPrefix }: {
+export const useGridServiceGetGridRuns = <TData =
Common.GridServiceGetGridRunsDefaultResponse, TError = unknown, TQueryKey
extends Array<unknown> = unknown[]>({ dagId, limit, offset, orderBy,
runAfterGt, runAfterGte, runAfterLt, runAfterLte, runIdPattern,
runIdPrefixPattern, runType, state, triggeringUser, triggeringUserPrefix }: {
dagId: string;
limit?: number;
offset?: number;
@@ -1970,11 +1976,13 @@ export const useGridServiceGetGridRuns = <TData =
Common.GridServiceGetGridRunsD
runAfterGte?: string;
runAfterLt?: string;
runAfterLte?: string;
+ runIdPattern?: string;
+ runIdPrefixPattern?: string;
runType?: string[];
state?: string[];
triggeringUser?: string;
triggeringUserPrefix?: string;
-}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>,
"queryKey" | "queryFn">) => useQuery<TData, TError>({ queryKey:
Common.UseGridServiceGetGridRunsKeyFn({ dagId, limit, offset, orderBy,
runAfterGt, runAfterGte, runAfterLt, runAfterLte, runType, state,
triggeringUser, triggeringUserPrefix }, queryKey), queryFn: () =>
GridService.getGridRuns({ dagId, limit, offset, orderBy, runAfterGt,
runAfterGte, runAfterLt, runAfterLte, runType, state, triggeringUser,
triggeringUser [...]
+}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>,
"queryKey" | "queryFn">) => useQuery<TData, TError>({ queryKey:
Common.UseGridServiceGetGridRunsKeyFn({ dagId, limit, offset, orderBy,
runAfterGt, runAfterGte, runAfterLt, runAfterLte, runIdPattern,
runIdPrefixPattern, runType, state, triggeringUser, triggeringUserPrefix },
queryKey), queryFn: () => GridService.getGridRuns({ dagId, limit, offset,
orderBy, runAfterGt, runAfterGte, runAfterLt, runAfterLte, runIdPattern [...]
/**
* Get Grid Ti Summaries Stream
* Stream TI summaries for multiple Dag runs as NDJSON (one JSON line per run).
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 08bbc85a0d6..743209b7bac 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts
@@ -1921,10 +1921,12 @@ export const useStructureServiceStructureDataSuspense =
<TData = Common.Structur
* @param data.state
* @param data.triggeringUser Case-insensitive substring match (SQL `ILIKE`).
Slower than `triggering_user` on large tables — see "Filtering with pattern
parameters".
* @param data.triggeringUserPrefix Case-sensitive, index-friendly prefix
match. See "Filtering with pattern parameters".
+* @param data.runIdPattern Case-insensitive substring match (SQL `ILIKE`).
Slower than `run_id_prefix_pattern` on large tables — see "Filtering with
pattern parameters".
+* @param data.runIdPrefixPattern Case-sensitive, index-friendly prefix match.
See "Filtering with pattern parameters".
* @returns GridNodeResponse Successful Response
* @throws ApiError
*/
-export const useGridServiceGetDagStructureSuspense = <TData =
Common.GridServiceGetDagStructureDefaultResponse, TError = unknown, TQueryKey
extends Array<unknown> = unknown[]>({ dagId, depth, includeDownstream,
includeUpstream, limit, offset, orderBy, root, runAfterGt, runAfterGte,
runAfterLt, runAfterLte, runType, state, triggeringUser, triggeringUserPrefix
}: {
+export const useGridServiceGetDagStructureSuspense = <TData =
Common.GridServiceGetDagStructureDefaultResponse, TError = unknown, TQueryKey
extends Array<unknown> = unknown[]>({ dagId, depth, includeDownstream,
includeUpstream, limit, offset, orderBy, root, runAfterGt, runAfterGte,
runAfterLt, runAfterLte, runIdPattern, runIdPrefixPattern, runType, state,
triggeringUser, triggeringUserPrefix }: {
dagId: string;
depth?: number;
includeDownstream?: boolean;
@@ -1937,11 +1939,13 @@ export const useGridServiceGetDagStructureSuspense =
<TData = Common.GridService
runAfterGte?: string;
runAfterLt?: string;
runAfterLte?: string;
+ runIdPattern?: string;
+ runIdPrefixPattern?: string;
runType?: string[];
state?: string[];
triggeringUser?: string;
triggeringUserPrefix?: string;
-}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>,
"queryKey" | "queryFn">) => useSuspenseQuery<TData, TError>({ queryKey:
Common.UseGridServiceGetDagStructureKeyFn({ dagId, depth, includeDownstream,
includeUpstream, limit, offset, orderBy, root, runAfterGt, runAfterGte,
runAfterLt, runAfterLte, runType, state, triggeringUser, triggeringUserPrefix
}, queryKey), queryFn: () => GridService.getDagStructure({ dagId, depth,
includeDownstream, includeUpstream, limit, offse [...]
+}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>,
"queryKey" | "queryFn">) => useSuspenseQuery<TData, TError>({ queryKey:
Common.UseGridServiceGetDagStructureKeyFn({ dagId, depth, includeDownstream,
includeUpstream, limit, offset, orderBy, root, runAfterGt, runAfterGte,
runAfterLt, runAfterLte, runIdPattern, runIdPrefixPattern, runType, state,
triggeringUser, triggeringUserPrefix }, queryKey), queryFn: () =>
GridService.getDagStructure({ dagId, depth, includeDownstr [...]
/**
* Get Grid Runs
* Get info about a run for the grid.
@@ -1958,10 +1962,12 @@ export const useGridServiceGetDagStructureSuspense =
<TData = Common.GridService
* @param data.state
* @param data.triggeringUser Case-insensitive substring match (SQL `ILIKE`).
Slower than `triggering_user` on large tables — see "Filtering with pattern
parameters".
* @param data.triggeringUserPrefix Case-sensitive, index-friendly prefix
match. See "Filtering with pattern parameters".
+* @param data.runIdPattern Case-insensitive substring match (SQL `ILIKE`).
Slower than `run_id_prefix_pattern` on large tables — see "Filtering with
pattern parameters".
+* @param data.runIdPrefixPattern Case-sensitive, index-friendly prefix match.
See "Filtering with pattern parameters".
* @returns GridRunsResponse Successful Response
* @throws ApiError
*/
-export const useGridServiceGetGridRunsSuspense = <TData =
Common.GridServiceGetGridRunsDefaultResponse, TError = unknown, TQueryKey
extends Array<unknown> = unknown[]>({ dagId, limit, offset, orderBy,
runAfterGt, runAfterGte, runAfterLt, runAfterLte, runType, state,
triggeringUser, triggeringUserPrefix }: {
+export const useGridServiceGetGridRunsSuspense = <TData =
Common.GridServiceGetGridRunsDefaultResponse, TError = unknown, TQueryKey
extends Array<unknown> = unknown[]>({ dagId, limit, offset, orderBy,
runAfterGt, runAfterGte, runAfterLt, runAfterLte, runIdPattern,
runIdPrefixPattern, runType, state, triggeringUser, triggeringUserPrefix }: {
dagId: string;
limit?: number;
offset?: number;
@@ -1970,11 +1976,13 @@ export const useGridServiceGetGridRunsSuspense = <TData
= Common.GridServiceGetG
runAfterGte?: string;
runAfterLt?: string;
runAfterLte?: string;
+ runIdPattern?: string;
+ runIdPrefixPattern?: string;
runType?: string[];
state?: string[];
triggeringUser?: string;
triggeringUserPrefix?: string;
-}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>,
"queryKey" | "queryFn">) => useSuspenseQuery<TData, TError>({ queryKey:
Common.UseGridServiceGetGridRunsKeyFn({ dagId, limit, offset, orderBy,
runAfterGt, runAfterGte, runAfterLt, runAfterLte, runType, state,
triggeringUser, triggeringUserPrefix }, queryKey), queryFn: () =>
GridService.getGridRuns({ dagId, limit, offset, orderBy, runAfterGt,
runAfterGte, runAfterLt, runAfterLte, runType, state, triggeringUser, trigge
[...]
+}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>,
"queryKey" | "queryFn">) => useSuspenseQuery<TData, TError>({ queryKey:
Common.UseGridServiceGetGridRunsKeyFn({ dagId, limit, offset, orderBy,
runAfterGt, runAfterGte, runAfterLt, runAfterLte, runIdPattern,
runIdPrefixPattern, runType, state, triggeringUser, triggeringUserPrefix },
queryKey), queryFn: () => GridService.getGridRuns({ dagId, limit, offset,
orderBy, runAfterGt, runAfterGte, runAfterLt, runAfterLte, runI [...]
/**
* Get Grid Ti Summaries Stream
* Stream TI summaries for multiple Dag runs as NDJSON (one JSON line per run).
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 c1ed9997d45..14a7cb408ce 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
@@ -4919,6 +4919,8 @@ export class GridService {
* @param data.state
* @param data.triggeringUser Case-insensitive substring match (SQL
`ILIKE`). Slower than `triggering_user` on large tables — see "Filtering with
pattern parameters".
* @param data.triggeringUserPrefix Case-sensitive, index-friendly prefix
match. See "Filtering with pattern parameters".
+ * @param data.runIdPattern Case-insensitive substring match (SQL
`ILIKE`). Slower than `run_id_prefix_pattern` on large tables — see "Filtering
with pattern parameters".
+ * @param data.runIdPrefixPattern Case-sensitive, index-friendly prefix
match. See "Filtering with pattern parameters".
* @returns GridNodeResponse Successful Response
* @throws ApiError
*/
@@ -4944,7 +4946,9 @@ export class GridService {
run_type: data.runType,
state: data.state,
triggering_user: data.triggeringUser,
- triggering_user_prefix: data.triggeringUserPrefix
+ triggering_user_prefix: data.triggeringUserPrefix,
+ run_id_pattern: data.runIdPattern,
+ run_id_prefix_pattern: data.runIdPrefixPattern
},
errors: {
400: 'Bad Request',
@@ -4970,6 +4974,8 @@ export class GridService {
* @param data.state
* @param data.triggeringUser Case-insensitive substring match (SQL
`ILIKE`). Slower than `triggering_user` on large tables — see "Filtering with
pattern parameters".
* @param data.triggeringUserPrefix Case-sensitive, index-friendly prefix
match. See "Filtering with pattern parameters".
+ * @param data.runIdPattern Case-insensitive substring match (SQL
`ILIKE`). Slower than `run_id_prefix_pattern` on large tables — see "Filtering
with pattern parameters".
+ * @param data.runIdPrefixPattern Case-sensitive, index-friendly prefix
match. See "Filtering with pattern parameters".
* @returns GridRunsResponse Successful Response
* @throws ApiError
*/
@@ -4991,7 +4997,9 @@ export class GridService {
run_type: data.runType,
state: data.state,
triggering_user: data.triggeringUser,
- triggering_user_prefix: data.triggeringUserPrefix
+ triggering_user_prefix: data.triggeringUserPrefix,
+ run_id_pattern: data.runIdPattern,
+ run_id_prefix_pattern: data.runIdPrefixPattern
},
errors: {
400: 'Bad Request',
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 3af0c45ee13..7d8551c8cd7 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
@@ -4630,6 +4630,14 @@ export type GetDagStructureData = {
runAfterGte?: string | null;
runAfterLt?: string | null;
runAfterLte?: string | null;
+ /**
+ * Case-insensitive substring match (SQL `ILIKE`). Slower than
`run_id_prefix_pattern` on large tables — see "Filtering with pattern
parameters".
+ */
+ runIdPattern?: string | null;
+ /**
+ * Case-sensitive, index-friendly prefix match. See "Filtering with
pattern parameters".
+ */
+ runIdPrefixPattern?: string | null;
runType?: Array<(string)>;
state?: Array<(string)>;
/**
@@ -4656,6 +4664,14 @@ export type GetGridRunsData = {
runAfterGte?: string | null;
runAfterLt?: string | null;
runAfterLte?: string | null;
+ /**
+ * Case-insensitive substring match (SQL `ILIKE`). Slower than
`run_id_prefix_pattern` on large tables — see "Filtering with pattern
parameters".
+ */
+ runIdPattern?: string | null;
+ /**
+ * Case-sensitive, index-friendly prefix match. See "Filtering with
pattern parameters".
+ */
+ runIdPrefixPattern?: string | null;
runType?: Array<(string)>;
state?: Array<(string)>;
/**
diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/DetailsLayout.tsx
b/airflow-core/src/airflow/ui/src/layouts/Details/DetailsLayout.tsx
index 95ac32ffc4d..979bfe22485 100644
--- a/airflow-core/src/airflow/ui/src/layouts/Details/DetailsLayout.tsx
+++ b/airflow-core/src/airflow/ui/src/layouts/Details/DetailsLayout.tsx
@@ -134,6 +134,7 @@ export const DetailsLayout = ({ children, error, isLoading,
outletContext, tabs
const runAfterLte = searchParams.get(SearchParamsKeys.RUN_AFTER_LTE) ??
undefined;
const runTypeFilter = (searchParams.get(SearchParamsKeys.RUN_TYPE) as
DagRunType | null) ?? undefined;
const triggeringUserFilter =
searchParams.get(SearchParamsKeys.TRIGGERING_USER_NAME_PATTERN) ?? undefined;
+ const runIdPatternFilter = searchParams.get(SearchParamsKeys.RUN_ID_PATTERN)
?? undefined;
const dagRunStateFilter = (searchParams.get(SearchParamsKeys.STATE) as
DagRunState | null) ?? undefined;
// --- Setters that write back to URL ---
@@ -164,6 +165,7 @@ export const DetailsLayout = ({ children, error, isLoading,
outletContext, tabs
const { data: initialGridRuns } = useGridRuns({
dagRunState: dagRunStateFilter,
limit,
+ runIdPattern: runIdPatternFilter,
runType: runTypeFilter,
triggeringUser: triggeringUserFilter,
});
@@ -289,6 +291,7 @@ export const DetailsLayout = ({ children, error, isLoading,
outletContext, tabs
onJumpToLatest={handleJumpToLatest}
runAfterGte={runAfterGte}
runAfterLte={runAfterLte}
+ runIdPattern={runIdPatternFilter}
runType={runTypeFilter}
setOffset={setOffset}
sharedScrollContainerRef={sharedGridGanttScrollRef}
@@ -302,6 +305,7 @@ export const DetailsLayout = ({ children, error, isLoading,
outletContext, tabs
offset={offset}
runAfterGte={runAfterGte}
runAfterLte={runAfterLte}
+ runIdPattern={runIdPatternFilter}
runType={runTypeFilter}
sharedScrollContainerRef={sharedGridGanttScrollRef}
triggeringUser={triggeringUserFilter}
@@ -325,6 +329,7 @@ export const DetailsLayout = ({ children, error, isLoading,
outletContext, tabs
onJumpToLatest={handleJumpToLatest}
runAfterGte={runAfterGte}
runAfterLte={runAfterLte}
+ runIdPattern={runIdPatternFilter}
runType={runTypeFilter}
setOffset={setOffset}
showVersionIndicatorMode={showVersionIndicatorMode}
diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/Gantt.tsx
b/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/Gantt.tsx
index 6383d57623a..ad7b3e68cb2 100644
--- a/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/Gantt.tsx
+++ b/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/Gantt.tsx
@@ -48,6 +48,7 @@ type Props = {
readonly offset?: number;
readonly runAfterGte?: string | undefined;
readonly runAfterLte?: string | undefined;
+ readonly runIdPattern?: string | undefined;
readonly runType?: DagRunType | undefined;
readonly sharedScrollContainerRef?: RefObject<HTMLDivElement | null>;
readonly triggeringUser?: string | undefined;
@@ -59,6 +60,7 @@ export const Gantt = ({
offset,
runAfterGte,
runAfterLte,
+ runIdPattern,
runType,
sharedScrollContainerRef,
triggeringUser,
@@ -85,6 +87,7 @@ export const Gantt = ({
offset,
runAfterGte,
runAfterLte,
+ runIdPattern,
runType,
triggeringUser,
});
@@ -95,6 +98,7 @@ export const Gantt = ({
includeUpstream,
limit,
root: filterRoot,
+ runIdPattern,
runType,
triggeringUser,
});
diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/Grid.tsx
b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/Grid.tsx
index a1cb9d36e99..ff122b47b2d 100644
--- a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/Grid.tsx
+++ b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/Grid.tsx
@@ -53,6 +53,7 @@ type Props = {
readonly onJumpToLatest: () => void;
readonly runAfterGte?: string;
readonly runAfterLte?: string;
+ readonly runIdPattern?: string | undefined;
readonly runType?: DagRunType | undefined;
readonly setOffset: (value: number) => void;
readonly sharedScrollContainerRef?: RefObject<HTMLDivElement | null>;
@@ -70,6 +71,7 @@ export const Grid = ({
onJumpToLatest,
runAfterGte,
runAfterLte,
+ runIdPattern,
runType,
setOffset,
sharedScrollContainerRef,
@@ -99,6 +101,7 @@ export const Grid = ({
offset,
runAfterGte,
runAfterLte,
+ runIdPattern,
runType,
triggeringUser,
});
@@ -121,6 +124,7 @@ export const Grid = ({
includeUpstream,
limit,
root: filterRoot,
+ runIdPattern,
runType,
triggeringUser,
});
diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/GridFilters.tsx
b/airflow-core/src/airflow/ui/src/layouts/Details/GridFilters.tsx
index ee30042ef70..ab7a281dd0d 100644
--- a/airflow-core/src/airflow/ui/src/layouts/Details/GridFilters.tsx
+++ b/airflow-core/src/airflow/ui/src/layouts/Details/GridFilters.tsx
@@ -21,6 +21,7 @@ import { SearchParamsKeys } from "src/constants/searchParams";
import { useFiltersHandler, type FilterableSearchParamsKeys } from "src/utils";
const searchParamKeys: Array<FilterableSearchParamsKeys> = [
+ SearchParamsKeys.RUN_ID_PATTERN,
SearchParamsKeys.STATE,
SearchParamsKeys.RUN_TYPE,
SearchParamsKeys.TRIGGERING_USER_NAME_PATTERN,
diff --git a/airflow-core/src/airflow/ui/src/queries/useGridRuns.ts
b/airflow-core/src/airflow/ui/src/queries/useGridRuns.ts
index f487de7a03f..fe6340f08ad 100644
--- a/airflow-core/src/airflow/ui/src/queries/useGridRuns.ts
+++ b/airflow-core/src/airflow/ui/src/queries/useGridRuns.ts
@@ -20,6 +20,8 @@ import { useParams } from "react-router-dom";
import { useGridServiceGetGridRuns } from "openapi/queries";
import type { DagRunState, DagRunType } from "openapi/requests/types.gen";
+import { SearchParamsKeys } from "src/constants/searchParams";
+import { useAdvancedSearchArg } from "src/hooks/useAdvancedSearch";
import { isStatePending, useAutoRefresh } from "src/utils";
export const useGridRuns = ({
@@ -28,6 +30,7 @@ export const useGridRuns = ({
offset,
runAfterGte,
runAfterLte,
+ runIdPattern,
runType,
triggeringUser,
}: {
@@ -36,6 +39,7 @@ export const useGridRuns = ({
offset?: number;
runAfterGte?: string;
runAfterLte?: string;
+ runIdPattern?: string | undefined;
runType?: DagRunType | undefined;
triggeringUser?: string | undefined;
}) => {
@@ -43,6 +47,15 @@ export const useGridRuns = ({
const refetchInterval = useAutoRefresh({ dagId });
+ // Advanced-search toggle picks between the substring ``runIdPattern`` and
the
+ // index-friendly ``runIdPrefixPattern`` variants of the Run ID filter.
+ const runIdPatternArg = useAdvancedSearchArg({
+ patternApiKey: "runIdPattern",
+ prefixApiKey: "runIdPrefixPattern",
+ storageKey: SearchParamsKeys.RUN_ID_PATTERN,
+ value: runIdPattern,
+ });
+
const { data: GridRuns, ...rest } = useGridServiceGetGridRuns(
{
dagId,
@@ -51,6 +64,7 @@ export const useGridRuns = ({
orderBy: ["-run_after"],
runAfterGte: runAfterGte ?? undefined,
runAfterLte: runAfterLte ?? undefined,
+ ...runIdPatternArg,
runType: runType ? [runType] : undefined,
state: dagRunState ? [dagRunState] : undefined,
triggeringUser: triggeringUser ?? undefined,
diff --git a/airflow-core/src/airflow/ui/src/queries/useGridStructure.ts
b/airflow-core/src/airflow/ui/src/queries/useGridStructure.ts
index bbae7d789da..702145b2bf5 100644
--- a/airflow-core/src/airflow/ui/src/queries/useGridStructure.ts
+++ b/airflow-core/src/airflow/ui/src/queries/useGridStructure.ts
@@ -20,6 +20,8 @@ import { useParams } from "react-router-dom";
import { useGridServiceGetDagStructure } from "openapi/queries";
import type { DagRunState, DagRunType } from "openapi/requests/types.gen";
+import { SearchParamsKeys } from "src/constants/searchParams";
+import { useAdvancedSearchArg } from "src/hooks/useAdvancedSearch";
import { useAutoRefresh } from "src/utils";
export const useGridStructure = ({
@@ -30,6 +32,7 @@ export const useGridStructure = ({
includeUpstream,
limit,
root,
+ runIdPattern,
runType,
triggeringUser,
}: {
@@ -40,12 +43,22 @@ export const useGridStructure = ({
includeUpstream?: boolean;
limit?: number;
root?: string;
+ runIdPattern?: string | undefined;
runType?: DagRunType | undefined;
triggeringUser?: string | undefined;
}) => {
const { dagId = "" } = useParams();
const refetchInterval = useAutoRefresh({ dagId });
+ // Advanced-search toggle picks between the substring ``runIdPattern`` and
the
+ // index-friendly ``runIdPrefixPattern`` variants of the Run ID filter.
+ const runIdPatternArg = useAdvancedSearchArg({
+ patternApiKey: "runIdPattern",
+ prefixApiKey: "runIdPrefixPattern",
+ storageKey: SearchParamsKeys.RUN_ID_PATTERN,
+ value: runIdPattern,
+ });
+
// This is necessary for keepPreviousData
const { data: dagStructure, ...rest } = useGridServiceGetDagStructure(
{
@@ -56,6 +69,7 @@ export const useGridStructure = ({
limit,
orderBy: ["-run_after"],
root,
+ ...runIdPatternArg,
runType: runType ? [runType] : undefined,
state: dagRunState ? [dagRunState] : undefined,
triggeringUser: triggeringUser ?? undefined,
diff --git
a/airflow-core/tests/unit/api_fastapi/core_api/routes/ui/test_grid.py
b/airflow-core/tests/unit/api_fastapi/core_api/routes/ui/test_grid.py
index 17b485b9ebf..ad4450903df 100644
--- a/airflow-core/tests/unit/api_fastapi/core_api/routes/ui/test_grid.py
+++ b/airflow-core/tests/unit/api_fastapi/core_api/routes/ui/test_grid.py
@@ -720,6 +720,39 @@ class TestGetGridDataEndpoint:
assert response.status_code == 200
assert _strip_dag_version_ids(response.json()) == [GRID_RUN_2]
+ @pytest.mark.parametrize(
+ ("endpoint", "run_id_pattern", "expected"),
+ [
+ ("runs", "run_1", [GRID_RUN_1]),
+ ("runs", "run_2", [GRID_RUN_2]),
+ ("runs", "RUN_1", [GRID_RUN_1]), # ILIKE substring search is
case-insensitive
+ ("runs", "nonexistent", []),
+ ("structure", "run_1", GRID_NODES),
+ ],
+ )
+ def test_filter_by_run_id_pattern(self, session, test_client, endpoint,
run_id_pattern, expected):
+ session.commit()
+ response =
test_client.get(f"/grid/{endpoint}/{DAG_ID}?run_id_pattern={run_id_pattern}")
+ assert response.status_code == 200
+ assert _strip_dag_version_ids(response.json()) == expected
+
+ @pytest.mark.parametrize(
+ ("endpoint", "run_id_prefix_pattern", "expected"),
+ [
+ ("runs", "run_1", [GRID_RUN_1]),
+ ("runs", "run_2", [GRID_RUN_2]),
+ ("runs", "nonexistent", []),
+ ("structure", "run_1", GRID_NODES),
+ ],
+ )
+ def test_filter_by_run_id_prefix_pattern(
+ self, session, test_client, endpoint, run_id_prefix_pattern, expected
+ ):
+ session.commit()
+ response =
test_client.get(f"/grid/{endpoint}/{DAG_ID}?run_id_prefix_pattern={run_id_prefix_pattern}")
+ assert response.status_code == 200
+ assert _strip_dag_version_ids(response.json()) == expected
+
@pytest.mark.parametrize(
("endpoint", "state", "expected"),
[