fix: send auto start/stop api calls only when changed (#5184)

* Send auto start/stop api calls only when changed

* Format

* Extract and test util function
This commit is contained in:
Presley Pizzo
2022-11-29 15:12:36 -05:00
committed by GitHub
parent 8b73844f69
commit 2e3db274f1
4 changed files with 99 additions and 6 deletions
@@ -4,6 +4,7 @@ import { scheduleToAutoStart } from "pages/WorkspaceSchedulePage/schedule"
import { ttlMsToAutoStop } from "pages/WorkspaceSchedulePage/ttl"
import React, { useEffect, useState } from "react"
import { Navigate, useNavigate, useParams } from "react-router-dom"
import { scheduleChanged } from "util/schedule"
import * as TypesGen from "../../api/typesGenerated"
import { FullScreenLoader } from "../../components/Loader/FullScreenLoader"
import { WorkspaceScheduleForm } from "../../components/WorkspaceScheduleForm/WorkspaceScheduleForm"
@@ -108,10 +109,10 @@ export const WorkspaceSchedulePage: React.FC = () => {
onSubmit={(values) => {
scheduleSend({
type: "SUBMIT_SCHEDULE",
autoStart: values.autoStartEnabled
? formValuesToAutoStartRequest(values)
: undefined,
autoStart: formValuesToAutoStartRequest(values),
ttl: formValuesToTTLRequest(values),
autoStartChanged: scheduleChanged(autoStart, values),
autoStopChanged: scheduleChanged(autoStop, values),
})
}}
/>
+71
View File
@@ -1,5 +1,7 @@
import dayjs from "dayjs"
import duration from "dayjs/plugin/duration"
import { emptySchedule } from "pages/WorkspaceSchedulePage/schedule"
import { emptyTTL } from "pages/WorkspaceSchedulePage/ttl"
import { Template, Workspace } from "../api/typesGenerated"
import * as Mocks from "../testHelpers/entities"
import {
@@ -12,6 +14,7 @@ import {
getMaxDeadlineChange,
getMinDeadline,
stripTimezone,
scheduleChanged,
} from "./schedule"
dayjs.extend(duration)
@@ -141,3 +144,71 @@ describe("getMaxDeadlineChange", () => {
expect(getMaxDeadlineChange(deadline, minDeadline)).toEqual(2)
})
})
describe("scheduleChanged", () => {
describe("autoStart", () => {
it("should be true if toggle values are different", () => {
const autoStart = { autoStartEnabled: true, ...emptySchedule }
const formValues = {
autoStartEnabled: false,
...emptySchedule,
autoStopEnabled: false,
ttl: emptyTTL,
}
expect(scheduleChanged(autoStart, formValues)).toBe(true)
})
it("should be true if schedule values are different", () => {
const autoStart = { autoStartEnabled: true, ...emptySchedule }
const formValues = {
autoStartEnabled: true,
...{ ...emptySchedule, monday: true, startTime: "09:00" },
autoStopEnabled: false,
ttl: emptyTTL,
}
expect(scheduleChanged(autoStart, formValues)).toBe(true)
})
it("should be false if all autostart values are the same", () => {
const autoStart = { autoStartEnabled: true, ...emptySchedule }
const formValues = {
autoStartEnabled: true,
...emptySchedule,
autoStopEnabled: false,
ttl: emptyTTL,
}
expect(scheduleChanged(autoStart, formValues)).toBe(false)
})
})
describe("autoStop", () => {
it("should be true if toggle values are different", () => {
const autoStop = { autoStopEnabled: true, ttl: 1000 }
const formValues = {
autoStartEnabled: false,
...emptySchedule,
autoStopEnabled: false,
ttl: 1000,
}
expect(scheduleChanged(autoStop, formValues)).toBe(true)
})
it("should be true if ttl values are different", () => {
const autoStop = { autoStopEnabled: true, ttl: 1000 }
const formValues = {
autoStartEnabled: false,
...emptySchedule,
autoStopEnabled: true,
ttl: 2000,
}
expect(scheduleChanged(autoStop, formValues)).toBe(true)
})
it("should be false if all autostop values are the same", () => {
const autoStop = { autoStopEnabled: true, ttl: 1000 }
const formValues = {
autoStartEnabled: false,
...emptySchedule,
autoStopEnabled: true,
ttl: 1000,
}
expect(scheduleChanged(autoStop, formValues)).toBe(false)
})
})
})
+17
View File
@@ -1,3 +1,5 @@
import map from "lodash/map"
import some from "lodash/some"
import cronstrue from "cronstrue"
import dayjs, { Dayjs } from "dayjs"
import advancedFormat from "dayjs/plugin/advancedFormat"
@@ -7,6 +9,9 @@ import timezone from "dayjs/plugin/timezone"
import utc from "dayjs/plugin/utc"
import { Template, Workspace } from "../api/typesGenerated"
import { isWorkspaceOn } from "./workspace"
import { WorkspaceScheduleFormValues } from "components/WorkspaceScheduleForm/WorkspaceScheduleForm"
import { AutoStop } from "pages/WorkspaceSchedulePage/ttl"
import { AutoStart } from "pages/WorkspaceSchedulePage/schedule"
// REMARK: some plugins depend on utc, so it's listed first. Otherwise they're
// sorted alphabetically.
@@ -179,3 +184,15 @@ export const getMaxDeadlineChange = (
deadline: dayjs.Dayjs,
extremeDeadline: dayjs.Dayjs,
): number => Math.abs(deadline.diff(extremeDeadline, "hours"))
export const scheduleChanged = (
initialValues: AutoStart | AutoStop,
formValues: WorkspaceScheduleFormValues,
): boolean =>
some(
map(
{ ...initialValues },
(v: boolean | string, k: keyof typeof initialValues) =>
formValues[k] !== v,
),
)
@@ -45,8 +45,10 @@ export type WorkspaceScheduleEvent =
| { type: "GET_WORKSPACE"; username: string; workspaceName: string }
| {
type: "SUBMIT_SCHEDULE"
autoStart: TypesGen.UpdateWorkspaceAutostartRequest | undefined
autoStart: TypesGen.UpdateWorkspaceAutostartRequest
autoStartChanged: boolean
ttl: TypesGen.UpdateWorkspaceTTLRequest
autoStopChanged: boolean
}
export const workspaceSchedule = createMachine(
@@ -195,10 +197,12 @@ export const workspaceSchedule = createMachine(
throw new Error("Failed to load workspace.")
}
if (event.autoStart?.schedule !== undefined) {
if (event.autoStartChanged) {
await API.putWorkspaceAutostart(context.workspace.id, event.autoStart)
}
await API.putWorkspaceAutostop(context.workspace.id, event.ttl)
if (event.autoStopChanged) {
await API.putWorkspaceAutostop(context.workspace.id, event.ttl)
}
},
},
},