1import * as GCP from "@/GCP";
2import * as Effect from "effect/Effect";
3import * as HttpServerResponse from "effect/http/HttpServerResponse";
4import { DataBucket, Tweets } from "./bound-resources.ts";
5
6/**
7 * Effect-native Cloud Run Service that binds Pub/Sub and Storage.
8 * Deployed from {@link ../Service.test.ts}.
9 */
10export default class BoundService extends GCP.Function<BoundService>()(
11 "BoundService",
12 {
13 main: import.meta.url,
14 location: "us-central1",
15 invokerIamDisabled: true,
16 },
17 Effect.gen(function* () {
18 const tweets = yield* Tweets;
19 const bucket = yield* DataBucket;
20 const publish = yield* GCP.PubSub.Publish(tweets);
21 const putObject = yield* GCP.Storage.PutObject(bucket);
22 const getObject = yield* GCP.Storage.GetObject(bucket);
23
24 return {
25 fetch: Effect.gen(function* () {
26 const { messageIds } = yield* publish({
27 body: { messages: [{ data: btoa("hello") }] },
28 }).pipe(Effect.orDie);
29 yield* putObject({ name: "probe.txt", body: "stored" }).pipe(
30 Effect.orDie,
31 );
32 const { body } = yield* getObject({ object: "probe.txt" }).pipe(
33 Effect.orDie,
34 );
35 return yield* HttpServerResponse.json({
36 published: (messageIds?.length ?? 0) > 0,
37 read: new TextDecoder().decode(body),
38 });
39 }),
40 };
41 }).pipe(
42 Effect.provide(GCP.PubSub.PublishHttp),
43 Effect.provide(GCP.Storage.PutObjectHttp),
44 Effect.provide(GCP.Storage.GetObjectHttp),
45 ),
46) {}