opencode/packages/server/src/service-status.ts

45 lines
1.5 KiB
TypeScript

export * as Status from "./service-status"
import { ServiceStatus } from "@opencode-ai/protocol/groups/health"
import { Effect, Ref } from "effect"
export type State =
| { readonly type: "starting" }
| { readonly type: "ready" }
| { readonly type: "stopping" }
| { readonly type: "failed" }
export interface Interface {
readonly current: Effect.Effect<State>
readonly ready: Effect.Effect<void>
readonly fail: Effect.Effect<void>
readonly beginStopping: Effect.Effect<void>
readonly requestStop: (request: ServiceStatus.StopRequest) => Effect.Effect<boolean>
}
export const make = Effect.fnUntraced(function* (options: {
readonly instanceID: string
readonly managed: boolean
readonly initial?: State
}) {
const current = yield* Ref.make(options.initial ?? ({ type: "starting" } satisfies State))
const beginStopping = Ref.update(current, (status) =>
status.type === "stopping" ? status : ({ type: "stopping" } satisfies State),
)
return {
current: Ref.get(current),
ready: Ref.update(current, (status) =>
status.type === "starting" ? ({ type: "ready" } satisfies State) : status,
),
fail: Ref.update(current, (status) =>
status.type === "starting" ? ({ type: "failed" } satisfies State) : status,
),
beginStopping,
requestStop: (request) => {
if (!options.managed || request.instanceID !== options.instanceID)
return Effect.succeed(false)
return beginStopping.pipe(Effect.as(true))
},
} satisfies Interface
})