From e95134a6e0e124090dab56ac68b0bef7f8b9c3e1 Mon Sep 17 00:00:00 2001 From: Presley Date: Mon, 23 May 2022 16:47:55 +0000 Subject: [PATCH 1/4] Make workspace machine ephemeral to limit polling --- site/src/pages/WorkspacePage/WorkspacePage.tsx | 9 ++++----- site/src/xServices/StateContext.tsx | 3 --- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/site/src/pages/WorkspacePage/WorkspacePage.tsx b/site/src/pages/WorkspacePage/WorkspacePage.tsx index cf9c9bb5b95db..7670286a4fd30 100644 --- a/site/src/pages/WorkspacePage/WorkspacePage.tsx +++ b/site/src/pages/WorkspacePage/WorkspacePage.tsx @@ -1,5 +1,5 @@ -import { useActor } from "@xstate/react" -import React, { useContext, useEffect } from "react" +import { useMachine } from "@xstate/react" +import React, { useEffect } from "react" import { useParams } from "react-router-dom" import { ErrorSummary } from "../../components/ErrorSummary/ErrorSummary" import { FullScreenLoader } from "../../components/Loader/FullScreenLoader" @@ -8,14 +8,13 @@ import { Stack } from "../../components/Stack/Stack" import { Workspace } from "../../components/Workspace/Workspace" import { firstOrItem } from "../../util/array" import { getWorkspaceStatus } from "../../util/workspace" -import { XServiceContext } from "../../xServices/StateContext" +import { workspaceMachine } from "../../xServices/workspace/workspaceXService" export const WorkspacePage: React.FC = () => { const { workspace: workspaceQueryParam } = useParams() const workspaceId = firstOrItem(workspaceQueryParam, null) - const xServices = useContext(XServiceContext) - const [workspaceState, workspaceSend] = useActor(xServices.workspaceXService) + const [workspaceState, workspaceSend] = useMachine(workspaceMachine) const { workspace, resources, getWorkspaceError, getResourcesError, builds } = workspaceState.context const workspaceStatus = getWorkspaceStatus(workspace?.latest_build) diff --git a/site/src/xServices/StateContext.tsx b/site/src/xServices/StateContext.tsx index 7606b626c881b..da7af13f1395c 100644 --- a/site/src/xServices/StateContext.tsx +++ b/site/src/xServices/StateContext.tsx @@ -6,13 +6,11 @@ import { authMachine } from "./auth/authXService" import { buildInfoMachine } from "./buildInfo/buildInfoXService" import { siteRolesMachine } from "./roles/siteRolesXService" import { usersMachine } from "./users/usersXService" -import { workspaceMachine } from "./workspace/workspaceXService" interface XServiceContextType { authXService: ActorRefFrom buildInfoXService: ActorRefFrom usersXService: ActorRefFrom - workspaceXService: ActorRefFrom siteRolesXService: ActorRefFrom } @@ -38,7 +36,6 @@ export const XServiceProvider: React.FC = ({ children }) => { authXService: useInterpret(authMachine), buildInfoXService: useInterpret(buildInfoMachine), usersXService: useInterpret(() => usersMachine.withConfig({ actions: { redirectToUsersPage } })), - workspaceXService: useInterpret(workspaceMachine), siteRolesXService: useInterpret(siteRolesMachine), }} > From 1ff47a6684c9999b07e827d52d28cb4b6038f24d Mon Sep 17 00:00:00 2001 From: Presley Date: Mon, 23 May 2022 18:53:50 +0000 Subject: [PATCH 2/4] Fix Workspace storybook --- .../Workspace/Workspace.stories.tsx | 32 +++++++++++-------- site/src/components/Workspace/Workspace.tsx | 3 -- .../WorkspaceActions/WorkspaceActions.tsx | 5 ++- .../src/pages/WorkspacePage/WorkspacePage.tsx | 3 -- site/src/testHelpers/entities.ts | 8 +++++ 5 files changed, 29 insertions(+), 22 deletions(-) diff --git a/site/src/components/Workspace/Workspace.stories.tsx b/site/src/components/Workspace/Workspace.stories.tsx index 9ad361fb51fb6..3b962bb57ce3f 100644 --- a/site/src/components/Workspace/Workspace.stories.tsx +++ b/site/src/components/Workspace/Workspace.stories.tsx @@ -2,8 +2,17 @@ import { action } from "@storybook/addon-actions" import { Story } from "@storybook/react" import React from "react" import { + MockCanceledWorkspace, + MockCancelingWorkspace, + MockDeletedWorkspace, + MockDeletingWorkspace, + MockFailedWorkspace, MockOutdatedWorkspace, + MockStartingWorkspace, + MockStoppedWorkspace, + MockStoppingWorkspace, MockWorkspace, + MockWorkspaceBuild, MockWorkspaceResource, MockWorkspaceResource2, } from "../../testHelpers/renderHelpers" @@ -23,36 +32,33 @@ Started.args = { handleStart: action("start"), handleStop: action("stop"), handleRetry: action("retry"), - workspaceStatus: "started", resources: [MockWorkspaceResource, MockWorkspaceResource2], + builds: [MockWorkspaceBuild] } export const Starting = Template.bind({}) -Starting.args = { ...Started.args, workspaceStatus: "starting" } +Starting.args = { ...Started.args, workspace: MockStartingWorkspace } export const Stopped = Template.bind({}) -Stopped.args = { ...Started.args, workspaceStatus: "stopped" } +Stopped.args = { ...Started.args, workspace: MockStoppedWorkspace } export const Stopping = Template.bind({}) -Stopping.args = { ...Started.args, workspaceStatus: "stopping" } +Stopping.args = { ...Started.args, workspace: MockStoppingWorkspace } export const Error = Template.bind({}) -Error.args = { ...Started.args, workspaceStatus: "error" } - -export const BuildLoading = Template.bind({}) -BuildLoading.args = { ...Started.args, workspaceStatus: "loading" } +Error.args = { ...Started.args, workspace: MockFailedWorkspace } export const Deleting = Template.bind({}) -Deleting.args = { ...Started.args, workspaceStatus: "deleting" } +Deleting.args = { ...Started.args, workspace: MockDeletingWorkspace } export const Deleted = Template.bind({}) -Deleted.args = { ...Started.args, workspaceStatus: "deleted" } +Deleted.args = { ...Started.args, workspace: MockDeletedWorkspace } export const Canceling = Template.bind({}) -Canceling.args = { ...Started.args, workspaceStatus: "canceling" } +Canceling.args = { ...Started.args, workspace: MockCancelingWorkspace } -export const NoBreadcrumb = Template.bind({}) -NoBreadcrumb.args = { ...Started.args, template: undefined } +export const Canceled = Template.bind({}) +Canceled.args = { ...Started.args, workspace: MockCanceledWorkspace } export const Outdated = Template.bind({}) Outdated.args = { ...Started.args, workspace: MockOutdatedWorkspace } diff --git a/site/src/components/Workspace/Workspace.tsx b/site/src/components/Workspace/Workspace.tsx index 60e9ef7d3f5e6..8526f1b6c4717 100644 --- a/site/src/components/Workspace/Workspace.tsx +++ b/site/src/components/Workspace/Workspace.tsx @@ -18,7 +18,6 @@ export interface WorkspaceProps { handleRetry: () => void handleUpdate: () => void workspace: TypesGen.Workspace - workspaceStatus: WorkspaceStatus resources?: TypesGen.WorkspaceResource[] getResourcesError?: Error builds?: TypesGen.WorkspaceBuild[] @@ -33,7 +32,6 @@ export const Workspace: React.FC = ({ handleRetry, handleUpdate, workspace, - workspaceStatus, resources, getResourcesError, builds, @@ -60,7 +58,6 @@ export const Workspace: React.FC = ({ handleStop={handleStop} handleRetry={handleRetry} handleUpdate={handleUpdate} - workspaceStatus={workspaceStatus} /> diff --git a/site/src/components/WorkspaceActions/WorkspaceActions.tsx b/site/src/components/WorkspaceActions/WorkspaceActions.tsx index 6bec9312bb91d..ac0f73e38272e 100644 --- a/site/src/components/WorkspaceActions/WorkspaceActions.tsx +++ b/site/src/components/WorkspaceActions/WorkspaceActions.tsx @@ -8,7 +8,7 @@ import StopIcon from "@material-ui/icons/Stop" import React from "react" import { Link as RouterLink } from "react-router-dom" import { Workspace } from "../../api/typesGenerated" -import { WorkspaceStatus } from "../../util/workspace" +import { getWorkspaceStatus, WorkspaceStatus } from "../../util/workspace" import { Stack } from "../Stack/Stack" import { WorkspaceActionButton } from "../WorkspaceActionButton/WorkspaceActionButton" @@ -30,7 +30,6 @@ const canAcceptJobs = (workspaceStatus: WorkspaceStatus) => export interface WorkspaceActionsProps { workspace: Workspace - workspaceStatus: WorkspaceStatus handleStart: () => void handleStop: () => void handleRetry: () => void @@ -39,13 +38,13 @@ export interface WorkspaceActionsProps { export const WorkspaceActions: React.FC = ({ workspace, - workspaceStatus, handleStart, handleStop, handleRetry, handleUpdate, }) => { const styles = useStyles() + const workspaceStatus = getWorkspaceStatus(workspace?.latest_build) return ( diff --git a/site/src/pages/WorkspacePage/WorkspacePage.tsx b/site/src/pages/WorkspacePage/WorkspacePage.tsx index 7670286a4fd30..fb3556019aca7 100644 --- a/site/src/pages/WorkspacePage/WorkspacePage.tsx +++ b/site/src/pages/WorkspacePage/WorkspacePage.tsx @@ -7,7 +7,6 @@ import { Margins } from "../../components/Margins/Margins" import { Stack } from "../../components/Stack/Stack" import { Workspace } from "../../components/Workspace/Workspace" import { firstOrItem } from "../../util/array" -import { getWorkspaceStatus } from "../../util/workspace" import { workspaceMachine } from "../../xServices/workspace/workspaceXService" export const WorkspacePage: React.FC = () => { @@ -16,7 +15,6 @@ export const WorkspacePage: React.FC = () => { const [workspaceState, workspaceSend] = useMachine(workspaceMachine) const { workspace, resources, getWorkspaceError, getResourcesError, builds } = workspaceState.context - const workspaceStatus = getWorkspaceStatus(workspace?.latest_build) /** * Get workspace, template, and organization on mount and whenever workspaceId changes. @@ -40,7 +38,6 @@ export const WorkspacePage: React.FC = () => { handleStop={() => workspaceSend("STOP")} handleRetry={() => workspaceSend("RETRY")} handleUpdate={() => workspaceSend("UPDATE")} - workspaceStatus={workspaceStatus} resources={resources} getResourcesError={getResourcesError instanceof Error ? getResourcesError : undefined} builds={builds} diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index 3d143aeac9ecd..06bd8201c414e 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -76,6 +76,10 @@ export const MockCancelingProvisionerJob = { ...MockProvisionerJob, status: "canceling" as TypesGen.ProvisionerJobStatus, } +export const MockCanceledProvisionerJob = { + ...MockProvisionerJob, + status: "canceled" as TypesGen.ProvisionerJobStatus, +} export const MockRunningProvisionerJob = { ...MockProvisionerJob, status: "running" as TypesGen.ProvisionerJobStatus } export const MockTemplateVersion: TypesGen.TemplateVersion = { @@ -164,6 +168,10 @@ export const MockCancelingWorkspace: TypesGen.Workspace = { ...MockWorkspace, latest_build: { ...MockWorkspaceBuild, job: MockCancelingProvisionerJob }, } +export const MockCanceledWorkspace: TypesGen.Workspace = { + ...MockWorkspace, + latest_build: { ...MockWorkspaceBuild, job: MockCanceledProvisionerJob }, +} export const MockFailedWorkspace: TypesGen.Workspace = { ...MockWorkspace, latest_build: { ...MockWorkspaceBuild, job: MockFailedProvisionerJob }, From 1b69acffc45720d03cad9f6a76aa0a4d5528ff8e Mon Sep 17 00:00:00 2001 From: Presley Date: Mon, 23 May 2022 19:46:36 +0000 Subject: [PATCH 3/4] Lint --- site/src/components/Workspace/Workspace.stories.tsx | 2 +- site/src/components/Workspace/Workspace.tsx | 1 - site/src/components/WorkspaceActions/WorkspaceActions.tsx | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/site/src/components/Workspace/Workspace.stories.tsx b/site/src/components/Workspace/Workspace.stories.tsx index 3b962bb57ce3f..d5087ebf949cd 100644 --- a/site/src/components/Workspace/Workspace.stories.tsx +++ b/site/src/components/Workspace/Workspace.stories.tsx @@ -33,7 +33,7 @@ Started.args = { handleStop: action("stop"), handleRetry: action("retry"), resources: [MockWorkspaceResource, MockWorkspaceResource2], - builds: [MockWorkspaceBuild] + builds: [MockWorkspaceBuild], } export const Starting = Template.bind({}) diff --git a/site/src/components/Workspace/Workspace.tsx b/site/src/components/Workspace/Workspace.tsx index 8526f1b6c4717..c563ba175bb2c 100644 --- a/site/src/components/Workspace/Workspace.tsx +++ b/site/src/components/Workspace/Workspace.tsx @@ -3,7 +3,6 @@ import Typography from "@material-ui/core/Typography" import React from "react" import * as TypesGen from "../../api/typesGenerated" import { MONOSPACE_FONT_FAMILY } from "../../theme/constants" -import { WorkspaceStatus } from "../../util/workspace" import { BuildsTable } from "../BuildsTable/BuildsTable" import { Resources } from "../Resources/Resources" import { Stack } from "../Stack/Stack" diff --git a/site/src/components/WorkspaceActions/WorkspaceActions.tsx b/site/src/components/WorkspaceActions/WorkspaceActions.tsx index ac0f73e38272e..15d0d391297a0 100644 --- a/site/src/components/WorkspaceActions/WorkspaceActions.tsx +++ b/site/src/components/WorkspaceActions/WorkspaceActions.tsx @@ -44,7 +44,7 @@ export const WorkspaceActions: React.FC = ({ handleUpdate, }) => { const styles = useStyles() - const workspaceStatus = getWorkspaceStatus(workspace?.latest_build) + const workspaceStatus = getWorkspaceStatus(workspace.latest_build) return ( From abe0eb3ace4e7a61d5d2a2a1eb9ee912a3228a3b Mon Sep 17 00:00:00 2001 From: Presley Date: Mon, 23 May 2022 19:46:48 +0000 Subject: [PATCH 4/4] Remove breadcrumb from workspaceXService --- .../xServices/workspace/workspaceXService.ts | 62 ------------------- 1 file changed, 62 deletions(-) diff --git a/site/src/xServices/workspace/workspaceXService.ts b/site/src/xServices/workspace/workspaceXService.ts index c8b2fea620b41..f61ca29c9e4ca 100644 --- a/site/src/xServices/workspace/workspaceXService.ts +++ b/site/src/xServices/workspace/workspaceXService.ts @@ -19,12 +19,9 @@ const Language = { export interface WorkspaceContext { workspace?: TypesGen.Workspace template?: TypesGen.Template - organization?: TypesGen.Organization build?: TypesGen.WorkspaceBuild resources?: TypesGen.WorkspaceResource[] getWorkspaceError?: Error | unknown - getTemplateError?: Error | unknown - getOrganizationError?: Error | unknown // error creating a new WorkspaceBuild buildError?: Error | unknown // these are separate from getX errors because they don't make the page unusable @@ -59,9 +56,6 @@ export const workspaceMachine = createMachine( getTemplate: { data: TypesGen.Template } - getOrganization: { - data: TypesGen.Organization - } startWorkspace: { data: TypesGen.WorkspaceBuild } @@ -130,43 +124,6 @@ export const workspaceMachine = createMachine( }, }, }, - breadcrumb: { - initial: "gettingTemplate", - states: { - gettingTemplate: { - invoke: { - src: "getTemplate", - id: "getTemplate", - onDone: { - target: "gettingOrganization", - actions: ["assignTemplate", "clearGetTemplateError"], - }, - onError: { - target: "error", - actions: "assignGetTemplateError", - }, - }, - tags: "loading", - }, - gettingOrganization: { - invoke: { - src: "getOrganization", - id: "getOrganization", - onDone: { - target: "ready", - actions: ["assignOrganization", "clearGetOrganizationError"], - }, - onError: { - target: "error", - actions: "assignGetOrganizationError", - }, - }, - tags: "loading", - }, - error: {}, - ready: {}, - }, - }, build: { initial: "idle", states: { @@ -309,7 +266,6 @@ export const workspaceMachine = createMachine( assign({ workspace: undefined, template: undefined, - organization: undefined, build: undefined, }), assignWorkspace: assign({ @@ -322,17 +278,6 @@ export const workspaceMachine = createMachine( assignTemplate: assign({ template: (_, event) => event.data, }), - assignGetTemplateError: assign({ - getTemplateError: (_, event) => event.data, - }), - clearGetTemplateError: (context) => assign({ ...context, getTemplateError: undefined }), - assignOrganization: assign({ - organization: (_, event) => event.data, - }), - assignGetOrganizationError: assign({ - getOrganizationError: (_, event) => event.data, - }), - clearGetOrganizationError: (context) => assign({ ...context, getOrganizationError: undefined }), assignBuild: (_, event) => assign({ build: event.data, @@ -438,13 +383,6 @@ export const workspaceMachine = createMachine( throw Error("Cannot get template without workspace") } }, - getOrganization: async (context) => { - if (context.template) { - return await API.getOrganization(context.template.organization_id) - } else { - throw Error("Cannot get organization without template") - } - }, startWorkspace: async (context) => { if (context.workspace) { return await API.startWorkspace(context.workspace.id, context.template?.active_version_id)