This is an automated email from the ASF dual-hosted git repository.
bbovenzi 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 dc2ee911151 UI: Add duration filter to DAG Backfills tab (#74202)
dc2ee911151 is described below
commit dc2ee91115169502a1dc1953ff9c0d7b277fabcd
Author: Sakshi Yadav <[email protected]>
AuthorDate: Wed Oct 7 00:20:04 2026 +0530
UI: Add duration filter to DAG Backfills tab (#74202)
* core file changes
Signed-off-by: ydsakshi <[email protected]>
* generated files
* Static checks failure - resolved
---------
Signed-off-by: ydsakshi <[email protected]>
---
.../api_fastapi/core_api/openapi/_private_ui.yaml | 32 ++++++++++++++++
.../api_fastapi/core_api/routes/ui/backfills.py | 3 ++
airflow-core/src/airflow/models/backfill.py | 43 ++++++++++++++++++++--
.../src/airflow/ui/openapi-gen/queries/common.ts | 8 +++-
.../ui/openapi-gen/queries/ensureQueryData.ts | 12 +++++-
.../src/airflow/ui/openapi-gen/queries/prefetch.ts | 12 +++++-
.../src/airflow/ui/openapi-gen/queries/queries.ts | 12 +++++-
.../src/airflow/ui/openapi-gen/queries/suspense.ts | 12 +++++-
.../ui/openapi-gen/requests/services.gen.ts | 8 ++++
.../airflow/ui/openapi-gen/requests/types.gen.ts | 4 ++
.../ui/src/pages/Dag/Backfills/Backfills.tsx | 6 +++
.../src/pages/Dag/Backfills/BackfillsFilters.tsx | 2 +
12 files changed, 141 insertions(+), 13 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 de12f997600..f28adbd241c 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
@@ -1634,6 +1634,38 @@ paths:
- type: integer
- type: 'null'
title: Max Active Runs Lt
+ - name: duration_gte
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: number
+ - type: 'null'
+ title: Duration Gte
+ - name: duration_gt
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: number
+ - type: 'null'
+ title: Duration Gt
+ - name: duration_lte
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: number
+ - type: 'null'
+ title: Duration Lte
+ - name: duration_lt
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: number
+ - type: 'null'
+ title: Duration Lt
- name: reprocess_behavior
in: query
required: false
diff --git
a/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/backfills.py
b/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/backfills.py
index ff8782e9316..eda81be7115 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/backfills.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/backfills.py
@@ -32,6 +32,7 @@ from airflow.api_fastapi.common.parameters import (
SortParam,
datetime_range_filter_factory,
filter_param_factory,
+ float_range_filter_factory,
int_range_filter_factory,
)
from airflow.api_fastapi.common.router import AirflowRouter
@@ -60,6 +61,7 @@ def list_backfills_ui(
created_at: Annotated[RangeFilter,
Depends(datetime_range_filter_factory("created_at", Backfill))],
completed_at: Annotated[RangeFilter,
Depends(datetime_range_filter_factory("completed_at", Backfill))],
max_active_runs: Annotated[RangeFilter,
Depends(int_range_filter_factory("max_active_runs", Backfill))],
+ duration_range: Annotated[RangeFilter,
Depends(float_range_filter_factory("duration", Backfill))],
reprocess_behavior: Annotated[
FilterParam, Depends(filter_param_factory(Backfill.reprocess_behavior,
ReprocessBehavior | None))
],
@@ -86,6 +88,7 @@ def list_backfills_ui(
created_at,
completed_at,
max_active_runs,
+ duration_range,
reprocess_behavior,
],
order_by=order_by,
diff --git a/airflow-core/src/airflow/models/backfill.py
b/airflow-core/src/airflow/models/backfill.py
index 5153c5c4c6c..8e74f3e7fab 100644
--- a/airflow-core/src/airflow/models/backfill.py
+++ b/airflow-core/src/airflow/models/backfill.py
@@ -26,7 +26,7 @@ from __future__ import annotations
from collections.abc import Iterable
from datetime import datetime
from enum import Enum
-from typing import TYPE_CHECKING
+from typing import TYPE_CHECKING, Any
import sqlalchemy as sa
import structlog
@@ -37,18 +37,26 @@ from sqlalchemy import (
Integer,
String,
UniqueConstraint,
+ case,
delete,
func,
select,
+ text,
)
from sqlalchemy.exc import IntegrityError, OperationalError
+from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import Mapped, mapped_column, relationship, validates
from airflow._shared.timezones import timezone
from airflow.exceptions import AirflowException, DagNotFound,
DagRunTypeNotAllowed
from airflow.models.base import Base, StringID
-from airflow.utils.session import create_session
-from airflow.utils.sqlalchemy import UtcDateTime, is_lock_not_available_error,
with_row_locks
+from airflow.utils.db import get_dialect_name
+from airflow.utils.session import NEW_SESSION, create_session, provide_session
+from airflow.utils.sqlalchemy import (
+ UtcDateTime,
+ is_lock_not_available_error,
+ with_row_locks,
+)
from airflow.utils.state import DagRunState
from airflow.utils.types import DagRunTriggeredByType, DagRunType
@@ -203,6 +211,35 @@ class Backfill(Base):
def __repr__(self):
return f"Backfill({self.dag_id=}, {self.from_date=}, {self.to_date=})"
+ @hybrid_property
+ def duration(self) -> float | None:
+ if self.completed_at and self.created_at:
+ return (self.completed_at - self.created_at).total_seconds()
+ return None
+
+ @duration.expression # type: ignore[no-redef]
+ def duration(cls) -> Any:
+ @provide_session
+ def _get_dialect(*, session: Session = NEW_SESSION) -> str:
+ return get_dialect_name(session=session)
+
+ dialect_name = _get_dialect()
+
+ duration_expr: Any
+ if dialect_name == "mysql":
+ duration_expr = func.timestampdiff(text("SECOND"), cls.created_at,
cls.completed_at)
+ elif dialect_name == "sqlite":
+ duration_expr = (func.julianday(cls.completed_at) -
func.julianday(cls.created_at)) * 86400
+ else:
+ duration_expr = func.extract("epoch", cls.completed_at -
cls.created_at) # type: ignore[operator, arg-type]
+
+ when_condition = (
+ cls.completed_at.isnot(None) & cls.created_at.isnot(None), #
type: ignore[union-attr, attr-defined]
+ duration_expr,
+ )
+
+ return case(when_condition, else_=None)
+
class BackfillDagRunExceptionReason(str, Enum):
"""
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 bbdde559034..4eb17d203b9 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts
@@ -139,7 +139,7 @@ export const UseBackfillServiceListBackfillDagRunsKeyFn =
({ backfillId, limit,
export type BackfillServiceListBackfillsUiDefaultResponse =
Awaited<ReturnType<typeof BackfillService.listBackfillsUi>>;
export type BackfillServiceListBackfillsUiQueryResult<TData =
BackfillServiceListBackfillsUiDefaultResponse, TError = unknown> =
UseQueryResult<TData, TError>;
export const useBackfillServiceListBackfillsUiKey =
"BackfillServiceListBackfillsUi";
-export const UseBackfillServiceListBackfillsUiKeyFn = ({ active,
completedAtGt, completedAtGte, completedAtLt, completedAtLte, createdAtGt,
createdAtGte, createdAtLt, createdAtLte, dagId, fromDateGt, fromDateGte,
fromDateLt, fromDateLte, limit, maxActiveRunsGt, maxActiveRunsGte,
maxActiveRunsLt, maxActiveRunsLte, offset, orderBy, reprocessBehavior,
toDateGt, toDateGte, toDateLt, toDateLte }: {
+export const UseBackfillServiceListBackfillsUiKeyFn = ({ active,
completedAtGt, completedAtGte, completedAtLt, completedAtLte, createdAtGt,
createdAtGte, createdAtLt, createdAtLte, dagId, durationGt, durationGte,
durationLt, durationLte, fromDateGt, fromDateGte, fromDateLt, fromDateLte,
limit, maxActiveRunsGt, maxActiveRunsGte, maxActiveRunsLt, maxActiveRunsLte,
offset, orderBy, reprocessBehavior, toDateGt, toDateGte, toDateLt, toDateLte }:
{
active?: boolean;
completedAtGt?: string;
completedAtGte?: string;
@@ -150,6 +150,10 @@ export const UseBackfillServiceListBackfillsUiKeyFn = ({
active, completedAtGt,
createdAtLt?: string;
createdAtLte?: string;
dagId?: string;
+ durationGt?: number;
+ durationGte?: number;
+ durationLt?: number;
+ durationLte?: number;
fromDateGt?: string;
fromDateGte?: string;
fromDateLt?: string;
@@ -166,7 +170,7 @@ export const UseBackfillServiceListBackfillsUiKeyFn = ({
active, completedAtGt,
toDateGte?: string;
toDateLt?: string;
toDateLte?: string;
-} = {}, queryKey?: Array<unknown>) => [useBackfillServiceListBackfillsUiKey,
...(queryKey ?? [{ active, completedAtGt, completedAtGte, completedAtLt,
completedAtLte, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId,
fromDateGt, fromDateGte, fromDateLt, fromDateLte, limit, maxActiveRunsGt,
maxActiveRunsGte, maxActiveRunsLt, maxActiveRunsLte, offset, orderBy,
reprocessBehavior, toDateGt, toDateGte, toDateLt, toDateLte }])];
+} = {}, queryKey?: Array<unknown>) => [useBackfillServiceListBackfillsUiKey,
...(queryKey ?? [{ active, completedAtGt, completedAtGte, completedAtLt,
completedAtLte, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId,
durationGt, durationGte, durationLt, durationLte, fromDateGt, fromDateGte,
fromDateLt, fromDateLte, limit, maxActiveRunsGt, maxActiveRunsGte,
maxActiveRunsLt, maxActiveRunsLte, offset, orderBy, reprocessBehavior,
toDateGt, toDateGte, toDateLt, toDateLte }])];
export type ConnectionServiceGetConnectionDefaultResponse =
Awaited<ReturnType<typeof ConnectionService.getConnection>>;
export type ConnectionServiceGetConnectionQueryResult<TData =
ConnectionServiceGetConnectionDefaultResponse, TError = unknown> =
UseQueryResult<TData, TError>;
export const useConnectionServiceGetConnectionKey =
"ConnectionServiceGetConnection";
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 35783c93ac1..508e8a98620 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts
@@ -279,6 +279,10 @@ export const
ensureUseBackfillServiceListBackfillDagRunsData = (queryClient: Que
* @param data.maxActiveRunsGt
* @param data.maxActiveRunsLte
* @param data.maxActiveRunsLt
+* @param data.durationGte
+* @param data.durationGt
+* @param data.durationLte
+* @param data.durationLt
* @param data.reprocessBehavior
* @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id`
* @param data.dagId
@@ -286,7 +290,7 @@ export const
ensureUseBackfillServiceListBackfillDagRunsData = (queryClient: Que
* @returns BackfillCollectionResponse Successful Response
* @throws ApiError
*/
-export const ensureUseBackfillServiceListBackfillsUiData = (queryClient:
QueryClient, { active, completedAtGt, completedAtGte, completedAtLt,
completedAtLte, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId,
fromDateGt, fromDateGte, fromDateLt, fromDateLte, limit, maxActiveRunsGt,
maxActiveRunsGte, maxActiveRunsLt, maxActiveRunsLte, offset, orderBy,
reprocessBehavior, toDateGt, toDateGte, toDateLt, toDateLte }: {
+export const ensureUseBackfillServiceListBackfillsUiData = (queryClient:
QueryClient, { active, completedAtGt, completedAtGte, completedAtLt,
completedAtLte, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId,
durationGt, durationGte, durationLt, durationLte, fromDateGt, fromDateGte,
fromDateLt, fromDateLte, limit, maxActiveRunsGt, maxActiveRunsGte,
maxActiveRunsLt, maxActiveRunsLte, offset, orderBy, reprocessBehavior,
toDateGt, toDateGte, toDateLt, toDateLte }: {
active?: boolean;
completedAtGt?: string;
completedAtGte?: string;
@@ -297,6 +301,10 @@ export const ensureUseBackfillServiceListBackfillsUiData =
(queryClient: QueryCl
createdAtLt?: string;
createdAtLte?: string;
dagId?: string;
+ durationGt?: number;
+ durationGte?: number;
+ durationLt?: number;
+ durationLte?: number;
fromDateGt?: string;
fromDateGte?: string;
fromDateLt?: string;
@@ -313,7 +321,7 @@ export const ensureUseBackfillServiceListBackfillsUiData =
(queryClient: QueryCl
toDateGte?: string;
toDateLt?: string;
toDateLte?: string;
-} = {}) => queryClient.ensureQueryData({ queryKey:
Common.UseBackfillServiceListBackfillsUiKeyFn({ active, completedAtGt,
completedAtGte, completedAtLt, completedAtLte, createdAtGt, createdAtGte,
createdAtLt, createdAtLte, dagId, fromDateGt, fromDateGte, fromDateLt,
fromDateLte, limit, maxActiveRunsGt, maxActiveRunsGte, maxActiveRunsLt,
maxActiveRunsLte, offset, orderBy, reprocessBehavior, toDateGt, toDateGte,
toDateLt, toDateLte }), queryFn: () => BackfillService.listBackfillsUi({ activ
[...]
+} = {}) => queryClient.ensureQueryData({ queryKey:
Common.UseBackfillServiceListBackfillsUiKeyFn({ active, completedAtGt,
completedAtGte, completedAtLt, completedAtLte, createdAtGt, createdAtGte,
createdAtLt, createdAtLte, dagId, durationGt, durationGte, durationLt,
durationLte, fromDateGt, fromDateGte, fromDateLt, fromDateLte, limit,
maxActiveRunsGt, maxActiveRunsGte, maxActiveRunsLt, maxActiveRunsLte, offset,
orderBy, reprocessBehavior, toDateGt, toDateGte, toDateLt, toDateLte }), quer
[...]
/**
* Get Connection
* Get a connection entry.
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 451c62087c6..5c48648cda9 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts
@@ -279,6 +279,10 @@ export const prefetchUseBackfillServiceListBackfillDagRuns
= (queryClient: Query
* @param data.maxActiveRunsGt
* @param data.maxActiveRunsLte
* @param data.maxActiveRunsLt
+* @param data.durationGte
+* @param data.durationGt
+* @param data.durationLte
+* @param data.durationLt
* @param data.reprocessBehavior
* @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id`
* @param data.dagId
@@ -286,7 +290,7 @@ export const prefetchUseBackfillServiceListBackfillDagRuns
= (queryClient: Query
* @returns BackfillCollectionResponse Successful Response
* @throws ApiError
*/
-export const prefetchUseBackfillServiceListBackfillsUi = (queryClient:
QueryClient, { active, completedAtGt, completedAtGte, completedAtLt,
completedAtLte, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId,
fromDateGt, fromDateGte, fromDateLt, fromDateLte, limit, maxActiveRunsGt,
maxActiveRunsGte, maxActiveRunsLt, maxActiveRunsLte, offset, orderBy,
reprocessBehavior, toDateGt, toDateGte, toDateLt, toDateLte }: {
+export const prefetchUseBackfillServiceListBackfillsUi = (queryClient:
QueryClient, { active, completedAtGt, completedAtGte, completedAtLt,
completedAtLte, createdAtGt, createdAtGte, createdAtLt, createdAtLte, dagId,
durationGt, durationGte, durationLt, durationLte, fromDateGt, fromDateGte,
fromDateLt, fromDateLte, limit, maxActiveRunsGt, maxActiveRunsGte,
maxActiveRunsLt, maxActiveRunsLte, offset, orderBy, reprocessBehavior,
toDateGt, toDateGte, toDateLt, toDateLte }: {
active?: boolean;
completedAtGt?: string;
completedAtGte?: string;
@@ -297,6 +301,10 @@ export const prefetchUseBackfillServiceListBackfillsUi =
(queryClient: QueryClie
createdAtLt?: string;
createdAtLte?: string;
dagId?: string;
+ durationGt?: number;
+ durationGte?: number;
+ durationLt?: number;
+ durationLte?: number;
fromDateGt?: string;
fromDateGte?: string;
fromDateLt?: string;
@@ -313,7 +321,7 @@ export const prefetchUseBackfillServiceListBackfillsUi =
(queryClient: QueryClie
toDateGte?: string;
toDateLt?: string;
toDateLte?: string;
-} = {}) => queryClient.prefetchQuery({ queryKey:
Common.UseBackfillServiceListBackfillsUiKeyFn({ active, completedAtGt,
completedAtGte, completedAtLt, completedAtLte, createdAtGt, createdAtGte,
createdAtLt, createdAtLte, dagId, fromDateGt, fromDateGte, fromDateLt,
fromDateLte, limit, maxActiveRunsGt, maxActiveRunsGte, maxActiveRunsLt,
maxActiveRunsLte, offset, orderBy, reprocessBehavior, toDateGt, toDateGte,
toDateLt, toDateLte }), queryFn: () => BackfillService.listBackfillsUi({
active, [...]
+} = {}) => queryClient.prefetchQuery({ queryKey:
Common.UseBackfillServiceListBackfillsUiKeyFn({ active, completedAtGt,
completedAtGte, completedAtLt, completedAtLte, createdAtGt, createdAtGte,
createdAtLt, createdAtLte, dagId, durationGt, durationGte, durationLt,
durationLte, fromDateGt, fromDateGte, fromDateLt, fromDateLte, limit,
maxActiveRunsGt, maxActiveRunsGte, maxActiveRunsLt, maxActiveRunsLte, offset,
orderBy, reprocessBehavior, toDateGt, toDateGte, toDateLt, toDateLte }), queryF
[...]
/**
* Get Connection
* Get a connection entry.
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 17e50def559..1dd1fb98a06 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts
@@ -279,6 +279,10 @@ export const useBackfillServiceListBackfillDagRuns =
<TData = Common.BackfillSer
* @param data.maxActiveRunsGt
* @param data.maxActiveRunsLte
* @param data.maxActiveRunsLt
+* @param data.durationGte
+* @param data.durationGt
+* @param data.durationLte
+* @param data.durationLt
* @param data.reprocessBehavior
* @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id`
* @param data.dagId
@@ -286,7 +290,7 @@ export const useBackfillServiceListBackfillDagRuns = <TData
= Common.BackfillSer
* @returns BackfillCollectionResponse Successful Response
* @throws ApiError
*/
-export const useBackfillServiceListBackfillsUi = <TData =
Common.BackfillServiceListBackfillsUiDefaultResponse, TError = unknown,
TQueryKey extends Array<unknown> = unknown[]>({ active, completedAtGt,
completedAtGte, completedAtLt, completedAtLte, createdAtGt, createdAtGte,
createdAtLt, createdAtLte, dagId, fromDateGt, fromDateGte, fromDateLt,
fromDateLte, limit, maxActiveRunsGt, maxActiveRunsGte, maxActiveRunsLt,
maxActiveRunsLte, offset, orderBy, reprocessBehavior, toDateGt, toDateGte, [...]
+export const useBackfillServiceListBackfillsUi = <TData =
Common.BackfillServiceListBackfillsUiDefaultResponse, TError = unknown,
TQueryKey extends Array<unknown> = unknown[]>({ active, completedAtGt,
completedAtGte, completedAtLt, completedAtLte, createdAtGt, createdAtGte,
createdAtLt, createdAtLte, dagId, durationGt, durationGte, durationLt,
durationLte, fromDateGt, fromDateGte, fromDateLt, fromDateLte, limit,
maxActiveRunsGt, maxActiveRunsGte, maxActiveRunsLt, maxActiveRunsLte, offset
[...]
active?: boolean;
completedAtGt?: string;
completedAtGte?: string;
@@ -297,6 +301,10 @@ export const useBackfillServiceListBackfillsUi = <TData =
Common.BackfillService
createdAtLt?: string;
createdAtLte?: string;
dagId?: string;
+ durationGt?: number;
+ durationGte?: number;
+ durationLt?: number;
+ durationLte?: number;
fromDateGt?: string;
fromDateGte?: string;
fromDateLt?: string;
@@ -313,7 +321,7 @@ export const useBackfillServiceListBackfillsUi = <TData =
Common.BackfillService
toDateGte?: string;
toDateLt?: string;
toDateLte?: string;
-} = {}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>,
"queryKey" | "queryFn">) => useQuery<TData, TError>({ queryKey:
Common.UseBackfillServiceListBackfillsUiKeyFn({ active, completedAtGt,
completedAtGte, completedAtLt, completedAtLte, createdAtGt, createdAtGte,
createdAtLt, createdAtLte, dagId, fromDateGt, fromDateGte, fromDateLt,
fromDateLte, limit, maxActiveRunsGt, maxActiveRunsGte, maxActiveRunsLt,
maxActiveRunsLte, offset, orderBy, reprocessBehavior, toDateGt, [...]
+} = {}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>,
"queryKey" | "queryFn">) => useQuery<TData, TError>({ queryKey:
Common.UseBackfillServiceListBackfillsUiKeyFn({ active, completedAtGt,
completedAtGte, completedAtLt, completedAtLte, createdAtGt, createdAtGte,
createdAtLt, createdAtLte, dagId, durationGt, durationGte, durationLt,
durationLte, fromDateGt, fromDateGte, fromDateLt, fromDateLte, limit,
maxActiveRunsGt, maxActiveRunsGte, maxActiveRunsLt, maxActiveRuns [...]
/**
* Get Connection
* Get a connection entry.
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 ffc31253bbd..9b762754d93 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts
@@ -279,6 +279,10 @@ export const useBackfillServiceListBackfillDagRunsSuspense
= <TData = Common.Bac
* @param data.maxActiveRunsGt
* @param data.maxActiveRunsLte
* @param data.maxActiveRunsLt
+* @param data.durationGte
+* @param data.durationGt
+* @param data.durationLte
+* @param data.durationLt
* @param data.reprocessBehavior
* @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id`
* @param data.dagId
@@ -286,7 +290,7 @@ export const useBackfillServiceListBackfillDagRunsSuspense
= <TData = Common.Bac
* @returns BackfillCollectionResponse Successful Response
* @throws ApiError
*/
-export const useBackfillServiceListBackfillsUiSuspense = <TData =
Common.BackfillServiceListBackfillsUiDefaultResponse, TError = unknown,
TQueryKey extends Array<unknown> = unknown[]>({ active, completedAtGt,
completedAtGte, completedAtLt, completedAtLte, createdAtGt, createdAtGte,
createdAtLt, createdAtLte, dagId, fromDateGt, fromDateGte, fromDateLt,
fromDateLte, limit, maxActiveRunsGt, maxActiveRunsGte, maxActiveRunsLt,
maxActiveRunsLte, offset, orderBy, reprocessBehavior, toDateGt, to [...]
+export const useBackfillServiceListBackfillsUiSuspense = <TData =
Common.BackfillServiceListBackfillsUiDefaultResponse, TError = unknown,
TQueryKey extends Array<unknown> = unknown[]>({ active, completedAtGt,
completedAtGte, completedAtLt, completedAtLte, createdAtGt, createdAtGte,
createdAtLt, createdAtLte, dagId, durationGt, durationGte, durationLt,
durationLte, fromDateGt, fromDateGte, fromDateLt, fromDateLte, limit,
maxActiveRunsGt, maxActiveRunsGte, maxActiveRunsLt, maxActiveRunsLte [...]
active?: boolean;
completedAtGt?: string;
completedAtGte?: string;
@@ -297,6 +301,10 @@ export const useBackfillServiceListBackfillsUiSuspense =
<TData = Common.Backfil
createdAtLt?: string;
createdAtLte?: string;
dagId?: string;
+ durationGt?: number;
+ durationGte?: number;
+ durationLt?: number;
+ durationLte?: number;
fromDateGt?: string;
fromDateGte?: string;
fromDateLt?: string;
@@ -313,7 +321,7 @@ export const useBackfillServiceListBackfillsUiSuspense =
<TData = Common.Backfil
toDateGte?: string;
toDateLt?: string;
toDateLte?: string;
-} = {}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>,
"queryKey" | "queryFn">) => useSuspenseQuery<TData, TError>({ queryKey:
Common.UseBackfillServiceListBackfillsUiKeyFn({ active, completedAtGt,
completedAtGte, completedAtLt, completedAtLte, createdAtGt, createdAtGte,
createdAtLt, createdAtLte, dagId, fromDateGt, fromDateGte, fromDateLt,
fromDateLte, limit, maxActiveRunsGt, maxActiveRunsGte, maxActiveRunsLt,
maxActiveRunsLte, offset, orderBy, reprocessBehavior, t [...]
+} = {}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>,
"queryKey" | "queryFn">) => useSuspenseQuery<TData, TError>({ queryKey:
Common.UseBackfillServiceListBackfillsUiKeyFn({ active, completedAtGt,
completedAtGte, completedAtLt, completedAtLte, createdAtGt, createdAtGte,
createdAtLt, createdAtLte, dagId, durationGt, durationGte, durationLt,
durationLte, fromDateGt, fromDateGte, fromDateLt, fromDateLte, limit,
maxActiveRunsGt, maxActiveRunsGte, maxActiveRunsLt, maxAc [...]
/**
* Get Connection
* Get a connection entry.
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 12161426709..eeb9bab1271 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
@@ -714,6 +714,10 @@ export class BackfillService {
* @param data.maxActiveRunsGt
* @param data.maxActiveRunsLte
* @param data.maxActiveRunsLt
+ * @param data.durationGte
+ * @param data.durationGt
+ * @param data.durationLte
+ * @param data.durationLt
* @param data.reprocessBehavior
* @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id`
* @param data.dagId
@@ -748,6 +752,10 @@ export class BackfillService {
max_active_runs_gt: data.maxActiveRunsGt,
max_active_runs_lte: data.maxActiveRunsLte,
max_active_runs_lt: data.maxActiveRunsLt,
+ duration_gte: data.durationGte,
+ duration_gt: data.durationGt,
+ duration_lte: data.durationLte,
+ duration_lt: data.durationLt,
reprocess_behavior: data.reprocessBehavior,
order_by: data.orderBy,
dag_id: data.dagId,
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 ddadbd19f28..9b88dfd07c8 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
@@ -3515,6 +3515,10 @@ export type ListBackfillsUiData = {
createdAtLt?: string | null;
createdAtLte?: string | null;
dagId?: string | null;
+ durationGt?: number | null;
+ durationGte?: number | null;
+ durationLt?: number | null;
+ durationLte?: number | null;
fromDateGt?: string | null;
fromDateGte?: string | null;
fromDateLt?: string | null;
diff --git a/airflow-core/src/airflow/ui/src/pages/Dag/Backfills/Backfills.tsx
b/airflow-core/src/airflow/ui/src/pages/Dag/Backfills/Backfills.tsx
index 971373ba5ff..4bb14409c29 100644
--- a/airflow-core/src/airflow/ui/src/pages/Dag/Backfills/Backfills.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Dag/Backfills/Backfills.tsx
@@ -41,6 +41,8 @@ const {
COMPLETED_AT_LTE: COMPLETED_AT_LTE_PARAM,
CREATED_AT_GTE: CREATED_AT_GTE_PARAM,
CREATED_AT_LTE: CREATED_AT_LTE_PARAM,
+ DURATION_GTE: DURATION_GTE_PARAM,
+ DURATION_LTE: DURATION_LTE_PARAM,
FROM_DATE_GTE: FROM_DATE_GTE_PARAM,
FROM_DATE_LTE: FROM_DATE_LTE_PARAM,
MAX_ACTIVE_RUNS_GTE: MAX_ACTIVE_RUNS_GTE_PARAM,
@@ -173,6 +175,8 @@ export const Backfills = () => {
const completedAtLte = searchParams.get(COMPLETED_AT_LTE_PARAM);
const maxActiveRunsGte = searchParams.get(MAX_ACTIVE_RUNS_GTE_PARAM);
const maxActiveRunsLte = searchParams.get(MAX_ACTIVE_RUNS_LTE_PARAM);
+ const durationGte = searchParams.get(DURATION_GTE_PARAM);
+ const durationLte = searchParams.get(DURATION_LTE_PARAM);
const reprocessBehaviorParam = searchParams.get(REPROCESS_BEHAVIOR_PARAM);
const reprocessBehavior = isReprocessBehavior(reprocessBehaviorParam) ?
reprocessBehaviorParam : undefined;
@@ -182,6 +186,8 @@ export const Backfills = () => {
createdAtGte: createdAtGte ?? undefined,
createdAtLte: createdAtLte ?? undefined,
dagId,
+ durationGte: durationGte !== null && durationGte !== "" ?
Number(durationGte) : undefined,
+ durationLte: durationLte !== null && durationLte !== "" ?
Number(durationLte) : undefined,
fromDateGte: fromDateGte ?? undefined,
fromDateLte: fromDateLte ?? undefined,
limit: pagination.pageSize,
diff --git
a/airflow-core/src/airflow/ui/src/pages/Dag/Backfills/BackfillsFilters.tsx
b/airflow-core/src/airflow/ui/src/pages/Dag/Backfills/BackfillsFilters.tsx
index e69893ddadd..48b9694d6ec 100644
--- a/airflow-core/src/airflow/ui/src/pages/Dag/Backfills/BackfillsFilters.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Dag/Backfills/BackfillsFilters.tsx
@@ -31,6 +31,8 @@ export const BackfillsFilters = () => {
SearchParamsKeys.COMPLETED_AT_RANGE,
SearchParamsKeys.MAX_ACTIVE_RUNS_GTE,
SearchParamsKeys.MAX_ACTIVE_RUNS_LTE,
+ SearchParamsKeys.DURATION_GTE,
+ SearchParamsKeys.DURATION_LTE,
SearchParamsKeys.REPROCESS_BEHAVIOR,
];