mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
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:
@@ -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),
|
||||
})
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user