1import * as GCP from "@/GCP";
2import * as Test from "@/Test/Alchemy";
3import * as bigquery from "@distilled.cloud/gcp/bigquery_v2";
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 waitUntilGone = (projectId: string, datasetId: string) =>
17 bigquery.getDatasets({ projectId, datasetId }).pipe(
18 Effect.as("found" as const),
19 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
20 Effect.repeat({
21 schedule: Schedule.spaced("1 second"),
22 until: (status) => status === "gone",
23 times: 10,
24 }),
25 );
26
27test.provider(
28 "create, update, and delete a dataset",
29 (stack) =>
30 Effect.gen(function* () {
31 yield* stack.destroy();
32
33 const created = yield* stack.deploy(
34 Effect.gen(function* () {
35 return yield* GCP.BigQuery.Dataset("Analytics", {
36 location: "US-CENTRAL1",
37 labels: { env: "test" },
38 description: "alchemy test dataset",
39 forceDestroy: true,
40 });
41 }),
42 );
43
44 expect(created.datasetId).toEqual(expect.any(String));
45 expect(created.datasetId).toMatch(/^[a-zA-Z0-9_]+$/);
46 expect(created.location.toUpperCase()).toEqual("US-CENTRAL1");
47 expect(created.labels).toMatchObject({ env: "test" });
48 expect(created.description).toEqual("alchemy test dataset");
49
50 const fetched = yield* bigquery.getDatasets({
51 projectId: created.project,
52 datasetId: created.datasetId,
53 });
54 expect(fetched.datasetReference?.datasetId).toEqual(created.datasetId);
55 expect(fetched.labels?.env).toEqual("test");
56 expect(fetched.description).toEqual("alchemy test dataset");
57
58 const queried = yield* bigquery.queryJobs({
59 projectId: created.project,
60 body: {
61 query: "SELECT 1 AS n",
62 useLegacySql: false,
63 location: created.location,
64 defaultDataset: {
65 projectId: created.project,
66 datasetId: created.datasetId,
67 },
68 },
69 });
70 expect(queried.jobComplete).toEqual(true);
71
72 const updated = yield* stack.deploy(
73 Effect.gen(function* () {
74 return yield* GCP.BigQuery.Dataset("Analytics", {
75 datasetId: created.datasetId,
76 location: "US-CENTRAL1",
77 labels: { env: "prod", role: "analytics" },
78 description: "updated analytics",
79 friendlyName: "analytics",
80 defaultTableExpirationMs: "3600000",
81 forceDestroy: true,
82 });
83 }),
84 );
85
86 expect(updated.datasetId).toEqual(created.datasetId);
87 expect(updated.labels).toMatchObject({
88 env: "prod",
89 role: "analytics",
90 });
91 expect(updated.description).toEqual("updated analytics");
92 expect(updated.friendlyName).toEqual("analytics");
93 expect(updated.defaultTableExpirationMs).toEqual("3600000");
94
95 const fetchedUpdate = yield* bigquery.getDatasets({
96 projectId: created.project,
97 datasetId: created.datasetId,
98 });
99 expect(fetchedUpdate.labels?.env).toEqual("prod");
100 expect(fetchedUpdate.labels?.role).toEqual("analytics");
101 expect(fetchedUpdate.description).toEqual("updated analytics");
102 expect(fetchedUpdate.friendlyName).toEqual("analytics");
103 expect(fetchedUpdate.defaultTableExpirationMs).toEqual("3600000");
104
105 yield* stack.destroy();
106
107 const gone = yield* waitUntilGone(created.project, created.datasetId);
108 expect(gone).toEqual("gone");
109 }).pipe(logLevel),
110 { tags: ["provider:gcp", "provider:gcp:bigquery", "live"], timeout: 90_000 },
111);