1import * as Fly from "@/Fly";
2import * as Cause from "effect/Cause";
3import * as Effect from "effect/Effect";
4import * as Stream from "effect/Stream";
5import * as HttpClientRequest from "effect/http/HttpClientRequest";
6import { HttpServerRequest } from "effect/http/HttpServerRequest";
7import * as HttpServerResponse from "effect/http/HttpServerResponse";
8import RpcOrders from "./rpc-orders.ts";
9import RpcUsers from "./rpc-users.ts";
10
11/**
12 * Public Service on the stack network. Each route exercises one way of
13 * calling the private Services.
14 */
15export default class RpcGateway extends Fly.Service<RpcGateway>()(
16 "RpcGateway",
17 Effect.gen(function* () {
18 return {
19 main: import.meta.url,
20 region: "iad",
21 network: yield* Fly.stackNetwork,
22 guest: { cpuKind: "shared" as const, cpus: 1, memoryMb: 256 },
23 };
24 }),
25 Effect.gen(function* () {
26 const users = yield* Fly.bindService(RpcUsers);
27 const orders = yield* Fly.bindService(RpcOrders);
28 const admin = yield* Fly.bindEndpoint(RpcUsers, { port: 9000 });
29 return {
30 fetch: Effect.gen(function* () {
31 const request = yield* HttpServerRequest;
32 const path = new URL(request.url, "http://gateway").pathname;
33 if (path === "/users") {
34 return yield* HttpServerResponse.json(yield* users.listUsers());
35 }
36 if (path === "/orders") {
37 return yield* HttpServerResponse.json(yield* orders.listOrders());
38 }
39 if (path === "/stream") {
40 const streamed = yield* users.streamUsers().pipe(Stream.runCollect);
41 return yield* HttpServerResponse.json(Array.from(streamed));
42 }
43 if (path === "/http") {
44 const response = yield* users.fetch(HttpClientRequest.get("/hello"));
45 return HttpServerResponse.text(yield* response.text);
46 }
47 if (path === "/admin") {
48 const response = yield* admin.client.get("/stats");
49 return HttpServerResponse.text(
50 `${yield* admin.host}:${admin.port} ${yield* response.text}`,
51 );
52 }
53 return HttpServerResponse.text("gateway");
54 }).pipe(
55 Effect.catchCause((cause) =>
56 Effect.succeed(
57 HttpServerResponse.text(Cause.pretty(cause), { status: 502 }),
58 ),
59 ),
60 ),
61 };
62 }),
63) {}