Skip to content
Merged
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
15 changes: 10 additions & 5 deletions airflow-core/src/airflow/ui/src/layouts/Details/Grid/Grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { Box, Flex } from "@chakra-ui/react";
import { useVirtualizer } from "@tanstack/react-virtual";
import dayjs from "dayjs";
import dayjsDuration from "dayjs/plugin/duration";
import { useRef } from "react";
import { useCallback, useMemo, useRef } from "react";
import type { RefObject } from "react";
import { useParams, useSearchParams } from "react-router-dom";

Expand Down Expand Up @@ -141,7 +141,12 @@ export const Grid = ({
showVersionIndicatorMode,
});

const { flatNodes } = flattenNodes(dagStructure, openGroupIds);
// React Compiler skips optimizing this whole component: `useVirtualizer` (@tanstack/react-virtual) is
// on the compiler's known-incompatible list — its return value exposes functions that can't be
// memoized safely — so it declines to memoize anything in Grid. Without the manual memoization here
// and on the click handlers below, `flatNodes` and the handlers get fresh references every render, so
// each TI-summaries stream line re-renders every column instead of only the run whose summary changed.
const { flatNodes } = useMemo(() => flattenNodes(dagStructure, openGroupIds), [dagStructure, openGroupIds]);

const taskNameColumnWidthPx = showGantt ? estimateTaskNameColumnWidthPx(flatNodes) : undefined;

Expand All @@ -166,9 +171,9 @@ export const Grid = ({
tasks: flatNodes,
});

const handleRowClick = () => setMode(NavigationModes.TASK);
const handleCellClick = () => setMode(NavigationModes.TI);
const handleColumnClick = () => setMode(NavigationModes.RUN);
const handleRowClick = useCallback(() => setMode(NavigationModes.TASK), [setMode]);
const handleCellClick = useCallback(() => setMode(NavigationModes.TI), [setMode]);
const handleColumnClick = useCallback(() => setMode(NavigationModes.RUN), [setMode]);

const rowVirtualizer = useVirtualizer({
count: flatNodes.length,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,10 @@ export const useGridTiSummariesStream = ({
return undefined;
}

// Kick off an immediate refresh so the stream doesn't have to wait for the first interval to elapse.
setRefreshTick((tick) => tick + 1);
// The stream already fetches on mount and whenever runIdsKey changes, so there is no first-interval
// wait to avoid. Bumping refreshTick here would abort that just-opened mount stream and immediately
// reopen it — a redundant connection plus an AbortError on every grid mount — so let the interval be
// the only re-stream trigger.
const timer = setInterval(() => {
setRefreshTick((tick) => tick + 1);
}, baseRefetchInterval);
Expand Down