Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions airflow-core/docs/ui.rst
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,22 @@ The **Events** tab surfaces structured events related to the Dag, such as Dag tr
.. image:: img/ui-light/dag_overview_events.png
:alt: Dag Events Tab (Light Mode)

Backfills Tab
''''''''

The **Backfills** tab displays historical backfill jobs for a specific DAG, including their date ranges, reprocessing behavior, and execution status.

.. image:: img/ui-dark/dag_overview_backfills.png
:alt: Dag Backfills Tab (Dark Mode)

|

.. image:: img/ui-light/dag_overview_backfills.png
:alt: Dag Overview Tab (Light Mode)

|


Code Tab
''''''''

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1102,6 +1102,190 @@ paths:
minimum: 0
default: 0
title: Offset
- name: from_date_gte
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
title: From Date Gte
- name: from_date_gt
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
title: From Date Gt
- name: from_date_lte
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
title: From Date Lte
- name: from_date_lt
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
title: From Date Lt
- name: to_date_gte
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
title: To Date Gte
- name: to_date_gt
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
title: To Date Gt
- name: to_date_lte
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
title: To Date Lte
- name: to_date_lt
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
title: To Date Lt
- name: created_at_gte
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
title: Created At Gte
- name: created_at_gt
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
title: Created At Gt
- name: created_at_lte
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
title: Created At Lte
- name: created_at_lt
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
title: Created At Lt
- name: completed_at_gte
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
title: Completed At Gte
- name: completed_at_gt
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
title: Completed At Gt
- name: completed_at_lte
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
title: Completed At Lte
- name: completed_at_lt
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
title: Completed At Lt
- name: max_active_runs_gte
in: query
required: false
schema:
anyOf:
- type: number
- type: 'null'
title: Max Active Runs Gte
- name: max_active_runs_gt
in: query
required: false
schema:
anyOf:
- type: number
- type: 'null'
title: Max Active Runs Gt
- name: max_active_runs_lte
in: query
required: false
schema:
anyOf:
- type: number
- type: 'null'
title: Max Active Runs Lte
- name: max_active_runs_lt
in: query
required: false
schema:
anyOf:
- type: number
- type: 'null'
title: Max Active Runs Lt
- name: reprocess_behavior
in: query
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: Reprocess Behavior
- name: order_by
in: query
required: false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
# under the License.
from __future__ import annotations

import logging
from typing import Annotated

from fastapi import Depends, status
Expand All @@ -28,8 +29,11 @@
FilterParam,
QueryLimit,
QueryOffset,
RangeFilter,
SortParam,
datetime_range_filter_factory,
filter_param_factory,
float_range_filter_factory,
)
from airflow.api_fastapi.common.router import AirflowRouter
from airflow.api_fastapi.core_api.datamodels.backfills import BackfillCollectionResponse, BackfillResponse
Expand All @@ -39,6 +43,8 @@
from airflow.api_fastapi.core_api.security import ReadableBackfillsFilterDep, requires_access_backfill
from airflow.models.backfill import Backfill

log = logging.getLogger(__name__)

backfills_router = AirflowRouter(tags=["Backfill"], prefix="/backfills")


Expand All @@ -52,6 +58,14 @@
def list_backfills_ui(
limit: QueryLimit,
offset: QueryOffset,
start_date_range: Annotated[RangeFilter, Depends(datetime_range_filter_factory("from_date", Backfill))],

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • start_date/end_date are exposed as public filter names, but Backfill has no columns
    with those literal names. The underlying columns are from_date/to_date.
  • Used
    datetime_range_filter_factory's attribute_name argument to map the public-facing name to
    the real column, so the API surface matches what DagRun already exposes without renaming
    Backfill's columns.

end_date_range: Annotated[RangeFilter, Depends(datetime_range_filter_factory("to_date", Backfill))],
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(float_range_filter_factory("max_active_runs", Backfill))],

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

max_active_runs is implemented as a RangeFilter (via float_range_filter_factory) rather
than an exact-match FilterParam, since the issue frames it as diagnosing throttling
("more/fewer than N active runs"), which a range serves better than exact equality.

reprocess_behavior: Annotated[
FilterParam, Depends(filter_param_factory(Backfill.reprocess_behavior, str | None))
],
order_by: Annotated[
SortParam,
Depends(SortParam(["id"], Backfill).dynamic_depends()),
Expand All @@ -66,7 +80,17 @@ def list_backfills_ui(
) -> BackfillCollectionResponse:
select_stmt, total_entries = paginated_select(
statement=select(Backfill).options(joinedload(Backfill.dag_model)),
filters=[dag_id, active, readable_backfills_filter],
filters=[
dag_id,
active,
readable_backfills_filter,
start_date_range,
end_date_range,
created_at,
completed_at,
max_active_runs,
reprocess_behavior,
],
order_by=order_by,
offset=offset,
limit=limit,
Expand All @@ -76,6 +100,7 @@ def list_backfills_ui(
BackfillResponse(**row._mapping) if not isinstance(row, Backfill) else row
for row in session.scalars(select_stmt)
]
log.warning("inside backfill*******************************************")
return BackfillCollectionResponse(
backfills=backfills,
total_entries=total_entries,
Expand Down
25 changes: 23 additions & 2 deletions airflow-core/src/airflow/ui/openapi-gen/queries/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,34 @@ 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, dagId, limit, offset, orderBy }: {
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 }: {
active?: boolean;
completedAtGt?: string;
completedAtGte?: string;
completedAtLt?: string;
completedAtLte?: string;
createdAtGt?: string;
createdAtGte?: string;
createdAtLt?: string;
createdAtLte?: string;
dagId?: string;
fromDateGt?: string;
fromDateGte?: string;
fromDateLt?: string;
fromDateLte?: string;
limit?: number;
maxActiveRunsGt?: number;
maxActiveRunsGte?: number;
maxActiveRunsLt?: number;
maxActiveRunsLte?: number;
offset?: number;
orderBy?: string[];
} = {}, queryKey?: Array<unknown>) => [useBackfillServiceListBackfillsUiKey, ...(queryKey ?? [{ active, dagId, limit, offset, orderBy }])];
reprocessBehavior?: string;
toDateGt?: string;
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 }])];
export type ConnectionServiceGetConnectionDefaultResponse = Awaited<ReturnType<typeof ConnectionService.getConnection>>;
export type ConnectionServiceGetConnectionQueryResult<TData = ConnectionServiceGetConnectionDefaultResponse, TError = unknown> = UseQueryResult<TData, TError>;
export const useConnectionServiceGetConnectionKey = "ConnectionServiceGetConnection";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,19 +224,61 @@ export const ensureUseBackfillServiceListBackfillDagRunsData = (queryClient: Que
* @param data The data for the request.
* @param data.limit
* @param data.offset
* @param data.fromDateGte
* @param data.fromDateGt
* @param data.fromDateLte
* @param data.fromDateLt
* @param data.toDateGte
* @param data.toDateGt
* @param data.toDateLte
* @param data.toDateLt
* @param data.createdAtGte
* @param data.createdAtGt
* @param data.createdAtLte
* @param data.createdAtLt
* @param data.completedAtGte
* @param data.completedAtGt
* @param data.completedAtLte
* @param data.completedAtLt
* @param data.maxActiveRunsGte
* @param data.maxActiveRunsGt
* @param data.maxActiveRunsLte
* @param data.maxActiveRunsLt
* @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
* @param data.active
* @returns BackfillCollectionResponse Successful Response
* @throws ApiError
*/
export const ensureUseBackfillServiceListBackfillsUiData = (queryClient: QueryClient, { active, dagId, limit, offset, orderBy }: {
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 }: {
active?: boolean;
completedAtGt?: string;
completedAtGte?: string;
completedAtLt?: string;
completedAtLte?: string;
createdAtGt?: string;
createdAtGte?: string;
createdAtLt?: string;
createdAtLte?: string;
dagId?: string;
fromDateGt?: string;
fromDateGte?: string;
fromDateLt?: string;
fromDateLte?: string;
limit?: number;
maxActiveRunsGt?: number;
maxActiveRunsGte?: number;
maxActiveRunsLt?: number;
maxActiveRunsLte?: number;
offset?: number;
orderBy?: string[];
} = {}) => queryClient.ensureQueryData({ queryKey: Common.UseBackfillServiceListBackfillsUiKeyFn({ active, dagId, limit, offset, orderBy }), queryFn: () => BackfillService.listBackfillsUi({ active, dagId, limit, offset, orderBy }) });
reprocessBehavior?: string;
toDateGt?: string;
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({ 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 }) });
/**
* Get Connection
* Get a connection entry.
Expand Down
Loading