import * as Data from "effect/Data"; import * as Effect from "effect/Effect"; import type { Env } from "./config.ts"; import type { InstallationParams } from "./installation-workflow.ts"; export class WorkflowUnavailable extends Data.TaggedError( "WorkflowUnavailable", )<{ missing: boolean }> {} function native(call: () => Promise) { return Effect.tryPromise({ try: call, catch: (error) => new WorkflowUnavailable({ missing: error instanceof Error && [ "instance.not_found", "Error: instance.not_found", "(instance.not_found) Instance not found", ].includes(error.message), }), }); } export function terminateWorkflow(env: Env, id: string) { return Effect.gen(function* () { const instance = yield* native(() => env.INSTALLATION_WORKFLOW.get(id)); yield* native(() => instance.terminate()); if ((yield* native(() => instance.status())).status !== "terminated") return yield* new WorkflowUnavailable({ missing: false }); }); } // A lost create reply is reconciled against the same durable reservation. export function ensureWorkflow( env: Env, id: string, params: InstallationParams, ) { return native(() => env.INSTALLATION_WORKFLOW.create({ id, params })).pipe( Effect.asVoid, Effect.catch(() => Effect.gen(function* () { const instance = yield* native(() => env.INSTALLATION_WORKFLOW.get(id)); yield* native(() => instance.status()); }), ), ); }