mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix: display build timings when all timings are loaded (#15728)
- [Refetch timings until script timings are present](https://github.com/coder/coder/commit/2181bec72b5334e5e15dc575d2234860be02920b) - [Stay on loading state when agent script timings are empty](https://github.com/coder/coder/commit/b16fad165c8733c60150b0dfce5df73ab2669e36) Fix https://github.com/coder/coder/issues/15273
This commit is contained in:
@@ -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),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -58,15 +58,25 @@ export const WorkspaceTimings: FC<WorkspaceTimingsProps> = ({
|
||||
].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
|
||||
const [isOpen, setIsOpen] = useState(defaultIsOpen);
|
||||
|
||||
// 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<WorkspaceTimingsProps> = ({
|
||||
: 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
|
||||
|
||||
@@ -157,13 +157,27 @@ export const WorkspaceReadyPage: FC<WorkspaceReadyPageProps> = ({
|
||||
// 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 = (
|
||||
|
||||
Reference in New Issue
Block a user