1import * as Cloudflare from "@/Cloudflare";
2import * as Effect from "effect/Effect";
3import { HttpServerRequest } from "effect/http/HttpServerRequest";
4import * as HttpServerResponse from "effect/http/HttpServerResponse";
5import { RestartObject } from "./object.ts";
6
7/**
8 * Drives the restart scenarios over HTTP. Each request targets a named DO
9 * instance (`?name=`) so tests can isolate instances:
10 * - `GET /ping` → RPC ping (starts/restarts the container, returns "pong")
11 * - `GET /running` → `{ running }`
12 * - `GET /stop` → destroy the container (SIGKILL)
13 * - `GET /crash` → make the container process exit non-zero
14 */
15export default Cloudflare.Worker(
16 "RestartWorker",
17 {
18 main: import.meta.filename,
19 },
20 Effect.gen(function* () {
21 const objects = yield* RestartObject;
22
23 return {
24 fetch: Effect.gen(function* () {
25 const request = yield* HttpServerRequest;
26 const url = new URL(request.url, "http://x");
27 const name = url.searchParams.get("name") ?? "default";
28 const object = objects.getByName(name);
29
30 if (url.pathname === "/ping") {
31 const pong = yield* object.ping();
32 return HttpServerResponse.text(pong);
33 }
34 if (url.pathname === "/running") {
35 const running = yield* object.running();
36 return yield* HttpServerResponse.json({ running });
37 }
38 if (url.pathname === "/stop") {
39 yield* object.stop();
40 return HttpServerResponse.text("stopped");
41 }
42 if (url.pathname === "/crash") {
43 const result = yield* object.crash();
44 return HttpServerResponse.text(result);
45 }
46
47 return HttpServerResponse.text("ok");
48 }).pipe(
49 // Surface failures as 5xx (not a thrown defect) so the test's readiness
50 // retry treats a mid-restart blip as retryable rather than fatal.
51 Effect.catchCause((cause) =>
52 Effect.succeed(
53 HttpServerResponse.text(String(cause), { status: 503 }),
54 ),
55 ),
56 ),
57 };
58 }),
59);