This is an automated email from the ASF dual-hosted git repository.
bbovenzi pushed a commit to branch v3-4-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/v3-4-test by this push:
new 65515bde8e0 [v3-4-test] UI: Fix slow pending Dag run checks on large
databases (#75674) (#75799)
65515bde8e0 is described below
commit 65515bde8e0b7efa471ca820c6e84e2a29edf258
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Tue Oct 27 17:03:34 2026 +0000
[v3-4-test] UI: Fix slow pending Dag run checks on large databases (#75674)
(#75799)
(cherry picked from commit 91ca0ac42c80deb9798dbfd637e7702d2f8a2c47)
Co-authored-by: Yuseok Jo <[email protected]>
---
.../src/airflow/ui/src/utils/query.test.ts | 50 ++++++++++++++++++++++
airflow-core/src/airflow/ui/src/utils/query.ts | 7 +--
2 files changed, 54 insertions(+), 3 deletions(-)
diff --git a/airflow-core/src/airflow/ui/src/utils/query.test.ts
b/airflow-core/src/airflow/ui/src/utils/query.test.ts
new file mode 100644
index 00000000000..ba72d50aa52
--- /dev/null
+++ b/airflow-core/src/airflow/ui/src/utils/query.test.ts
@@ -0,0 +1,50 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { renderHook, waitFor } from "@testing-library/react";
+import { http, HttpResponse } from "msw";
+import { expect, it } from "vitest";
+
+import { server } from "src/mocks/server";
+import { Wrapper } from "src/utils/Wrapper";
+import { useAutoRefresh } from "src/utils/query";
+
+it("refreshes when pending runs exist without fetching any of them", async ()
=> {
+ const autoRefreshInterval = 5;
+ const pendingRuns = [{ dag_run_id: "running_run" }, { dag_run_id:
"queued_run" }];
+ const requestedLimits: Array<string | null> = [];
+
+ server.use(
+ http.get("/ui/config", () => HttpResponse.json({ auto_refresh_interval:
autoRefreshInterval })),
+ http.get("/api/v2/dags/~/dagRuns", ({ request }) => {
+ const limit = new URL(request.url).searchParams.get("limit");
+
+ requestedLimits.push(limit);
+
+ return HttpResponse.json({
+ dag_runs: pendingRuns.slice(0, Number(limit)),
+ total_entries: pendingRuns.length,
+ });
+ }),
+ );
+
+ const { result } = renderHook(() => useAutoRefresh({ checkPendingRuns: true
}), { wrapper: Wrapper });
+
+ await waitFor(() => expect(result.current).toBe(autoRefreshInterval * 1000));
+ expect(new Set(requestedLimits)).toEqual(new Set(["0"]));
+});
diff --git a/airflow-core/src/airflow/ui/src/utils/query.ts
b/airflow-core/src/airflow/ui/src/utils/query.ts
index f364fcab0de..4dced5b1cd5 100644
--- a/airflow-core/src/airflow/ui/src/utils/query.ts
+++ b/airflow-core/src/airflow/ui/src/utils/query.ts
@@ -52,7 +52,8 @@ export const useAutoRefresh = ({
const { data: dagRunData } = useDagRunServiceGetDagRuns(
{
dagId: dagId ?? "~",
- limit: 1,
+ // Only the count is needed. Fetching a row can make Postgres scan
dag_run from its oldest run.
+ limit: 0,
state: ["running", "queued"],
},
undefined,
@@ -61,13 +62,13 @@ export const useAutoRefresh = ({
enabled: checkPendingRuns,
refetchInterval: (query) =>
autoRefreshInterval !== undefined &&
- ((query.state.data?.dag_runs ?? []).length > 0
+ ((query.state.data?.total_entries ?? 0) > 0
? autoRefreshInterval * 1000
: autoRefreshInterval * 10 * 1000),
},
);
- const pendingRuns = !checkPendingRuns || (dagRunData?.dag_runs ?? []).length
>= 1;
+ const pendingRuns = !checkPendingRuns || (dagRunData?.total_entries ?? 0) >
0;
const paused = Boolean(dagId) && dag?.is_paused;