1import * as GCP from "@/GCP";
2import * as Test from "@/Test/Alchemy";
3import * as pubsub from "@distilled.cloud/gcp/pubsub_v1";
4import { expect } from "alchemy-test";
5import * as Effect from "effect/Effect";
6import { MinimumLogLevel } from "effect/References";
7import * as Schedule from "effect/Schedule";
8
9const { test } = Test.make({ providers: GCP.providers() });
10
11const logLevel = Effect.provideService(
12 MinimumLogLevel,
13 process.env.DEBUG ? "Debug" : "Info",
14);
15
16const AVRO_V1 = JSON.stringify({
17 type: "record",
18 name: "Event",
19 fields: [{ name: "id", type: "string" }],
20});
21
22const AVRO_V2 = JSON.stringify({
23 type: "record",
24 name: "Event",
25 fields: [
26 { name: "id", type: "string" },
27 { name: "count", type: "int", default: 0 },
28 ],
29});
30
31const waitUntilGone = (name: string) =>
32 pubsub.getProjectsSchemas({ name, view: "BASIC" }).pipe(
33 Effect.as("found" as const),
34 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
35 Effect.repeat({
36 schedule: Schedule.spaced("1 second"),
37 until: (status) => status === "gone",
38 times: 10,
39 }),
40 );
41
42test.provider(
43 "create, update, and delete a schema",
44 (stack) =>
45 Effect.gen(function* () {
46 yield* stack.destroy();
47
48 const created = yield* stack.deploy(
49 Effect.gen(function* () {
50 return yield* GCP.PubSub.Schema("Events", {
51 type: "AVRO",
52 definition: AVRO_V1,
53 });
54 }),
55 );
56
57 expect(created.name).toContain("/schemas/");
58 expect(created.schemaId).toEqual(expect.any(String));
59 expect(created.type).toEqual("AVRO");
60 expect(created.definition).toContain("string");
61 expect(created.revisionId).toEqual(expect.any(String));
62
63 const fetched = yield* pubsub.getProjectsSchemas({
64 name: created.name,
65 view: "FULL",
66 });
67 expect(fetched.name).toEqual(created.name);
68 expect(fetched.type).toEqual("AVRO");
69 expect(fetched.definition).toBeDefined();
70
71 const updated = yield* stack.deploy(
72 Effect.gen(function* () {
73 return yield* GCP.PubSub.Schema("Events", {
74 schemaId: created.schemaId,
75 type: "AVRO",
76 definition: AVRO_V2,
77 });
78 }),
79 );
80
81 expect(updated.name).toEqual(created.name);
82 expect(updated.type).toEqual("AVRO");
83 expect(updated.revisionId).toEqual(expect.any(String));
84 expect(updated.revisionId).not.toEqual(created.revisionId);
85 expect(updated.definition).toContain("count");
86
87 yield* stack.destroy();
88
89 const gone = yield* waitUntilGone(created.name);
90 expect(gone).toEqual("gone");
91 }).pipe(logLevel),
92 { tags: ["provider:gcp", "provider:gcp:pubsub", "live"], timeout: 90_000 },
93);