diff --git a/site/src/api/queries/workspaceBuilds.ts b/site/src/api/queries/workspaceBuilds.ts index 45f7ac3bb7fe6..a537cbed092e3 100644 --- a/site/src/api/queries/workspaceBuilds.ts +++ b/site/src/api/queries/workspaceBuilds.ts @@ -58,17 +58,9 @@ export const infiniteWorkspaceBuilds = ( }; // We use readyAgentsCount to invalidate the query when an agent connects -export const workspaceBuildTimings = ( - workspaceBuildId: string, - readyAgentsCount: number, -) => { +export const workspaceBuildTimings = (workspaceBuildId: string) => { return { - queryKey: [ - "workspaceBuilds", - workspaceBuildId, - "timings", - { readyAgentsCount }, - ], + queryKey: ["workspaceBuilds", workspaceBuildId, "timings"], queryFn: () => API.workspaceBuildTimings(workspaceBuildId), }; }; diff --git a/site/src/modules/workspaces/WorkspaceTiming/WorkspaceTimings.stories.tsx b/site/src/modules/workspaces/WorkspaceTiming/WorkspaceTimings.stories.tsx index 02a544ea9a718..0210353488257 100644 --- a/site/src/modules/workspaces/WorkspaceTiming/WorkspaceTimings.stories.tsx +++ b/site/src/modules/workspaces/WorkspaceTiming/WorkspaceTimings.stories.tsx @@ -118,3 +118,11 @@ export const DuplicatedScriptTiming: Story = { ], }, }; + +// Loading when agent script timings are empty +// Test case for https://github.com/coder/coder/issues/15273 +export const LoadingWhenAgentScriptTimingsAreEmpty: Story = { + args: { + agentScriptTimings: undefined, + }, +}; diff --git a/site/src/modules/workspaces/WorkspaceTiming/WorkspaceTimings.tsx b/site/src/modules/workspaces/WorkspaceTiming/WorkspaceTimings.tsx index 47873f8aaaede..63fc03ad2a3de 100644 --- a/site/src/modules/workspaces/WorkspaceTiming/WorkspaceTimings.tsx +++ b/site/src/modules/workspaces/WorkspaceTiming/WorkspaceTimings.tsx @@ -58,15 +58,25 @@ export const WorkspaceTimings: FC = ({ ].sort((a, b) => { return new Date(a.started_at).getTime() - new Date(b.started_at).getTime(); }); + const [isOpen, setIsOpen] = useState(defaultIsOpen); - const isLoading = timings.length === 0; - // All stages + // If any of the timings are empty, we are still loading the data. They can be + // filled in different moments. + const isLoading = [ + provisionerTimings, + agentScriptTimings, + agentConnectionTimings, + ].some((t) => t.length === 0); + + // Each agent connection timing is a stage in the timeline to make it easier + // to users to see the timing for connection and the other scripts. const agentStageLabels = Array.from( new Set( agentConnectionTimings.map((t) => `agent (${t.workspace_agent_name})`), ), ); + const stages = [ ...provisioningStages, ...agentStageLabels.flatMap((a) => agentStages(a)), @@ -120,7 +130,8 @@ export const WorkspaceTimings: FC = ({ : mergeTimeRanges(stageTimings.map(toTimeRange)); // Prevent users from inspecting internal coder resources in - // provisioner timings. + // provisioner timings because they were not useful to the + // user and would add noise. const visibleResources = stageTimings.filter((t) => { const isProvisionerTiming = "resource" in t; return isProvisionerTiming diff --git a/site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx b/site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx index cdb47f86f508c..62e1b5a6c6dd5 100644 --- a/site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx +++ b/site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx @@ -157,13 +157,27 @@ export const WorkspaceReadyPage: FC = ({ // Cancel build const cancelBuildMutation = useMutation(cancelBuild(workspace, queryClient)); - // Build Timings. Fetch build timings only when the build job is completed. - const readyAgents = workspace.latest_build.resources - .flatMap((r) => r.agents) - .filter((a) => a && a.lifecycle_state !== "starting"); + // Workspace Timings. const timingsQuery = useQuery({ - ...workspaceBuildTimings(workspace.latest_build.id, readyAgents.length), + ...workspaceBuildTimings(workspace.latest_build.id), + + // Fetch build timings only when the build job is completed. enabled: Boolean(workspace.latest_build.job.completed_at), + + // Sometimes, the timings can be fetched before the agent script timings are + // done or saved in the database so we need to conditionally refetch the + // timings. To refetch the timings, I found the best way was to compare the + // expected amount of script timings with the current amount of script + // timings returned in the response. + refetchInterval: (data) => { + const expectedScriptTimingsCount = workspace.latest_build.resources + .flatMap((r) => r.agents) + .flatMap((a) => a?.scripts ?? []).length; + const currentScriptTimingsCount = data?.agent_script_timings?.length ?? 0; + return expectedScriptTimingsCount === currentScriptTimingsCount + ? false + : 1_000; + }, }); const runLastBuild = ( pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy