1import * as Docker from "@/Docker";
2import { ServerHost } from "@/Server/Process.ts";
3import * as Effect from "effect/Effect";
4import * as Ref from "effect/Ref";
5import * as Schedule from "effect/Schedule";
6import { HttpServerRequest } from "effect/http/HttpServerRequest";
7import * as HttpServerResponse from "effect/http/HttpServerResponse";
8
9/**
10 * Fixed host port published through the swarm ingress. Deterministic (never
11 * derived from the clock) and uncommon enough to avoid colliding with other
12 * suites on the shared local daemon.
13 */
14export const SERVICE_EXTERNAL_PORT = 43117;
15
16/**
17 * End-to-end fixture for the effectful `Docker.Service` platform: a
18 * long-running server bundled from this module and deployed to the local
19 * swarm.
20 *
21 * - `yield* ServerHost` + `host.run(...)` registers a background loop that
22 * increments a counter once a second.
23 * - the returned `{ fetch }` handler is served over HTTP by the container's
24 * Bun HTTP server. `/ticks` reports the counter so the test can prove the
25 * background loop is actually running inside the deployed swarm task.
26 */
27export default class TestService extends Docker.Service<TestService>()(
28 "DockerPlatformService",
29 {
30 main: import.meta.filename,
31 port: 3000,
32 ports: [{ external: SERVICE_EXTERNAL_PORT, internal: 3000 }],
33 replicas: 1,
34 },
35 Effect.gen(function* () {
36 const host = yield* ServerHost;
37 const ticks = yield* Ref.make(0);
38
39 // Long-running background loop (the `host.run` pattern).
40 yield* host.run(
41 Ref.update(ticks, (n) => n + 1).pipe(
42 Effect.repeat(Schedule.spaced("1 second")),
43 Effect.asVoid,
44 ),
45 );
46
47 return {
48 fetch: Effect.gen(function* () {
49 const request = yield* HttpServerRequest;
50 const url = new URL(request.url, "http://service");
51 if (url.pathname === "/health") {
52 return yield* HttpServerResponse.json({ ok: true });
53 }
54 if (url.pathname === "/ticks") {
55 return yield* HttpServerResponse.json({
56 ticks: yield* Ref.get(ticks),
57 });
58 }
59 return HttpServerResponse.text("hello from docker service");
60 }),
61 };
62 }),
63) {}