1import * as healthcare from "@distilled.cloud/gcp/healthcare_v1";
2import * as Effect from "effect/Effect";
3import { waitForOperation as waitForGcpOperation } from "../Operation.ts";
4
5/** Wait for an operation through the shared GCP waiter. */
6export const waitForOperation = (
7 operation: healthcare.Operation,
8 options?: { notFoundOk?: boolean; alreadyExistsOk?: boolean },
9) =>
10 waitForGcpOperation(
11 operation,
12 (name) =>
13 healthcare
14 .getProjectsLocationsDatasetsOperations({ name })
15 .pipe(
16 Effect.catchTag("NotFound", (error) =>
17 options?.notFoundOk === true
18 ? Effect.succeed<healthcare.Operation>({ name, done: true })
19 : Effect.fail(error),
20 ),
21 ),
22 { budget: "20 minutes" },
23 ).pipe(
24 // ALREADY_EXISTS (6): a concurrent create won the race. NOT_FOUND (5)
25 // is success for a delete.
26 Effect.catchIf(
27 (error) =>
28 error._tag === "GCP.OperationFailed" &&
29 ((options?.alreadyExistsOk !== false && error.code === 6) ||
30 (options?.notFoundOk === true && error.code === 5)),
31 () => Effect.void,
32 ),
33 // Re-read the finished operation for its typed response and metadata.
34 Effect.flatMap(() =>
35 operation.name === undefined || operation.name.length === 0
36 ? Effect.succeed(operation)
37 : healthcare
38 .getProjectsLocationsDatasetsOperations({ name: operation.name })
39 .pipe(Effect.catchTag("NotFound", () => Effect.succeed(operation))),
40 ),
41 );