This is an automated email from the ASF dual-hosted git repository.
pierrejeambrun 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 855c7ec6304 Deadlines endpoints (#62583)
855c7ec6304 is described below
commit 855c7ec6304734cebf2001d0aa2f65871805c643
Author: Richard Wu <[email protected]>
AuthorDate: Thu Apr 2 04:53:14 2026 -0600
Deadlines endpoints (#62583)
* feat: add deadlines UI endpoints
* refactor(deadlines): streamline deadline response models and update
related endpoints
---
.../api_fastapi/core_api/datamodels/ui/deadline.py | 20 ++
.../api_fastapi/core_api/openapi/_private_ui.yaml | 229 ++++++++++++++++++++-
.../api_fastapi/core_api/routes/ui/deadlines.py | 141 +++++++++++--
.../src/airflow/ui/openapi-gen/queries/common.ts | 28 ++-
.../ui/openapi-gen/queries/ensureQueryData.ts | 48 ++++-
.../src/airflow/ui/openapi-gen/queries/prefetch.ts | 48 ++++-
.../src/airflow/ui/openapi-gen/queries/queries.ts | 48 ++++-
.../src/airflow/ui/openapi-gen/queries/suspense.ts | 48 ++++-
.../airflow/ui/openapi-gen/requests/schemas.gen.ts | 80 ++++++-
.../ui/openapi-gen/requests/services.gen.ts | 62 +++++-
.../airflow/ui/openapi-gen/requests/types.gen.ts | 77 ++++++-
.../core_api/routes/ui/test_deadlines.py | 225 ++++++++++++++++++--
12 files changed, 981 insertions(+), 73 deletions(-)
diff --git
a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/ui/deadline.py
b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/ui/deadline.py
index 1ceddeac318..8b9370c4e10 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/ui/deadline.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/ui/deadline.py
@@ -33,6 +33,8 @@ class DeadlineResponse(BaseModel):
deadline_time: datetime
missed: bool
created_at: datetime
+ dag_id: str = Field(validation_alias=AliasPath("dagrun", "dag_id"))
+ dag_run_id: str = Field(validation_alias=AliasPath("dagrun", "run_id"))
alert_name: str | None =
Field(validation_alias=AliasPath("deadline_alert", "name"), default=None)
alert_description: str | None = Field(
validation_alias=AliasPath("deadline_alert", "description"),
default=None
@@ -44,3 +46,21 @@ class DeadlineCollectionResponse(BaseModel):
deadlines: Iterable[DeadlineResponse]
total_entries: int
+
+
+class DeadlineAlertResponse(BaseModel):
+ """DeadlineAlert serializer for responses."""
+
+ id: UUID
+ name: str | None = None
+ description: str | None = None
+ reference_type: str = Field(validation_alias=AliasPath("reference",
"reference_type"))
+ interval: float = Field(description="Interval in seconds between deadline
evaluations.")
+ created_at: datetime
+
+
+class DeadlineAlertCollectionResponse(BaseModel):
+ """DeadlineAlert Collection serializer for responses."""
+
+ deadline_alerts: Iterable[DeadlineAlertResponse]
+ total_entries: int
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 915e4d54300..0e58f9cba26 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
@@ -587,9 +587,15 @@ paths:
get:
tags:
- Deadlines
- summary: Get Dag Run Deadlines
- description: Get all deadlines for a specific DAG run.
- operationId: get_dag_run_deadlines
+ summary: Get Deadlines
+ description: 'Get deadlines for a DAG run.
+
+
+ This endpoint allows specifying `~` as the dag_id and dag_run_id to
retrieve
+ Deadlines for all
+
+ DAGs and DAG runs.'
+ operationId: get_deadlines
security:
- OAuth2PasswordBearer: []
- HTTPBearer: []
@@ -631,13 +637,93 @@ paths:
type: string
description: 'Attributes to order by, multi criteria sort is
supported.
Prefix with `-` for descending order. Supported attributes: `id,
deadline_time,
- created_at, alert_name`'
+ created_at, last_updated_at, missed, dag_id, dag_run_id,
alert_name`'
default:
- deadline_time
title: Order By
description: 'Attributes to order by, multi criteria sort is
supported. Prefix
with `-` for descending order. Supported attributes: `id,
deadline_time,
- created_at, alert_name`'
+ created_at, last_updated_at, missed, dag_id, dag_run_id, alert_name`'
+ - name: missed
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Missed
+ - name: deadline_time_gte
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ format: date-time
+ - type: 'null'
+ title: Deadline Time Gte
+ - name: deadline_time_gt
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ format: date-time
+ - type: 'null'
+ title: Deadline Time Gt
+ - name: deadline_time_lte
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ format: date-time
+ - type: 'null'
+ title: Deadline Time Lte
+ - name: deadline_time_lt
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ format: date-time
+ - type: 'null'
+ title: Deadline Time Lt
+ - name: last_updated_at_gte
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ format: date-time
+ - type: 'null'
+ title: Last Updated At Gte
+ - name: last_updated_at_gt
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ format: date-time
+ - type: 'null'
+ title: Last Updated At Gt
+ - name: last_updated_at_lte
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ format: date-time
+ - type: 'null'
+ title: Last Updated At Lte
+ - name: last_updated_at_lt
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ format: date-time
+ - type: 'null'
+ title: Last Updated At Lt
responses:
'200':
description: Successful Response
@@ -645,6 +731,80 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/DeadlineCollectionResponse'
+ '400':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/HTTPExceptionResponse'
+ description: Bad Request
+ '404':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/HTTPExceptionResponse'
+ description: Not Found
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/HTTPValidationError'
+ /ui/dags/{dag_id}/deadlineAlerts:
+ get:
+ tags:
+ - Deadlines
+ summary: Get Dag Deadline Alerts
+ description: Get all deadline alerts defined on a DAG.
+ operationId: get_dag_deadline_alerts
+ security:
+ - OAuth2PasswordBearer: []
+ - HTTPBearer: []
+ parameters:
+ - name: dag_id
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Dag Id
+ - name: limit
+ in: query
+ required: false
+ schema:
+ type: integer
+ minimum: 0
+ default: 50
+ title: Limit
+ - name: offset
+ in: query
+ required: false
+ schema:
+ type: integer
+ minimum: 0
+ default: 0
+ title: Offset
+ - name: order_by
+ in: query
+ required: false
+ schema:
+ type: array
+ items:
+ type: string
+ description: 'Attributes to order by, multi criteria sort is
supported.
+ Prefix with `-` for descending order. Supported attributes: `id,
created_at,
+ name, interval`'
+ default:
+ - created_at
+ title: Order By
+ description: 'Attributes to order by, multi criteria sort is
supported. Prefix
+ with `-` for descending order. Supported attributes: `id,
created_at, name,
+ interval`'
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DeadlineAlertCollectionResponse'
'404':
content:
application/json:
@@ -2121,6 +2281,57 @@ components:
- queued_dag_count
title: DashboardDagStatsResponse
description: Dashboard DAG Stats serializer for responses.
+ DeadlineAlertCollectionResponse:
+ properties:
+ deadline_alerts:
+ items:
+ $ref: '#/components/schemas/DeadlineAlertResponse'
+ type: array
+ title: Deadline Alerts
+ total_entries:
+ type: integer
+ title: Total Entries
+ type: object
+ required:
+ - deadline_alerts
+ - total_entries
+ title: DeadlineAlertCollectionResponse
+ description: DeadlineAlert Collection serializer for responses.
+ DeadlineAlertResponse:
+ properties:
+ id:
+ type: string
+ format: uuid
+ title: Id
+ name:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Name
+ description:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Description
+ reference_type:
+ type: string
+ title: Reference Type
+ interval:
+ type: number
+ title: Interval
+ description: Interval in seconds between deadline evaluations.
+ created_at:
+ type: string
+ format: date-time
+ title: Created At
+ type: object
+ required:
+ - id
+ - reference_type
+ - interval
+ - created_at
+ title: DeadlineAlertResponse
+ description: DeadlineAlert serializer for responses.
DeadlineCollectionResponse:
properties:
deadlines:
@@ -2154,6 +2365,12 @@ components:
type: string
format: date-time
title: Created At
+ dag_id:
+ type: string
+ title: Dag Id
+ dag_run_id:
+ type: string
+ title: Dag Run Id
alert_name:
anyOf:
- type: string
@@ -2170,6 +2387,8 @@ components:
- deadline_time
- missed
- created_at
+ - dag_id
+ - dag_run_id
title: DeadlineResponse
description: Deadline serializer for responses.
EdgeResponse:
diff --git
a/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/deadlines.py
b/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/deadlines.py
index 5449cf6e953..7e4e44e855b 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/deadlines.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/deadlines.py
@@ -21,26 +21,39 @@ from typing import Annotated
from fastapi import Depends, HTTPException, status
from sqlalchemy import select
-from sqlalchemy.orm import joinedload
+from sqlalchemy.orm import contains_eager, noload
from airflow.api_fastapi.auth.managers.models.resource_details import
DagAccessEntity
from airflow.api_fastapi.common.db.common import SessionDep, paginated_select
-from airflow.api_fastapi.common.parameters import QueryLimit, QueryOffset,
SortParam
+from airflow.api_fastapi.common.parameters import (
+ FilterParam,
+ QueryLimit,
+ QueryOffset,
+ RangeFilter,
+ SortParam,
+ datetime_range_filter_factory,
+ filter_param_factory,
+)
from airflow.api_fastapi.common.router import AirflowRouter
-from airflow.api_fastapi.core_api.datamodels.ui.deadline import
DeadlineCollectionResponse
+from airflow.api_fastapi.core_api.datamodels.ui.deadline import (
+ DeadlineAlertCollectionResponse,
+ DeadlineCollectionResponse,
+)
from airflow.api_fastapi.core_api.openapi.exceptions import
create_openapi_http_exception_doc
-from airflow.api_fastapi.core_api.security import requires_access_dag
+from airflow.api_fastapi.core_api.security import ReadableDagRunsFilterDep,
requires_access_dag
from airflow.models.dagrun import DagRun
from airflow.models.deadline import Deadline
from airflow.models.deadline_alert import DeadlineAlert
+from airflow.models.serialized_dag import SerializedDagModel
-deadlines_router =
AirflowRouter(prefix="/dags/{dag_id}/dagRuns/{dag_run_id}/deadlines",
tags=["Deadlines"])
+deadlines_router = AirflowRouter(prefix="/dags/{dag_id}", tags=["Deadlines"])
@deadlines_router.get(
- "",
+ "/dagRuns/{dag_run_id}/deadlines",
responses=create_openapi_http_exception_doc(
[
+ status.HTTP_400_BAD_REQUEST,
status.HTTP_404_NOT_FOUND,
]
),
@@ -53,52 +66,138 @@ deadlines_router =
AirflowRouter(prefix="/dags/{dag_id}/dagRuns/{dag_run_id}/dea
),
],
)
-def get_dag_run_deadlines(
+def get_deadlines(
dag_id: str,
dag_run_id: str,
session: SessionDep,
limit: QueryLimit,
offset: QueryOffset,
+ readable_dag_runs_filter: ReadableDagRunsFilterDep,
order_by: Annotated[
SortParam,
Depends(
SortParam(
- ["id", "deadline_time", "created_at"],
+ ["id", "deadline_time", "created_at", "last_updated_at",
"missed"],
Deadline,
to_replace={
+ "dag_id": DagRun.dag_id,
+ "dag_run_id": DagRun.run_id,
"alert_name": DeadlineAlert.name,
},
).dynamic_depends(default="deadline_time")
),
],
+ missed: Annotated[FilterParam[bool | None],
Depends(filter_param_factory(Deadline.missed, bool | None))],
+ deadline_time: Annotated[RangeFilter,
Depends(datetime_range_filter_factory("deadline_time", Deadline))],
+ last_updated_at: Annotated[
+ RangeFilter, Depends(datetime_range_filter_factory("last_updated_at",
Deadline))
+ ],
) -> DeadlineCollectionResponse:
- """Get all deadlines for a specific DAG run."""
- dag_run = session.scalar(select(DagRun).where(DagRun.dag_id == dag_id,
DagRun.run_id == dag_run_id))
-
- if not dag_run:
- raise HTTPException(
- status.HTTP_404_NOT_FOUND,
- f"No DAG run found for dag_id={dag_id} dag_run_id={dag_run_id}",
- )
+ """
+ Get deadlines for a DAG run.
+ This endpoint allows specifying `~` as the dag_id and dag_run_id to
retrieve Deadlines for all
+ DAGs and DAG runs.
+ """
query = (
select(Deadline)
.join(Deadline.dagrun)
.outerjoin(Deadline.deadline_alert)
- .where(Deadline.dagrun_id == dag_run.id)
- .where(DagRun.dag_id == dag_id)
- .options(joinedload(Deadline.deadline_alert))
+ .options(
+ contains_eager(Deadline.dagrun).options(noload(DagRun.deadlines)),
+ contains_eager(Deadline.deadline_alert),
+ noload(Deadline.callback),
+ )
)
+ if dag_run_id != "~":
+ if dag_id == "~":
+ raise HTTPException(
+ status.HTTP_400_BAD_REQUEST,
+ "dag_id is required when dag_run_id is specified",
+ )
+ query = query.where(DagRun.dag_id == dag_id, DagRun.run_id ==
dag_run_id)
+ elif dag_id != "~":
+ query = query.where(DagRun.dag_id == dag_id)
+
deadlines_select, total_entries = paginated_select(
statement=query,
- filters=None,
+ filters=[readable_dag_runs_filter, missed, deadline_time,
last_updated_at],
order_by=order_by,
offset=offset,
limit=limit,
session=session,
)
- deadlines = session.scalars(deadlines_select)
+ deadlines = session.scalars(deadlines_select).unique()
+
+ if dag_run_id != "~" and total_entries == 0:
+ dag_run = session.scalar(select(DagRun).where(DagRun.dag_id == dag_id,
DagRun.run_id == dag_run_id))
+ if not dag_run:
+ raise HTTPException(
+ status.HTTP_404_NOT_FOUND,
+ f"DagRun with dag_id: `{dag_id}` and run_id: `{dag_run_id}`
was not found",
+ )
return DeadlineCollectionResponse(deadlines=deadlines,
total_entries=total_entries)
+
+
+@deadlines_router.get(
+ "/deadlineAlerts",
+ responses=create_openapi_http_exception_doc(
+ [
+ status.HTTP_404_NOT_FOUND,
+ ]
+ ),
+ dependencies=[
+ Depends(
+ requires_access_dag(
+ method="GET",
+ )
+ ),
+ ],
+)
+def get_dag_deadline_alerts(
+ dag_id: str,
+ session: SessionDep,
+ limit: QueryLimit,
+ offset: QueryOffset,
+ order_by: Annotated[
+ SortParam,
+ Depends(
+ SortParam(
+ ["id", "created_at", "name", "interval"],
+ DeadlineAlert,
+ ).dynamic_depends(default="created_at")
+ ),
+ ],
+) -> DeadlineAlertCollectionResponse:
+ """Get all deadline alerts defined on a DAG."""
+ serialized_dag = session.scalar(
+ select(SerializedDagModel)
+ .where(SerializedDagModel.dag_id == dag_id)
+ .order_by(SerializedDagModel.id.desc())
+ )
+
+ if not serialized_dag:
+ raise HTTPException(
+ status.HTTP_404_NOT_FOUND,
+ f"Dag with id {dag_id} was not found",
+ )
+
+ query = select(DeadlineAlert).where(
+ DeadlineAlert.serialized_dag_id == serialized_dag.id,
+ )
+
+ alerts_select, total_entries = paginated_select(
+ statement=query,
+ filters=None,
+ order_by=order_by,
+ offset=offset,
+ limit=limit,
+ session=session,
+ )
+
+ alerts = session.scalars(alerts_select)
+
+ return DeadlineAlertCollectionResponse(deadline_alerts=alerts,
total_entries=total_entries)
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 612a3d56747..d37cf4fdad4 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts
@@ -822,16 +822,34 @@ export type DashboardServiceDagStatsDefaultResponse =
Awaited<ReturnType<typeof
export type DashboardServiceDagStatsQueryResult<TData =
DashboardServiceDagStatsDefaultResponse, TError = unknown> =
UseQueryResult<TData, TError>;
export const useDashboardServiceDagStatsKey = "DashboardServiceDagStats";
export const UseDashboardServiceDagStatsKeyFn = (queryKey?: Array<unknown>) =>
[useDashboardServiceDagStatsKey, ...(queryKey ?? [])];
-export type DeadlinesServiceGetDagRunDeadlinesDefaultResponse =
Awaited<ReturnType<typeof DeadlinesService.getDagRunDeadlines>>;
-export type DeadlinesServiceGetDagRunDeadlinesQueryResult<TData =
DeadlinesServiceGetDagRunDeadlinesDefaultResponse, TError = unknown> =
UseQueryResult<TData, TError>;
-export const useDeadlinesServiceGetDagRunDeadlinesKey =
"DeadlinesServiceGetDagRunDeadlines";
-export const UseDeadlinesServiceGetDagRunDeadlinesKeyFn = ({ dagId, dagRunId,
limit, offset, orderBy }: {
+export type DeadlinesServiceGetDeadlinesDefaultResponse =
Awaited<ReturnType<typeof DeadlinesService.getDeadlines>>;
+export type DeadlinesServiceGetDeadlinesQueryResult<TData =
DeadlinesServiceGetDeadlinesDefaultResponse, TError = unknown> =
UseQueryResult<TData, TError>;
+export const useDeadlinesServiceGetDeadlinesKey =
"DeadlinesServiceGetDeadlines";
+export const UseDeadlinesServiceGetDeadlinesKeyFn = ({ dagId, dagRunId,
deadlineTimeGt, deadlineTimeGte, deadlineTimeLt, deadlineTimeLte,
lastUpdatedAtGt, lastUpdatedAtGte, lastUpdatedAtLt, lastUpdatedAtLte, limit,
missed, offset, orderBy }: {
dagId: string;
dagRunId: string;
+ deadlineTimeGt?: string;
+ deadlineTimeGte?: string;
+ deadlineTimeLt?: string;
+ deadlineTimeLte?: string;
+ lastUpdatedAtGt?: string;
+ lastUpdatedAtGte?: string;
+ lastUpdatedAtLt?: string;
+ lastUpdatedAtLte?: string;
limit?: number;
+ missed?: boolean;
offset?: number;
orderBy?: string[];
-}, queryKey?: Array<unknown>) => [useDeadlinesServiceGetDagRunDeadlinesKey,
...(queryKey ?? [{ dagId, dagRunId, limit, offset, orderBy }])];
+}, queryKey?: Array<unknown>) => [useDeadlinesServiceGetDeadlinesKey,
...(queryKey ?? [{ dagId, dagRunId, deadlineTimeGt, deadlineTimeGte,
deadlineTimeLt, deadlineTimeLte, lastUpdatedAtGt, lastUpdatedAtGte,
lastUpdatedAtLt, lastUpdatedAtLte, limit, missed, offset, orderBy }])];
+export type DeadlinesServiceGetDagDeadlineAlertsDefaultResponse =
Awaited<ReturnType<typeof DeadlinesService.getDagDeadlineAlerts>>;
+export type DeadlinesServiceGetDagDeadlineAlertsQueryResult<TData =
DeadlinesServiceGetDagDeadlineAlertsDefaultResponse, TError = unknown> =
UseQueryResult<TData, TError>;
+export const useDeadlinesServiceGetDagDeadlineAlertsKey =
"DeadlinesServiceGetDagDeadlineAlerts";
+export const UseDeadlinesServiceGetDagDeadlineAlertsKeyFn = ({ dagId, limit,
offset, orderBy }: {
+ dagId: string;
+ limit?: number;
+ offset?: number;
+ orderBy?: string[];
+}, queryKey?: Array<unknown>) => [useDeadlinesServiceGetDagDeadlineAlertsKey,
...(queryKey ?? [{ dagId, limit, offset, orderBy }])];
export type StructureServiceStructureDataDefaultResponse =
Awaited<ReturnType<typeof StructureService.structureData>>;
export type StructureServiceStructureDataQueryResult<TData =
StructureServiceStructureDataDefaultResponse, TError = unknown> =
UseQueryResult<TData, TError>;
export const useStructureServiceStructureDataKey =
"StructureServiceStructureData";
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 8bc9e9df8e6..24bcb69c78a 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts
@@ -1560,24 +1560,62 @@ export const
ensureUseDashboardServiceHistoricalMetricsData = (queryClient: Quer
*/
export const ensureUseDashboardServiceDagStatsData = (queryClient:
QueryClient) => queryClient.ensureQueryData({ queryKey:
Common.UseDashboardServiceDagStatsKeyFn(), queryFn: () =>
DashboardService.dagStats() });
/**
-* Get Dag Run Deadlines
-* Get all deadlines for a specific DAG run.
+* Get Deadlines
+* Get deadlines for a DAG run.
+*
+* This endpoint allows specifying `~` as the dag_id and dag_run_id to retrieve
Deadlines for all
+* DAGs and DAG runs.
* @param data The data for the request.
* @param data.dagId
* @param data.dagRunId
* @param data.limit
* @param data.offset
-* @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id,
deadline_time, created_at, alert_name`
+* @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id,
deadline_time, created_at, last_updated_at, missed, dag_id, dag_run_id,
alert_name`
+* @param data.missed
+* @param data.deadlineTimeGte
+* @param data.deadlineTimeGt
+* @param data.deadlineTimeLte
+* @param data.deadlineTimeLt
+* @param data.lastUpdatedAtGte
+* @param data.lastUpdatedAtGt
+* @param data.lastUpdatedAtLte
+* @param data.lastUpdatedAtLt
* @returns DeadlineCollectionResponse Successful Response
* @throws ApiError
*/
-export const ensureUseDeadlinesServiceGetDagRunDeadlinesData = (queryClient:
QueryClient, { dagId, dagRunId, limit, offset, orderBy }: {
+export const ensureUseDeadlinesServiceGetDeadlinesData = (queryClient:
QueryClient, { dagId, dagRunId, deadlineTimeGt, deadlineTimeGte,
deadlineTimeLt, deadlineTimeLte, lastUpdatedAtGt, lastUpdatedAtGte,
lastUpdatedAtLt, lastUpdatedAtLte, limit, missed, offset, orderBy }: {
dagId: string;
dagRunId: string;
+ deadlineTimeGt?: string;
+ deadlineTimeGte?: string;
+ deadlineTimeLt?: string;
+ deadlineTimeLte?: string;
+ lastUpdatedAtGt?: string;
+ lastUpdatedAtGte?: string;
+ lastUpdatedAtLt?: string;
+ lastUpdatedAtLte?: string;
+ limit?: number;
+ missed?: boolean;
+ offset?: number;
+ orderBy?: string[];
+}) => queryClient.ensureQueryData({ queryKey:
Common.UseDeadlinesServiceGetDeadlinesKeyFn({ dagId, dagRunId, deadlineTimeGt,
deadlineTimeGte, deadlineTimeLt, deadlineTimeLte, lastUpdatedAtGt,
lastUpdatedAtGte, lastUpdatedAtLt, lastUpdatedAtLte, limit, missed, offset,
orderBy }), queryFn: () => DeadlinesService.getDeadlines({ dagId, dagRunId,
deadlineTimeGt, deadlineTimeGte, deadlineTimeLt, deadlineTimeLte,
lastUpdatedAtGt, lastUpdatedAtGte, lastUpdatedAtLt, lastUpdatedAtLte, limit,
misse [...]
+/**
+* Get Dag Deadline Alerts
+* Get all deadline alerts defined on a DAG.
+* @param data The data for the request.
+* @param data.dagId
+* @param data.limit
+* @param data.offset
+* @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id,
created_at, name, interval`
+* @returns DeadlineAlertCollectionResponse Successful Response
+* @throws ApiError
+*/
+export const ensureUseDeadlinesServiceGetDagDeadlineAlertsData = (queryClient:
QueryClient, { dagId, limit, offset, orderBy }: {
+ dagId: string;
limit?: number;
offset?: number;
orderBy?: string[];
-}) => queryClient.ensureQueryData({ queryKey:
Common.UseDeadlinesServiceGetDagRunDeadlinesKeyFn({ dagId, dagRunId, limit,
offset, orderBy }), queryFn: () => DeadlinesService.getDagRunDeadlines({ dagId,
dagRunId, limit, offset, orderBy }) });
+}) => queryClient.ensureQueryData({ queryKey:
Common.UseDeadlinesServiceGetDagDeadlineAlertsKeyFn({ dagId, limit, offset,
orderBy }), queryFn: () => DeadlinesService.getDagDeadlineAlerts({ dagId,
limit, offset, orderBy }) });
/**
* Structure Data
* Get Structure Data.
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 f4cb6f482bd..b6c6318a978 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts
@@ -1560,24 +1560,62 @@ export const
prefetchUseDashboardServiceHistoricalMetrics = (queryClient: QueryC
*/
export const prefetchUseDashboardServiceDagStats = (queryClient: QueryClient)
=> queryClient.prefetchQuery({ queryKey:
Common.UseDashboardServiceDagStatsKeyFn(), queryFn: () =>
DashboardService.dagStats() });
/**
-* Get Dag Run Deadlines
-* Get all deadlines for a specific DAG run.
+* Get Deadlines
+* Get deadlines for a DAG run.
+*
+* This endpoint allows specifying `~` as the dag_id and dag_run_id to retrieve
Deadlines for all
+* DAGs and DAG runs.
* @param data The data for the request.
* @param data.dagId
* @param data.dagRunId
* @param data.limit
* @param data.offset
-* @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id,
deadline_time, created_at, alert_name`
+* @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id,
deadline_time, created_at, last_updated_at, missed, dag_id, dag_run_id,
alert_name`
+* @param data.missed
+* @param data.deadlineTimeGte
+* @param data.deadlineTimeGt
+* @param data.deadlineTimeLte
+* @param data.deadlineTimeLt
+* @param data.lastUpdatedAtGte
+* @param data.lastUpdatedAtGt
+* @param data.lastUpdatedAtLte
+* @param data.lastUpdatedAtLt
* @returns DeadlineCollectionResponse Successful Response
* @throws ApiError
*/
-export const prefetchUseDeadlinesServiceGetDagRunDeadlines = (queryClient:
QueryClient, { dagId, dagRunId, limit, offset, orderBy }: {
+export const prefetchUseDeadlinesServiceGetDeadlines = (queryClient:
QueryClient, { dagId, dagRunId, deadlineTimeGt, deadlineTimeGte,
deadlineTimeLt, deadlineTimeLte, lastUpdatedAtGt, lastUpdatedAtGte,
lastUpdatedAtLt, lastUpdatedAtLte, limit, missed, offset, orderBy }: {
dagId: string;
dagRunId: string;
+ deadlineTimeGt?: string;
+ deadlineTimeGte?: string;
+ deadlineTimeLt?: string;
+ deadlineTimeLte?: string;
+ lastUpdatedAtGt?: string;
+ lastUpdatedAtGte?: string;
+ lastUpdatedAtLt?: string;
+ lastUpdatedAtLte?: string;
+ limit?: number;
+ missed?: boolean;
+ offset?: number;
+ orderBy?: string[];
+}) => queryClient.prefetchQuery({ queryKey:
Common.UseDeadlinesServiceGetDeadlinesKeyFn({ dagId, dagRunId, deadlineTimeGt,
deadlineTimeGte, deadlineTimeLt, deadlineTimeLte, lastUpdatedAtGt,
lastUpdatedAtGte, lastUpdatedAtLt, lastUpdatedAtLte, limit, missed, offset,
orderBy }), queryFn: () => DeadlinesService.getDeadlines({ dagId, dagRunId,
deadlineTimeGt, deadlineTimeGte, deadlineTimeLt, deadlineTimeLte,
lastUpdatedAtGt, lastUpdatedAtGte, lastUpdatedAtLt, lastUpdatedAtLte, limit,
missed, [...]
+/**
+* Get Dag Deadline Alerts
+* Get all deadline alerts defined on a DAG.
+* @param data The data for the request.
+* @param data.dagId
+* @param data.limit
+* @param data.offset
+* @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id,
created_at, name, interval`
+* @returns DeadlineAlertCollectionResponse Successful Response
+* @throws ApiError
+*/
+export const prefetchUseDeadlinesServiceGetDagDeadlineAlerts = (queryClient:
QueryClient, { dagId, limit, offset, orderBy }: {
+ dagId: string;
limit?: number;
offset?: number;
orderBy?: string[];
-}) => queryClient.prefetchQuery({ queryKey:
Common.UseDeadlinesServiceGetDagRunDeadlinesKeyFn({ dagId, dagRunId, limit,
offset, orderBy }), queryFn: () => DeadlinesService.getDagRunDeadlines({ dagId,
dagRunId, limit, offset, orderBy }) });
+}) => queryClient.prefetchQuery({ queryKey:
Common.UseDeadlinesServiceGetDagDeadlineAlertsKeyFn({ dagId, limit, offset,
orderBy }), queryFn: () => DeadlinesService.getDagDeadlineAlerts({ dagId,
limit, offset, orderBy }) });
/**
* Structure Data
* Get Structure Data.
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 dac7a198e59..b35fb3b8bf4 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts
@@ -1560,24 +1560,62 @@ export const useDashboardServiceHistoricalMetrics =
<TData = Common.DashboardSer
*/
export const useDashboardServiceDagStats = <TData =
Common.DashboardServiceDagStatsDefaultResponse, TError = unknown, TQueryKey
extends Array<unknown> = unknown[]>(queryKey?: TQueryKey, options?:
Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">) =>
useQuery<TData, TError>({ queryKey:
Common.UseDashboardServiceDagStatsKeyFn(queryKey), queryFn: () =>
DashboardService.dagStats() as TData, ...options });
/**
-* Get Dag Run Deadlines
-* Get all deadlines for a specific DAG run.
+* Get Deadlines
+* Get deadlines for a DAG run.
+*
+* This endpoint allows specifying `~` as the dag_id and dag_run_id to retrieve
Deadlines for all
+* DAGs and DAG runs.
* @param data The data for the request.
* @param data.dagId
* @param data.dagRunId
* @param data.limit
* @param data.offset
-* @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id,
deadline_time, created_at, alert_name`
+* @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id,
deadline_time, created_at, last_updated_at, missed, dag_id, dag_run_id,
alert_name`
+* @param data.missed
+* @param data.deadlineTimeGte
+* @param data.deadlineTimeGt
+* @param data.deadlineTimeLte
+* @param data.deadlineTimeLt
+* @param data.lastUpdatedAtGte
+* @param data.lastUpdatedAtGt
+* @param data.lastUpdatedAtLte
+* @param data.lastUpdatedAtLt
* @returns DeadlineCollectionResponse Successful Response
* @throws ApiError
*/
-export const useDeadlinesServiceGetDagRunDeadlines = <TData =
Common.DeadlinesServiceGetDagRunDeadlinesDefaultResponse, TError = unknown,
TQueryKey extends Array<unknown> = unknown[]>({ dagId, dagRunId, limit, offset,
orderBy }: {
+export const useDeadlinesServiceGetDeadlines = <TData =
Common.DeadlinesServiceGetDeadlinesDefaultResponse, TError = unknown, TQueryKey
extends Array<unknown> = unknown[]>({ dagId, dagRunId, deadlineTimeGt,
deadlineTimeGte, deadlineTimeLt, deadlineTimeLte, lastUpdatedAtGt,
lastUpdatedAtGte, lastUpdatedAtLt, lastUpdatedAtLte, limit, missed, offset,
orderBy }: {
dagId: string;
dagRunId: string;
+ deadlineTimeGt?: string;
+ deadlineTimeGte?: string;
+ deadlineTimeLt?: string;
+ deadlineTimeLte?: string;
+ lastUpdatedAtGt?: string;
+ lastUpdatedAtGte?: string;
+ lastUpdatedAtLt?: string;
+ lastUpdatedAtLte?: string;
+ limit?: number;
+ missed?: boolean;
+ offset?: number;
+ orderBy?: string[];
+}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>,
"queryKey" | "queryFn">) => useQuery<TData, TError>({ queryKey:
Common.UseDeadlinesServiceGetDeadlinesKeyFn({ dagId, dagRunId, deadlineTimeGt,
deadlineTimeGte, deadlineTimeLt, deadlineTimeLte, lastUpdatedAtGt,
lastUpdatedAtGte, lastUpdatedAtLt, lastUpdatedAtLte, limit, missed, offset,
orderBy }, queryKey), queryFn: () => DeadlinesService.getDeadlines({ dagId,
dagRunId, deadlineTimeGt, deadlineTimeGte, deadlineTimeLt, [...]
+/**
+* Get Dag Deadline Alerts
+* Get all deadline alerts defined on a DAG.
+* @param data The data for the request.
+* @param data.dagId
+* @param data.limit
+* @param data.offset
+* @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id,
created_at, name, interval`
+* @returns DeadlineAlertCollectionResponse Successful Response
+* @throws ApiError
+*/
+export const useDeadlinesServiceGetDagDeadlineAlerts = <TData =
Common.DeadlinesServiceGetDagDeadlineAlertsDefaultResponse, TError = unknown,
TQueryKey extends Array<unknown> = unknown[]>({ dagId, limit, offset, orderBy
}: {
+ dagId: string;
limit?: number;
offset?: number;
orderBy?: string[];
-}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>,
"queryKey" | "queryFn">) => useQuery<TData, TError>({ queryKey:
Common.UseDeadlinesServiceGetDagRunDeadlinesKeyFn({ dagId, dagRunId, limit,
offset, orderBy }, queryKey), queryFn: () =>
DeadlinesService.getDagRunDeadlines({ dagId, dagRunId, limit, offset, orderBy
}) as TData, ...options });
+}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>,
"queryKey" | "queryFn">) => useQuery<TData, TError>({ queryKey:
Common.UseDeadlinesServiceGetDagDeadlineAlertsKeyFn({ dagId, limit, offset,
orderBy }, queryKey), queryFn: () => DeadlinesService.getDagDeadlineAlerts({
dagId, limit, offset, orderBy }) as TData, ...options });
/**
* Structure Data
* Get Structure Data.
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 c4a41691b1a..4f5e12fd437 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts
@@ -1560,24 +1560,62 @@ export const
useDashboardServiceHistoricalMetricsSuspense = <TData = Common.Dash
*/
export const useDashboardServiceDagStatsSuspense = <TData =
Common.DashboardServiceDagStatsDefaultResponse, TError = unknown, TQueryKey
extends Array<unknown> = unknown[]>(queryKey?: TQueryKey, options?:
Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">) =>
useSuspenseQuery<TData, TError>({ queryKey:
Common.UseDashboardServiceDagStatsKeyFn(queryKey), queryFn: () =>
DashboardService.dagStats() as TData, ...options });
/**
-* Get Dag Run Deadlines
-* Get all deadlines for a specific DAG run.
+* Get Deadlines
+* Get deadlines for a DAG run.
+*
+* This endpoint allows specifying `~` as the dag_id and dag_run_id to retrieve
Deadlines for all
+* DAGs and DAG runs.
* @param data The data for the request.
* @param data.dagId
* @param data.dagRunId
* @param data.limit
* @param data.offset
-* @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id,
deadline_time, created_at, alert_name`
+* @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id,
deadline_time, created_at, last_updated_at, missed, dag_id, dag_run_id,
alert_name`
+* @param data.missed
+* @param data.deadlineTimeGte
+* @param data.deadlineTimeGt
+* @param data.deadlineTimeLte
+* @param data.deadlineTimeLt
+* @param data.lastUpdatedAtGte
+* @param data.lastUpdatedAtGt
+* @param data.lastUpdatedAtLte
+* @param data.lastUpdatedAtLt
* @returns DeadlineCollectionResponse Successful Response
* @throws ApiError
*/
-export const useDeadlinesServiceGetDagRunDeadlinesSuspense = <TData =
Common.DeadlinesServiceGetDagRunDeadlinesDefaultResponse, TError = unknown,
TQueryKey extends Array<unknown> = unknown[]>({ dagId, dagRunId, limit, offset,
orderBy }: {
+export const useDeadlinesServiceGetDeadlinesSuspense = <TData =
Common.DeadlinesServiceGetDeadlinesDefaultResponse, TError = unknown, TQueryKey
extends Array<unknown> = unknown[]>({ dagId, dagRunId, deadlineTimeGt,
deadlineTimeGte, deadlineTimeLt, deadlineTimeLte, lastUpdatedAtGt,
lastUpdatedAtGte, lastUpdatedAtLt, lastUpdatedAtLte, limit, missed, offset,
orderBy }: {
dagId: string;
dagRunId: string;
+ deadlineTimeGt?: string;
+ deadlineTimeGte?: string;
+ deadlineTimeLt?: string;
+ deadlineTimeLte?: string;
+ lastUpdatedAtGt?: string;
+ lastUpdatedAtGte?: string;
+ lastUpdatedAtLt?: string;
+ lastUpdatedAtLte?: string;
+ limit?: number;
+ missed?: boolean;
+ offset?: number;
+ orderBy?: string[];
+}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>,
"queryKey" | "queryFn">) => useSuspenseQuery<TData, TError>({ queryKey:
Common.UseDeadlinesServiceGetDeadlinesKeyFn({ dagId, dagRunId, deadlineTimeGt,
deadlineTimeGte, deadlineTimeLt, deadlineTimeLte, lastUpdatedAtGt,
lastUpdatedAtGte, lastUpdatedAtLt, lastUpdatedAtLte, limit, missed, offset,
orderBy }, queryKey), queryFn: () => DeadlinesService.getDeadlines({ dagId,
dagRunId, deadlineTimeGt, deadlineTimeGte, deadlin [...]
+/**
+* Get Dag Deadline Alerts
+* Get all deadline alerts defined on a DAG.
+* @param data The data for the request.
+* @param data.dagId
+* @param data.limit
+* @param data.offset
+* @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id,
created_at, name, interval`
+* @returns DeadlineAlertCollectionResponse Successful Response
+* @throws ApiError
+*/
+export const useDeadlinesServiceGetDagDeadlineAlertsSuspense = <TData =
Common.DeadlinesServiceGetDagDeadlineAlertsDefaultResponse, TError = unknown,
TQueryKey extends Array<unknown> = unknown[]>({ dagId, limit, offset, orderBy
}: {
+ dagId: string;
limit?: number;
offset?: number;
orderBy?: string[];
-}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>,
"queryKey" | "queryFn">) => useSuspenseQuery<TData, TError>({ queryKey:
Common.UseDeadlinesServiceGetDagRunDeadlinesKeyFn({ dagId, dagRunId, limit,
offset, orderBy }, queryKey), queryFn: () =>
DeadlinesService.getDagRunDeadlines({ dagId, dagRunId, limit, offset, orderBy
}) as TData, ...options });
+}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>,
"queryKey" | "queryFn">) => useSuspenseQuery<TData, TError>({ queryKey:
Common.UseDeadlinesServiceGetDagDeadlineAlertsKeyFn({ dagId, limit, offset,
orderBy }, queryKey), queryFn: () => DeadlinesService.getDagDeadlineAlerts({
dagId, limit, offset, orderBy }) as TData, ...options });
/**
* Structure Data
* Get Structure Data.
diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts
b/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts
index c5077028b44..cbc0ecaa172 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts
@@ -7958,6 +7958,76 @@ export const $DashboardDagStatsResponse = {
description: 'Dashboard DAG Stats serializer for responses.'
} as const;
+export const $DeadlineAlertCollectionResponse = {
+ properties: {
+ deadline_alerts: {
+ items: {
+ '$ref': '#/components/schemas/DeadlineAlertResponse'
+ },
+ type: 'array',
+ title: 'Deadline Alerts'
+ },
+ total_entries: {
+ type: 'integer',
+ title: 'Total Entries'
+ }
+ },
+ type: 'object',
+ required: ['deadline_alerts', 'total_entries'],
+ title: 'DeadlineAlertCollectionResponse',
+ description: 'DeadlineAlert Collection serializer for responses.'
+} as const;
+
+export const $DeadlineAlertResponse = {
+ properties: {
+ id: {
+ type: 'string',
+ format: 'uuid',
+ title: 'Id'
+ },
+ name: {
+ anyOf: [
+ {
+ type: 'string'
+ },
+ {
+ type: 'null'
+ }
+ ],
+ title: 'Name'
+ },
+ description: {
+ anyOf: [
+ {
+ type: 'string'
+ },
+ {
+ type: 'null'
+ }
+ ],
+ title: 'Description'
+ },
+ reference_type: {
+ type: 'string',
+ title: 'Reference Type'
+ },
+ interval: {
+ type: 'number',
+ title: 'Interval',
+ description: 'Interval in seconds between deadline evaluations.'
+ },
+ created_at: {
+ type: 'string',
+ format: 'date-time',
+ title: 'Created At'
+ }
+ },
+ type: 'object',
+ required: ['id', 'reference_type', 'interval', 'created_at'],
+ title: 'DeadlineAlertResponse',
+ description: 'DeadlineAlert serializer for responses.'
+} as const;
+
export const $DeadlineCollectionResponse = {
properties: {
deadlines: {
@@ -7999,6 +8069,14 @@ export const $DeadlineResponse = {
format: 'date-time',
title: 'Created At'
},
+ dag_id: {
+ type: 'string',
+ title: 'Dag Id'
+ },
+ dag_run_id: {
+ type: 'string',
+ title: 'Dag Run Id'
+ },
alert_name: {
anyOf: [
{
@@ -8023,7 +8101,7 @@ export const $DeadlineResponse = {
}
},
type: 'object',
- required: ['id', 'deadline_time', 'missed', 'created_at'],
+ required: ['id', 'deadline_time', 'missed', 'created_at', 'dag_id',
'dag_run_id'],
title: 'DeadlineResponse',
description: 'Deadline serializer for responses.'
} as const;
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 6f0c2af82fb..005e0a16cdf 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
@@ -3,7 +3,7 @@
import type { CancelablePromise } from './core/CancelablePromise';
import { OpenAPI } from './core/OpenAPI';
import { request as __request } from './core/request';
-import type { GetAssetsData, GetAssetsResponse, GetAssetAliasesData,
GetAssetAliasesResponse, GetAssetAliasData, GetAssetAliasResponse,
GetAssetEventsData, GetAssetEventsResponse, CreateAssetEventData,
CreateAssetEventResponse, MaterializeAssetData, MaterializeAssetResponse,
GetAssetQueuedEventsData, GetAssetQueuedEventsResponse,
DeleteAssetQueuedEventsData, DeleteAssetQueuedEventsResponse, GetAssetData,
GetAssetResponse, GetDagAssetQueuedEventsData, GetDagAssetQueuedEventsResponse,
Dele [...]
+import type { GetAssetsData, GetAssetsResponse, GetAssetAliasesData,
GetAssetAliasesResponse, GetAssetAliasData, GetAssetAliasResponse,
GetAssetEventsData, GetAssetEventsResponse, CreateAssetEventData,
CreateAssetEventResponse, MaterializeAssetData, MaterializeAssetResponse,
GetAssetQueuedEventsData, GetAssetQueuedEventsResponse,
DeleteAssetQueuedEventsData, DeleteAssetQueuedEventsResponse, GetAssetData,
GetAssetResponse, GetDagAssetQueuedEventsData, GetDagAssetQueuedEventsResponse,
Dele [...]
export class AssetService {
/**
@@ -3992,18 +3992,30 @@ export class DashboardService {
export class DeadlinesService {
/**
- * Get Dag Run Deadlines
- * Get all deadlines for a specific DAG run.
+ * Get Deadlines
+ * Get deadlines for a DAG run.
+ *
+ * This endpoint allows specifying `~` as the dag_id and dag_run_id to
retrieve Deadlines for all
+ * DAGs and DAG runs.
* @param data The data for the request.
* @param data.dagId
* @param data.dagRunId
* @param data.limit
* @param data.offset
- * @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id,
deadline_time, created_at, alert_name`
+ * @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id,
deadline_time, created_at, last_updated_at, missed, dag_id, dag_run_id,
alert_name`
+ * @param data.missed
+ * @param data.deadlineTimeGte
+ * @param data.deadlineTimeGt
+ * @param data.deadlineTimeLte
+ * @param data.deadlineTimeLt
+ * @param data.lastUpdatedAtGte
+ * @param data.lastUpdatedAtGt
+ * @param data.lastUpdatedAtLte
+ * @param data.lastUpdatedAtLt
* @returns DeadlineCollectionResponse Successful Response
* @throws ApiError
*/
- public static getDagRunDeadlines(data: GetDagRunDeadlinesData):
CancelablePromise<GetDagRunDeadlinesResponse> {
+ public static getDeadlines(data: GetDeadlinesData):
CancelablePromise<GetDeadlinesResponse> {
return __request(OpenAPI, {
method: 'GET',
url: '/ui/dags/{dag_id}/dagRuns/{dag_run_id}/deadlines',
@@ -4011,6 +4023,46 @@ export class DeadlinesService {
dag_id: data.dagId,
dag_run_id: data.dagRunId
},
+ query: {
+ limit: data.limit,
+ offset: data.offset,
+ order_by: data.orderBy,
+ missed: data.missed,
+ deadline_time_gte: data.deadlineTimeGte,
+ deadline_time_gt: data.deadlineTimeGt,
+ deadline_time_lte: data.deadlineTimeLte,
+ deadline_time_lt: data.deadlineTimeLt,
+ last_updated_at_gte: data.lastUpdatedAtGte,
+ last_updated_at_gt: data.lastUpdatedAtGt,
+ last_updated_at_lte: data.lastUpdatedAtLte,
+ last_updated_at_lt: data.lastUpdatedAtLt
+ },
+ errors: {
+ 400: 'Bad Request',
+ 404: 'Not Found',
+ 422: 'Validation Error'
+ }
+ });
+ }
+
+ /**
+ * Get Dag Deadline Alerts
+ * Get all deadline alerts defined on a DAG.
+ * @param data The data for the request.
+ * @param data.dagId
+ * @param data.limit
+ * @param data.offset
+ * @param data.orderBy Attributes to order by, multi criteria sort is
supported. Prefix with `-` for descending order. Supported attributes: `id,
created_at, name, interval`
+ * @returns DeadlineAlertCollectionResponse Successful Response
+ * @throws ApiError
+ */
+ public static getDagDeadlineAlerts(data: GetDagDeadlineAlertsData):
CancelablePromise<GetDagDeadlineAlertsResponse> {
+ return __request(OpenAPI, {
+ method: 'GET',
+ url: '/ui/dags/{dag_id}/deadlineAlerts',
+ path: {
+ dag_id: data.dagId
+ },
query: {
limit: data.limit,
offset: data.offset,
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 521643cf7f0..595fc8ab06a 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
@@ -1937,6 +1937,29 @@ export type DashboardDagStatsResponse = {
queued_dag_count: number;
};
+/**
+ * DeadlineAlert Collection serializer for responses.
+ */
+export type DeadlineAlertCollectionResponse = {
+ deadline_alerts: Array<DeadlineAlertResponse>;
+ total_entries: number;
+};
+
+/**
+ * DeadlineAlert serializer for responses.
+ */
+export type DeadlineAlertResponse = {
+ id: string;
+ name?: string | null;
+ description?: string | null;
+ reference_type: string;
+ /**
+ * Interval in seconds between deadline evaluations.
+ */
+ interval: number;
+ created_at: string;
+};
+
/**
* Deadline Collection serializer for responses.
*/
@@ -1953,6 +1976,8 @@ export type DeadlineResponse = {
deadline_time: string;
missed: boolean;
created_at: string;
+ dag_id: string;
+ dag_run_id: string;
alert_name?: string | null;
alert_description?: string | null;
};
@@ -3596,18 +3621,39 @@ export type HistoricalMetricsResponse =
HistoricalMetricDataResponse;
export type DagStatsResponse2 = DashboardDagStatsResponse;
-export type GetDagRunDeadlinesData = {
+export type GetDeadlinesData = {
dagId: string;
dagRunId: string;
+ deadlineTimeGt?: string | null;
+ deadlineTimeGte?: string | null;
+ deadlineTimeLt?: string | null;
+ deadlineTimeLte?: string | null;
+ lastUpdatedAtGt?: string | null;
+ lastUpdatedAtGte?: string | null;
+ lastUpdatedAtLt?: string | null;
+ lastUpdatedAtLte?: string | null;
limit?: number;
+ missed?: boolean | null;
offset?: number;
/**
- * Attributes to order by, multi criteria sort is supported. Prefix with
`-` for descending order. Supported attributes: `id, deadline_time, created_at,
alert_name`
+ * Attributes to order by, multi criteria sort is supported. Prefix with
`-` for descending order. Supported attributes: `id, deadline_time, created_at,
last_updated_at, missed, dag_id, dag_run_id, alert_name`
*/
orderBy?: Array<(string)>;
};
-export type GetDagRunDeadlinesResponse = DeadlineCollectionResponse;
+export type GetDeadlinesResponse = DeadlineCollectionResponse;
+
+export type GetDagDeadlineAlertsData = {
+ dagId: string;
+ limit?: number;
+ offset?: number;
+ /**
+ * Attributes to order by, multi criteria sort is supported. Prefix with
`-` for descending order. Supported attributes: `id, created_at, name, interval`
+ */
+ orderBy?: Array<(string)>;
+};
+
+export type GetDagDeadlineAlertsResponse = DeadlineAlertCollectionResponse;
export type StructureDataData = {
dagId: string;
@@ -6870,12 +6916,35 @@ export type $OpenApiTs = {
};
'/ui/dags/{dag_id}/dagRuns/{dag_run_id}/deadlines': {
get: {
- req: GetDagRunDeadlinesData;
+ req: GetDeadlinesData;
res: {
/**
* Successful Response
*/
200: DeadlineCollectionResponse;
+ /**
+ * Bad Request
+ */
+ 400: HTTPExceptionResponse;
+ /**
+ * Not Found
+ */
+ 404: HTTPExceptionResponse;
+ /**
+ * Validation Error
+ */
+ 422: HTTPValidationError;
+ };
+ };
+ };
+ '/ui/dags/{dag_id}/deadlineAlerts': {
+ get: {
+ req: GetDagDeadlineAlertsData;
+ res: {
+ /**
+ * Successful Response
+ */
+ 200: DeadlineAlertCollectionResponse;
/**
* Not Found
*/
diff --git
a/airflow-core/tests/unit/api_fastapi/core_api/routes/ui/test_deadlines.py
b/airflow-core/tests/unit/api_fastapi/core_api/routes/ui/test_deadlines.py
index 4dec594eb64..52c61514398 100644
--- a/airflow-core/tests/unit/api_fastapi/core_api/routes/ui/test_deadlines.py
+++ b/airflow-core/tests/unit/api_fastapi/core_api/routes/ui/test_deadlines.py
@@ -42,6 +42,7 @@ from tests_common.test_utils.db import (
pytestmark = pytest.mark.db_test
DAG_ID = "test_deadlines_dag"
+DAG_ID_2 = "test_deadlines_dag_2"
# Each run represents a different deadline scenario tested below.
RUN_EMPTY = "run_empty" # no deadlines
@@ -50,6 +51,7 @@ RUN_MISSED = "run_missed" # 1 deadline, missed=True
RUN_ALERT = "run_alert" # 1 deadline linked to a DeadlineAlert
RUN_MULTI = "run_multi" # 3 deadlines added out-of-order (ordering test)
RUN_OTHER = "run_other" # has 1 deadline; used to verify per-run isolation
+RUN_DAG2 = "run_dag2" # belongs to DAG_ID_2, which is used for cross-dag
filter tests
ALERT_NAME = "SLA Breach Alert"
ALERT_DESCRIPTION = "Fires when SLA is breached"
@@ -195,6 +197,28 @@ def setup(dag_maker, session):
)
)
+ # Second DAG with two deadlines (for cross-DAG filter verification)
+ with dag_maker(DAG_ID_2, serialized=True, session=session):
+ EmptyOperator(task_id="task")
+
+ run_dag2 = dag_maker.create_dagrun(
+ run_id=RUN_DAG2,
+ state=DagRunState.SUCCESS,
+ run_type=DagRunType.SCHEDULED,
+ logical_date=timezone.datetime(2024, 11, 7),
+ triggered_by=DagRunTriggeredByType.TEST,
+ )
+ # Two non-missed deadlines in Jan 2025 (avoids disturbing deadline_time
filter tests)
+ for dl_time in [timezone.datetime(2025, 1, 10), timezone.datetime(2025, 1,
20)]:
+ session.add(
+ Deadline(
+ deadline_time=dl_time,
+ callback=_cb(),
+ dagrun_id=run_dag2.id,
+ deadline_alert_id=None,
+ )
+ )
+
dag_maker.sync_dagbag_to_db()
session.commit()
yield
@@ -208,10 +232,6 @@ def setup(dag_maker, session):
class TestGetDagRunDeadlines:
"""Tests for GET /dags/{dag_id}/dagRuns/{dag_run_id}/deadlines."""
- # ------------------------------------------------------------------
- # 200 – happy paths
- # ------------------------------------------------------------------
-
def test_no_deadlines_returns_empty_list(self, test_client):
response =
test_client.get(f"/dags/{DAG_ID}/dagRuns/{RUN_EMPTY}/deadlines")
assert response.status_code == 200
@@ -227,6 +247,8 @@ class TestGetDagRunDeadlines:
assert deadline1["missed"] is False
assert deadline1["alert_name"] is None
assert deadline1["alert_description"] is None
+ assert deadline1["dag_id"] == DAG_ID
+ assert deadline1["dag_run_id"] == RUN_SINGLE
assert "id" in deadline1
assert "created_at" in deadline1
@@ -283,10 +305,6 @@ class TestGetDagRunDeadlines:
assert response.status_code == 200
assert response.json()["total_entries"] == 1
- # ------------------------------------------------------------------
- # 404
- # ------------------------------------------------------------------
-
@pytest.mark.parametrize(
("dag_id", "run_id"),
[
@@ -299,10 +317,6 @@ class TestGetDagRunDeadlines:
response =
test_client.get(f"/dags/{dag_id}/dagRuns/{run_id}/deadlines")
assert response.status_code == 404
- # ------------------------------------------------------------------
- # 401 / 403
- # ------------------------------------------------------------------
-
def test_should_response_401(self, unauthenticated_test_client):
response =
unauthenticated_test_client.get(f"/dags/{DAG_ID}/dagRuns/{RUN_EMPTY}/deadlines")
assert response.status_code == 401
@@ -310,3 +324,190 @@ class TestGetDagRunDeadlines:
def test_should_response_403(self, unauthorized_test_client):
response =
unauthorized_test_client.get(f"/dags/{DAG_ID}/dagRuns/{RUN_EMPTY}/deadlines")
assert response.status_code == 403
+
+
+class TestGetDeadlines:
+ """Tests for GET /dags/{dag_id}/dagRuns/{dag_run_id}/deadlines with ~
wildcards."""
+
+ def test_returns_all_deadlines(self, test_client):
+ """All deadlines across all DAGs and runs are returned"""
+ response = test_client.get("/dags/~/dagRuns/~/deadlines")
+ assert response.status_code == 200
+ data = response.json()
+ # DAG_ID: 7 deadlines (run_single, run_missed, run_alert, 3×run_multi,
run_other)
+ # DAG_ID_2: 2 deadlines (run_dag2)
+ assert data["total_entries"] == 9
+ assert len(data["deadlines"]) == 9
+ assert {dl["dag_id"] for dl in data["deadlines"]} == {DAG_ID, DAG_ID_2}
+ for dl in data["deadlines"]:
+ assert "id" in dl
+ assert "dag_run_id" in dl
+ assert "deadline_time" in dl
+ assert "missed" in dl
+
+ def test_filter_by_dag_id(self, test_client):
+ """Specifying a dag_id returns only that DAG's deadlines, not other
DAGs'."""
+ response = test_client.get(f"/dags/{DAG_ID}/dagRuns/~/deadlines")
+ assert response.status_code == 200
+ data = response.json()
+ assert data["total_entries"] == 7
+ for dl in data["deadlines"]:
+ assert dl["dag_id"] == DAG_ID
+
+ # Cross-check: the second DAG's deadlines are isolated
+ dag2_response =
test_client.get(f"/dags/{DAG_ID_2}/dagRuns/~/deadlines")
+ assert dag2_response.json()["total_entries"] == 2
+ for dl in dag2_response.json()["deadlines"]:
+ assert dl["dag_id"] == DAG_ID_2
+
+ def test_filter_missed_true(self, test_client):
+ """Only missed deadlines are returned when missed=true."""
+ response = test_client.get("/dags/~/dagRuns/~/deadlines",
params={"missed": "true"})
+ assert response.status_code == 200
+ data = response.json()
+ assert data["total_entries"] == 1
+ assert data["deadlines"][0]["missed"] is True
+
+ def test_filter_missed_false(self, test_client):
+ """Only non-missed (pending) deadlines are returned when
missed=false."""
+ response = test_client.get("/dags/~/dagRuns/~/deadlines",
params={"missed": "false"})
+ assert response.status_code == 200
+ data = response.json()
+ # DAG_ID non-missed: 6; DAG_ID_2 non-missed: 2
+ assert data["total_entries"] == 8
+ for dl in data["deadlines"]:
+ assert dl["missed"] is False
+
+ def test_filter_deadline_time_gte(self, test_client):
+ """deadline_time_gte filters out deadlines before the given time."""
+ response = test_client.get(
+ "/dags/~/dagRuns/~/deadlines", params={"deadline_time_gte":
"2025-02-01T00:00:00Z"}
+ )
+ assert response.status_code == 200
+ data = response.json()
+ # Deadline times at/after 2025-02-01: run_multi 2025-02-01,
2025-03-01, run_other 2025-06-01 = 3
+ assert data["total_entries"] == 3
+
+ def test_filter_deadline_time_lte(self, test_client):
+ """deadline_time_lte filters out deadlines after the given time."""
+ response = test_client.get(
+ "/dags/~/dagRuns/~/deadlines", params={"deadline_time_lte":
"2024-12-31T23:59:59Z"}
+ )
+ assert response.status_code == 200
+ data = response.json()
+ # Only run_missed's 2024-12-01 is before 2025
+ assert data["total_entries"] == 1
+
+ def test_filter_last_updated_at_gte(self, test_client):
+ """last_updated_at_gte filters deadlines updated before the given
time."""
+ response = test_client.get(
+ "/dags/~/dagRuns/~/deadlines", params={"last_updated_at_gte":
"2099-01-01T00:00:00Z"}
+ )
+ assert response.status_code == 200
+ assert response.json()["total_entries"] == 0
+
+ def test_filter_last_updated_at_lte(self, test_client):
+ """last_updated_at_lte filters deadlines updated after the given
time."""
+ response = test_client.get(
+ "/dags/~/dagRuns/~/deadlines", params={"last_updated_at_lte":
"2099-01-01T00:00:00Z"}
+ )
+ assert response.status_code == 200
+ assert response.json()["total_entries"] == 9
+
+ def test_ordered_by_deadline_time_ascending_by_default(self, test_client):
+ """Deadlines are ordered by deadline_time ascending by default."""
+ response = test_client.get("/dags/~/dagRuns/~/deadlines")
+ assert response.status_code == 200
+ times = [dl["deadline_time"] for dl in response.json()["deadlines"]]
+ assert times == sorted(times)
+
+ def test_pagination(self, test_client):
+ """limit and offset work correctly."""
+ all_resp = test_client.get("/dags/~/dagRuns/~/deadlines")
+ all_ids = [dl["id"] for dl in all_resp.json()["deadlines"]]
+
+ page1 = test_client.get("/dags/~/dagRuns/~/deadlines",
params={"limit": 3, "offset": 0}).json()[
+ "deadlines"
+ ]
+ page2 = test_client.get("/dags/~/dagRuns/~/deadlines",
params={"limit": 3, "offset": 3}).json()[
+ "deadlines"
+ ]
+
+ assert [dl["id"] for dl in page1] == all_ids[:3]
+ assert [dl["id"] for dl in page2] == all_ids[3:6]
+
+ def test_alert_name_present_when_linked(self, test_client):
+ """Deadlines linked to a DeadlineAlert include alert_name and
alert_description."""
+ response = test_client.get(f"/dags/{DAG_ID}/dagRuns/~/deadlines")
+ assert response.status_code == 200
+ deadlines = response.json()["deadlines"]
+ alerts = [dl for dl in deadlines if dl["alert_name"] is not None]
+ assert len(alerts) == 1
+ assert alerts[0]["alert_name"] == ALERT_NAME
+ assert alerts[0]["alert_description"] == ALERT_DESCRIPTION
+
+ def test_filter_nonexistent_dag_returns_empty(self, test_client):
+ """Filtering by a dag_id that doesn't exist returns an empty list."""
+ response = test_client.get("/dags/nonexistent_dag/dagRuns/~/deadlines")
+ assert response.status_code == 200
+ assert response.json() == {"deadlines": [], "total_entries": 0}
+
+ def test_dag_run_id_without_dag_id_returns_400(self, test_client):
+ """Specifying a concrete dag_run_id with dag_id=~ is a bad request."""
+ response = test_client.get(f"/dags/~/dagRuns/{RUN_SINGLE}/deadlines")
+ assert response.status_code == 400
+
+ def test_should_response_401(self, unauthenticated_test_client):
+ response =
unauthenticated_test_client.get("/dags/~/dagRuns/~/deadlines")
+ assert response.status_code == 401
+
+ def test_should_response_403(self, unauthorized_test_client):
+ response = unauthorized_test_client.get("/dags/~/dagRuns/~/deadlines")
+ assert response.status_code == 403
+
+
+class TestGetDagDeadlineAlerts:
+ """Tests for GET /dags/{dag_id}/deadlineAlerts."""
+
+ def test_returns_deadline_alerts_for_dag(self, test_client):
+ """Returns all deadline alerts defined on the DAG."""
+ response = test_client.get(f"/dags/{DAG_ID}/deadlineAlerts")
+ assert response.status_code == 200
+ data = response.json()
+ assert data["total_entries"] == 1
+ assert len(data["deadline_alerts"]) == 1
+
+ def test_alert_response_fields(self, test_client):
+ """Alert response includes expected fields with correct values."""
+ response = test_client.get(f"/dags/{DAG_ID}/deadlineAlerts")
+ assert response.status_code == 200
+ alert = response.json()["deadline_alerts"][0]
+ assert alert["name"] == ALERT_NAME
+ assert alert["description"] == ALERT_DESCRIPTION
+ assert alert["interval"] == 3600.0
+ assert alert["reference_type"] == "DagRunQueuedAtDeadline"
+ assert "id" in alert
+ assert "created_at" in alert
+
+ def test_dag_with_no_alerts_returns_empty_list(self, test_client,
dag_maker, session):
+ """A DAG with no deadline alerts returns an empty list."""
+ with dag_maker("dag_no_alerts", serialized=True, session=session):
+ EmptyOperator(task_id="task")
+ dag_maker.sync_dagbag_to_db()
+ session.commit()
+
+ response = test_client.get("/dags/dag_no_alerts/deadlineAlerts")
+ assert response.status_code == 200
+ assert response.json() == {"deadline_alerts": [], "total_entries": 0}
+
+ def test_should_response_404_for_nonexistent_dag(self, test_client):
+ response = test_client.get("/dags/nonexistent_dag/deadlineAlerts")
+ assert response.status_code == 404
+
+ def test_should_response_401(self, unauthenticated_test_client):
+ response =
unauthenticated_test_client.get(f"/dags/{DAG_ID}/deadlineAlerts")
+ assert response.status_code == 401
+
+ def test_should_response_403(self, unauthorized_test_client):
+ response =
unauthorized_test_client.get(f"/dags/{DAG_ID}/deadlineAlerts")
+ assert response.status_code == 403