1import * as Fly from "@/Fly";
2import * as Effect from "effect/Effect";
3import * as Redacted from "effect/Redacted";
4import { HttpServerRequest } from "effect/http/HttpServerRequest";
5import * as HttpServerResponse from "effect/http/HttpServerResponse";
6
7export const REDIS_PORT = 3000;
8export const REDIS_KEY = "alchemy-marker";
9export const REDIS_VALUE = "hello-from-redis";
10
11export const RedisSite = Fly.App("RedisSite", {
12 enableSubdomains: true,
13});
14
15export const Cache = Fly.Redis("Cache");
16
17export const RedisIp = Fly.IpAssignment("Shared", {
18 app: RedisSite,
19 type: "shared_v4",
20});
21
22/**
23 * HTTP Service that PINGs Redis and round-trips a key via
24 * {@link Fly.ReadWriteRedis}.
25 */
26export default class RedisApi extends Fly.Service<RedisApi>()(
27 "RedisApi",
28 {
29 app: RedisSite,
30 main: import.meta.url,
31 region: "iad",
32 port: REDIS_PORT,
33 guest: { cpuKind: "shared", cpus: 1, memoryMb: 256 },
34 },
35 Effect.gen(function* () {
36 const cache = yield* Fly.ReadWriteRedis(Cache);
37 const resource = yield* Cache;
38 const url = yield* resource.url;
39
40 return {
41 fetch: Effect.gen(function* () {
42 const request = yield* HttpServerRequest;
43 const path = new URL(request.url, "http://service").pathname;
44
45 if (path === "/health" || path === "/") {
46 const pong = yield* cache.ping().pipe(
47 Effect.map((body) => /pong/i.test(body)),
48 Effect.orElseSucceed(() => false),
49 );
50 const resolvedUrl = yield* url;
51 return yield* HttpServerResponse.json({
52 pong,
53 hasOutputUrl:
54 resolvedUrl !== undefined &&
55 Redacted.isRedacted(resolvedUrl) &&
56 Redacted.value(resolvedUrl).length > 0,
57 });
58 }
59
60 if (path === "/set") {
61 yield* cache.set(REDIS_KEY, REDIS_VALUE).pipe(Effect.orDie);
62 return yield* HttpServerResponse.json({ ok: true, key: REDIS_KEY });
63 }
64
65 if (path === "/get") {
66 const value = yield* cache.get(REDIS_KEY).pipe(Effect.orDie);
67 return yield* HttpServerResponse.json({
68 ok: value === REDIS_VALUE,
69 value,
70 });
71 }
72
73 return yield* HttpServerResponse.json({ ok: false }, { status: 404 });
74 }),
75 };
76 }).pipe(Effect.provide(Fly.ReadWriteRedisHttp)),
77) {}