1import * as GCP from "@/GCP";
2import * as Output from "@/Output";
3import * as Effect from "effect/Effect";
4import * as Schedule from "effect/Schedule";
5import { serveProbes } from "../../bindingHost.ts";
6
7/** Scratch bucket the Word Count template writes to. */
8export const PipelineTmp = GCP.Storage.Bucket("PipelineBindTmp", {
9 location: "US-CENTRAL1",
10 forceDestroy: true,
11});
12
13/**
14 * Batch pipeline the bindings run and stop (roles/datapipelines.invoker,
15 * roles/datapipelines.admin on the project).
16 */
17export const BindBatch = Effect.gen(function* () {
18 const bucket = yield* PipelineTmp;
19 return yield* GCP.DataPipelines.Pipeline("BindBatch", {
20 type: "PIPELINE_TYPE_BATCH",
21 displayName: "bind-batch",
22 workload: {
23 dataflowLaunchTemplateRequest: {
24 location: "us-central1",
25 gcsPath: "gs://dataflow-templates/latest/Word_Count",
26 launchParameters: {
27 jobName: "alchemy-bind-word-count",
28 parameters: {
29 inputFile: "gs://dataflow-samples/shakespeare/kinglear.txt",
30 output: Output.interpolate`gs://${bucket.bucketName}/out`,
31 },
32 environment: {
33 tempLocation: Output.interpolate`gs://${bucket.bucketName}/tmp`,
34 },
35 },
36 },
37 },
38 });
39});
40
41/**
42 * Effect-native Cloud Run service exercising every Data Pipelines binding
43 * as its own runtime service account. Deployed from
44 * {@link ../Bindings.test.ts}.
45 */
46export default class DataPipelinesBindingsHost extends GCP.Function<DataPipelinesBindingsHost>()(
47 "DataPipelinesBindingsHost",
48 { main: import.meta.url, invokerIamDisabled: true },
49 Effect.gen(function* () {
50 const runPipeline = yield* GCP.DataPipelines.RunPipeline(BindBatch);
51 const stopPipeline = yield* GCP.DataPipelines.StopPipeline(BindBatch);
52
53 return {
54 fetch: serveProbes({
55 runPipeline: runPipeline(),
56 // Stopping right after a run fails with `NotFound: Job not found.`
57 // until Dataflow registers the launched job.
58 stopPipeline: stopPipeline().pipe(
59 Effect.retry({
60 while: (error) => error._tag === "NotFound",
61 schedule: Schedule.spaced("3 seconds"),
62 times: 20,
63 }),
64 ),
65 }),
66 };
67 }).pipe(
68 Effect.provide(GCP.DataPipelines.RunPipelineHttp),
69 Effect.provide(GCP.DataPipelines.StopPipelineHttp),
70 ),
71) {}