1import * as GCP from "@/GCP";
2import * as Test from "@/Test/Alchemy";
3import * as dataplex from "@distilled.cloud/gcp/dataplex_v1";
4import { expect } from "alchemy-test";
5import * as Effect from "effect/Effect";
6import { MinimumLogLevel } from "effect/References";
7import * as Schedule from "effect/Schedule";
8import { withDataplexSlot } from "./quota.ts";
9
10const { test } = Test.make({ providers: GCP.providers() });
11
12const logLevel = Effect.provideService(
13 MinimumLogLevel,
14 process.env.DEBUG ? "Debug" : "Info",
15);
16
17const waitUntilGone = (name: string) =>
18 dataplex.getProjectsLocationsMetadataFeeds({ name }).pipe(
19 Effect.as("found" as const),
20 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
21 Effect.repeat({
22 schedule: Schedule.spaced("2 seconds"),
23 until: (status) => status === "gone",
24 times: 10,
25 }),
26 );
27
28test.provider.skipIf(!!process.env.FAST)(
29 "create, update, and delete a metadata feed",
30 (stack) =>
31 Effect.gen(function* () {
32 yield* stack.destroy();
33
34 const created = yield* stack.deploy(
35 Effect.gen(function* () {
36 const topic = yield* GCP.PubSub.Topic("CatalogFeed", {
37 labels: { env: "test" },
38 });
39 const feed = yield* GCP.Dataplex.MetadataFeed("Catalog", {
40 location: "us-central1",
41 pubsubTopic: topic.name,
42 labels: { env: "test" },
43 });
44 return { topic, feed };
45 }),
46 );
47
48 expect(created.feed.name).toContain("/metadataFeeds/");
49 expect(created.feed.metadataFeedId).toEqual(expect.any(String));
50 expect(created.feed.pubsubTopic).toEqual(created.topic.name);
51 expect(created.feed.labels).toMatchObject({ env: "test" });
52
53 const fetched = yield* dataplex.getProjectsLocationsMetadataFeeds({
54 name: created.feed.name,
55 });
56 expect(fetched.name).toEqual(created.feed.name);
57 expect(fetched.labels?.env).toEqual("test");
58
59 const updated = yield* stack.deploy(
60 Effect.gen(function* () {
61 const topic = yield* GCP.PubSub.Topic("CatalogFeed", {
62 topicId: created.topic.topicId,
63 labels: { env: "test" },
64 });
65 const feed = yield* GCP.Dataplex.MetadataFeed("Catalog", {
66 metadataFeedId: created.feed.metadataFeedId,
67 location: "us-central1",
68 pubsubTopic: topic.name,
69 filters: { changeTypes: ["CREATE"] },
70 labels: { env: "prod", team: "data" },
71 });
72 return { topic, feed };
73 }),
74 );
75
76 expect(updated.feed.name).toEqual(created.feed.name);
77 expect(updated.feed.labels).toMatchObject({ env: "prod", team: "data" });
78
79 yield* stack.destroy();
80 const gone = yield* waitUntilGone(created.feed.name);
81 expect(gone).toEqual("gone");
82 }).pipe(logLevel, withDataplexSlot),
83 { tags: ["provider:gcp", "provider:gcp:dataplex", "live"], timeout: 900_000 },
84);