1import * as Lambda from "@/AWS/Lambda";
2import * as RedshiftData from "@/AWS/RedshiftData";
3import * as RedshiftServerless from "@/AWS/RedshiftServerless";
4import * as Duration from "effect/Duration";
5import * as Effect from "effect/Effect";
6import { HttpServerRequest } from "effect/http/HttpServerRequest";
7import * as HttpServerResponse from "effect/http/HttpServerResponse";
8import path from "pathe";
9
10const main = path.resolve(import.meta.dirname, "query-handler.ts");
11
12export class RedshiftQueryFunction extends Lambda.Function<Lambda.Function>()(
13 "RedshiftQueryFunction",
14) {}
15
16export default RedshiftQueryFunction.make(
17 {
18 main,
19 functionUrl: true,
20 // Redshift Data statements are submitted then polled — allow generous
21 // time for the composite query to finish.
22 timeout: Duration.seconds(120),
23 },
24 Effect.gen(function* () {
25 const namespace = yield* RedshiftServerless.Namespace("QueryNamespace", {
26 namespaceName: "alchemy-test-rs-ns",
27 dbName: "dev",
28 adminUsername: "alchemyadmin",
29 manageAdminPassword: true,
30 });
31 const workgroup = yield* RedshiftServerless.Workgroup("QueryWorkgroup", {
32 workgroupName: "alchemy-test-rs-wg",
33 namespaceName: namespace.namespaceName,
34 baseCapacity: 8,
35 publiclyAccessible: false,
36 });
37
38 const sql = yield* RedshiftData.Statements(workgroup, { database: "dev" });
39
40 return {
41 fetch: Effect.gen(function* () {
42 const request = yield* HttpServerRequest;
43 const url = new URL(request.originalUrl);
44 const pathname = url.pathname;
45
46 if (request.method === "GET" && pathname === "/query") {
47 const result = yield* sql.query("SELECT 1 AS n");
48 return yield* HttpServerResponse.json({
49 columns: (result.ColumnMetadata ?? []).map((c) => c.name),
50 records: result.Records,
51 totalNumRows: result.TotalNumRows,
52 });
53 }
54
55 return yield* HttpServerResponse.json(
56 { error: "Not found", method: request.method, pathname },
57 { status: 404 },
58 );
59 }).pipe(Effect.orDie),
60 };
61 }).pipe(Effect.provide(RedshiftData.StatementsHttp)),
62);