This is an automated email from the ASF dual-hosted git repository.

vatsrahul1001 pushed a commit to branch v3-3-test
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/v3-3-test by this push:
     new 67f94944f2d Respect the limit search param in the task overview 
duration chart (#72147) (#72357)
67f94944f2d is described below

commit 67f94944f2df9ea2c4124938ca7b86e3f0214402
Author: warreee <[email protected]>
AuthorDate: Mon Sep 7 09:03:21 2026 +0200

    Respect the limit search param in the task overview duration chart (#72147) 
(#72357)
    
    The duration chart on the task overview always requested the last 14 task
    instances, ignoring the number of dag runs the user picked. The dag details
    layout already writes that choice to the limit search param, and the dag
    overview page reads a value of its own, so the task page was the only view
    that could not be widened.
    
    Read the same limit search param the details layout writes, falling back to
    the same default of 10, so the chart follows the selector and can be shared
    through the URL.
    
    The remaining limit on the failed task instance query is left alone: that
    query only reads total_entries and never renders the rows it fetches.
    
    (cherry picked from commit 4dae472e41a619e529f26885d596b9d03416776a)
---
 .../ui/src/pages/Task/Overview/Overview.test.tsx   | 80 ++++++++++++++++++++++
 .../ui/src/pages/Task/Overview/Overview.tsx        |  7 +-
 2 files changed, 85 insertions(+), 2 deletions(-)

diff --git 
a/airflow-core/src/airflow/ui/src/pages/Task/Overview/Overview.test.tsx 
b/airflow-core/src/airflow/ui/src/pages/Task/Overview/Overview.test.tsx
new file mode 100644
index 00000000000..62b5345c7e7
--- /dev/null
+++ b/airflow-core/src/airflow/ui/src/pages/Task/Overview/Overview.test.tsx
@@ -0,0 +1,80 @@
+/*!
+ * 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 "@testing-library/jest-dom";
+import { render } from "@testing-library/react";
+import type { PropsWithChildren } from "react";
+import { MemoryRouter } from "react-router-dom";
+import { beforeEach, describe, expect, it, vi } from "vitest";
+
+import { BaseWrapper } from "src/utils/Wrapper";
+
+import { Overview } from "./Overview";
+
+const { mockUseTaskInstanceServiceGetTaskInstances } = vi.hoisted(() => ({
+  mockUseTaskInstanceServiceGetTaskInstances: vi.fn(() => ({
+    data: { task_instances: [], total_entries: 0 },
+    isLoading: false,
+  })),
+}));
+
+const wrapperWithSearch = (search: string) => {
+  const RouterWrapper = ({ children }: PropsWithChildren) => (
+    <BaseWrapper>
+      <MemoryRouter 
initialEntries={[`/dags/my_dag/tasks/my_task${search}`]}>{children}</MemoryRouter>
+    </BaseWrapper>
+  );
+
+  return RouterWrapper;
+};
+
+vi.mock("openapi/queries", () => ({
+  useTaskInstanceServiceGetTaskInstances: 
mockUseTaskInstanceServiceGetTaskInstances,
+}));
+
+vi.mock("src/components/DurationChart", () => ({ DurationChart: () => null }));
+vi.mock("src/components/NeedsReviewButton", () => ({ NeedsReviewButton: () => 
null }));
+vi.mock("src/components/TimeRangeSelector", () => ({ default: () => null }));
+vi.mock("src/components/TrendCountButton", () => ({ TrendCountButton: () => 
null }));
+vi.mock("src/utils", () => ({ isStatePending: () => false, useAutoRefresh: () 
=> false }));
+
+describe("Task overview duration chart limit", () => {
+  beforeEach(() => {
+    mockUseTaskInstanceServiceGetTaskInstances.mockClear();
+  });
+
+  it("requests the default number of task instances when no limit is set", () 
=> {
+    render(<Overview />, { wrapper: wrapperWithSearch("") });
+
+    expect(mockUseTaskInstanceServiceGetTaskInstances).toHaveBeenCalledWith(
+      expect.objectContaining({ limit: 10, orderBy: ["-run_after"] }),
+      undefined,
+      expect.anything(),
+    );
+  });
+
+  it("requests the number of task instances given by the limit search param", 
() => {
+    render(<Overview />, { wrapper: wrapperWithSearch("?limit=50") });
+
+    expect(mockUseTaskInstanceServiceGetTaskInstances).toHaveBeenCalledWith(
+      expect.objectContaining({ limit: 50, orderBy: ["-run_after"] }),
+      undefined,
+      expect.anything(),
+    );
+  });
+});
diff --git a/airflow-core/src/airflow/ui/src/pages/Task/Overview/Overview.tsx 
b/airflow-core/src/airflow/ui/src/pages/Task/Overview/Overview.tsx
index f48bd9e26cf..60645136d88 100644
--- a/airflow-core/src/airflow/ui/src/pages/Task/Overview/Overview.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Task/Overview/Overview.tsx
@@ -20,7 +20,7 @@ import { Box, HStack, Skeleton } from "@chakra-ui/react";
 import dayjs from "dayjs";
 import { useState } from "react";
 import { useTranslation } from "react-i18next";
-import { useParams } from "react-router-dom";
+import { useParams, useSearchParams } from "react-router-dom";
 
 import { useTaskInstanceServiceGetTaskInstances } from "openapi/queries";
 import { DurationChart } from "src/components/DurationChart";
@@ -36,6 +36,9 @@ export const Overview = () => {
   const { dagId = "", groupId, taskId } = useParams();
   const { t: translate } = useTranslation("dag");
 
+  const [searchParams] = useSearchParams();
+  const limit = Number(searchParams.get(SearchParamsKeys.LIMIT) ?? "10");
+
   const now = dayjs();
   const [startDate, setStartDate] = useState(now.subtract(Number(defaultHour), 
"hour").toISOString());
   const [endDate, setEndDate] = useState(now.toISOString());
@@ -60,7 +63,7 @@ export const Overview = () => {
     {
       dagId,
       dagRunId: "~",
-      limit: 14,
+      limit,
       orderBy: ["-run_after"],
       taskGroupId: groupId ?? undefined,
       taskId: Boolean(groupId) ? undefined : taskId,

Reply via email to