mirror of https://github.com/coder/coder.git
141 lines
3.3 KiB
TypeScript
141 lines
3.3 KiB
TypeScript
import { assign, createMachine } from "xstate"
|
|
import * as API from "../../api/api"
|
|
import { ProvisionerJobLog, WorkspaceBuild } from "../../api/typesGenerated"
|
|
|
|
type LogsContext = {
|
|
// Build
|
|
buildId: string
|
|
build?: WorkspaceBuild
|
|
getBuildError?: Error | unknown
|
|
// Logs
|
|
logs?: ProvisionerJobLog[]
|
|
}
|
|
|
|
type LogsEvent =
|
|
| {
|
|
type: "ADD_LOG"
|
|
log: ProvisionerJobLog
|
|
}
|
|
| {
|
|
type: "NO_MORE_LOGS"
|
|
}
|
|
|
|
export const workspaceBuildMachine = createMachine(
|
|
{
|
|
id: "workspaceBuildState",
|
|
schema: {
|
|
context: {} as LogsContext,
|
|
events: {} as LogsEvent,
|
|
services: {} as {
|
|
getWorkspaceBuild: {
|
|
data: WorkspaceBuild
|
|
}
|
|
getLogs: {
|
|
data: ProvisionerJobLog[]
|
|
}
|
|
},
|
|
},
|
|
tsTypes: {} as import("./workspaceBuildXService.typegen").Typegen0,
|
|
type: "parallel",
|
|
states: {
|
|
build: {
|
|
initial: "gettingBuild",
|
|
states: {
|
|
gettingBuild: {
|
|
entry: "clearGetBuildError",
|
|
invoke: {
|
|
src: "getWorkspaceBuild",
|
|
onDone: {
|
|
target: "idle",
|
|
actions: "assignBuild",
|
|
},
|
|
onError: {
|
|
target: "idle",
|
|
actions: "assignGetBuildError",
|
|
},
|
|
},
|
|
},
|
|
idle: {},
|
|
},
|
|
},
|
|
logs: {
|
|
initial: "gettingExistentLogs",
|
|
states: {
|
|
gettingExistentLogs: {
|
|
invoke: {
|
|
id: "getLogs",
|
|
src: "getLogs",
|
|
onDone: {
|
|
actions: ["assignLogs"],
|
|
target: "watchingLogs",
|
|
},
|
|
},
|
|
},
|
|
watchingLogs: {
|
|
id: "watchingLogs",
|
|
invoke: {
|
|
id: "streamWorkspaceBuildLogs",
|
|
src: "streamWorkspaceBuildLogs",
|
|
},
|
|
},
|
|
loaded: {
|
|
type: "final",
|
|
},
|
|
},
|
|
on: {
|
|
ADD_LOG: {
|
|
actions: "addLog",
|
|
},
|
|
NO_MORE_LOGS: {
|
|
target: "logs.loaded",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
actions: {
|
|
// Build
|
|
assignBuild: assign({
|
|
build: (_, event) => event.data,
|
|
}),
|
|
assignGetBuildError: assign({
|
|
getBuildError: (_, event) => event.data,
|
|
}),
|
|
clearGetBuildError: assign({
|
|
getBuildError: (_) => undefined,
|
|
}),
|
|
// Logs
|
|
assignLogs: assign({
|
|
logs: (_, event) => event.data,
|
|
}),
|
|
addLog: assign({
|
|
logs: (context, event) => {
|
|
const previousLogs = context.logs ?? []
|
|
return [...previousLogs, event.log]
|
|
},
|
|
}),
|
|
},
|
|
services: {
|
|
getWorkspaceBuild: (ctx) => API.getWorkspaceBuild(ctx.buildId),
|
|
getLogs: async (ctx) => API.getWorkspaceBuildLogs(ctx.buildId),
|
|
streamWorkspaceBuildLogs: (ctx) => async (callback) => {
|
|
const reader = await API.streamWorkspaceBuildLogs(ctx.buildId)
|
|
|
|
// Watching for the stream
|
|
// eslint-disable-next-line no-constant-condition, @typescript-eslint/no-unnecessary-condition
|
|
while (true) {
|
|
const { value, done } = await reader.read()
|
|
|
|
if (done) {
|
|
callback("NO_MORE_LOGS")
|
|
break
|
|
}
|
|
|
|
callback({ type: "ADD_LOG", log: value })
|
|
}
|
|
},
|
|
},
|
|
},
|
|
)
|