From 170842260d4d6d21da619449164aff6d5b0f286b Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Wed, 2 Jul 2025 18:30:18 +0100 Subject: [PATCH 1/4] chore(site): reduce fetch interval on workspaces page if there are no pending workspaces --- .../pages/WorkspacesPage/WorkspacesPage.tsx | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/site/src/pages/WorkspacesPage/WorkspacesPage.tsx b/site/src/pages/WorkspacesPage/WorkspacesPage.tsx index 22ba0d15f1f9a..4f7b195cf9f80 100644 --- a/site/src/pages/WorkspacesPage/WorkspacesPage.tsx +++ b/site/src/pages/WorkspacesPage/WorkspacesPage.tsx @@ -78,8 +78,24 @@ const WorkspacesPage: FC = () => { const { data, error, refetch } = useQuery({ ...workspacesQueryOptions, refetchInterval: ({ state }) => { - return state.error ? false : 5_000; + if (state.error) return false; + + // Check if any workspace has an active build + const hasActiveBuilds = state.data?.workspaces?.some((workspace) => { + const status = workspace.latest_build.status; + return [ + "canceling", + "deleting", + "pending", + "starting", + "stopping", + ].includes(status); + }); + + // Poll every 5s if there are active builds, otherwise every 30s + return hasActiveBuilds ? 5_000 : 30_000; }, + refetchIntervalInBackground: false, // Stop polling when tab is inactive }); const [checkedWorkspaces, setCheckedWorkspaces] = useState< From e1b59cb00298b22d4d1bffe0e9f035b7d7101c38 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Thu, 3 Jul 2025 17:55:21 +0100 Subject: [PATCH 2/4] address copilot suggestions --- .../pages/WorkspacesPage/WorkspacesPage.tsx | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/site/src/pages/WorkspacesPage/WorkspacesPage.tsx b/site/src/pages/WorkspacesPage/WorkspacesPage.tsx index 4f7b195cf9f80..a1af6411ba075 100644 --- a/site/src/pages/WorkspacesPage/WorkspacesPage.tsx +++ b/site/src/pages/WorkspacesPage/WorkspacesPage.tsx @@ -2,7 +2,7 @@ import { getErrorDetail, getErrorMessage } from "api/errors"; import { workspacePermissionsByOrganization } from "api/queries/organizations"; import { templates } from "api/queries/templates"; import { workspaces } from "api/queries/workspaces"; -import type { Workspace } from "api/typesGenerated"; +import type { Workspace, WorkspaceStatus } from "api/typesGenerated"; import { useFilter } from "components/Filter/Filter"; import { useUserFilterMenu } from "components/Filter/UserFilter"; import { displayError } from "components/GlobalSnackbar/utils"; @@ -22,6 +22,18 @@ import { WorkspacesPageView } from "./WorkspacesPageView"; import { useBatchActions } from "./batchActions"; import { useStatusFilterMenu, useTemplateFilterMenu } from "./filter/menus"; +// To reduce the number of fetches, we reduce the fetch interval if there are no +// active workspace builds. +const ACTIVE_BUILD_STATUSES: WorkspaceStatus[] = [ + "canceling", + "deleting", + "pending", + "starting", + "stopping", +]; +const ACTIVE_BUILDS_REFRESH_INTERVAL = 5_000; +const NO_ACTIVE_BUILDS_REFRESH_INTERVAL = 30_000; + function useSafeSearchParams() { // Have to wrap setSearchParams because React Router doesn't make sure that // the function's memory reference stays stable on each render, even though @@ -80,20 +92,19 @@ const WorkspacesPage: FC = () => { refetchInterval: ({ state }) => { if (state.error) return false; + // Default to 5s interval until first fetch completes + if (!state.data) return ACTIVE_BUILDS_REFRESH_INTERVAL; + // Check if any workspace has an active build - const hasActiveBuilds = state.data?.workspaces?.some((workspace) => { + const hasActiveBuilds = state.data.workspaces?.some((workspace) => { const status = workspace.latest_build.status; - return [ - "canceling", - "deleting", - "pending", - "starting", - "stopping", - ].includes(status); + return ACTIVE_BUILD_STATUSES.includes(status); }); // Poll every 5s if there are active builds, otherwise every 30s - return hasActiveBuilds ? 5_000 : 30_000; + return hasActiveBuilds + ? ACTIVE_BUILDS_REFRESH_INTERVAL + : NO_ACTIVE_BUILDS_REFRESH_INTERVAL; }, refetchIntervalInBackground: false, // Stop polling when tab is inactive }); From 641d001289ef62b40d5a1401a0669087cd49b71c Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Tue, 8 Jul 2025 09:03:07 +0100 Subject: [PATCH 3/4] fixup! address copilot suggestions --- site/src/pages/WorkspacesPage/WorkspacesPage.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/site/src/pages/WorkspacesPage/WorkspacesPage.tsx b/site/src/pages/WorkspacesPage/WorkspacesPage.tsx index a1af6411ba075..36b3ecb51f13c 100644 --- a/site/src/pages/WorkspacesPage/WorkspacesPage.tsx +++ b/site/src/pages/WorkspacesPage/WorkspacesPage.tsx @@ -106,7 +106,6 @@ const WorkspacesPage: FC = () => { ? ACTIVE_BUILDS_REFRESH_INTERVAL : NO_ACTIVE_BUILDS_REFRESH_INTERVAL; }, - refetchIntervalInBackground: false, // Stop polling when tab is inactive }); const [checkedWorkspaces, setCheckedWorkspaces] = useState< From 04f7090dc1941838f2f6f222396eca22deb6fb59 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Tue, 8 Jul 2025 10:50:46 +0100 Subject: [PATCH 4/4] always refetchOnWindowFocus --- site/src/pages/WorkspacesPage/WorkspacesPage.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/site/src/pages/WorkspacesPage/WorkspacesPage.tsx b/site/src/pages/WorkspacesPage/WorkspacesPage.tsx index 36b3ecb51f13c..fa96191501379 100644 --- a/site/src/pages/WorkspacesPage/WorkspacesPage.tsx +++ b/site/src/pages/WorkspacesPage/WorkspacesPage.tsx @@ -106,6 +106,7 @@ const WorkspacesPage: FC = () => { ? ACTIVE_BUILDS_REFRESH_INTERVAL : NO_ACTIVE_BUILDS_REFRESH_INTERVAL; }, + refetchOnWindowFocus: "always", }); const [checkedWorkspaces, setCheckedWorkspaces] = useState<