1import * as Cloudflare from "@/Cloudflare";
2import * as Effect from "effect/Effect";
3import { HttpServerRequest } from "effect/http/HttpServerRequest";
4import * as HttpServerResponse from "effect/http/HttpServerResponse";
5
6/**
7 * Minimal effectful container for exercising stop/crash → auto-restart. `ping`
8 * proves the container is up; the `/exit` route makes the container process
9 * kill itself (non-zero exit) so we can drive the monitor-observed-crash path.
10 */
11export class RestartContainer extends Cloudflare.Container<
12 RestartContainer,
13 {
14 ping: () => Effect.Effect<string>;
15 }
16>()("RestartContainer") {}
17
18export default RestartContainer.make(
19 {
20 main: import.meta.filename,
21 image: "oven/bun:latest",
22 },
23 Effect.gen(function* () {
24 return {
25 ping: () => Effect.succeed("pong"),
26 fetch: Effect.gen(function* () {
27 const request = yield* HttpServerRequest;
28 const url = new URL(request.url, "http://container");
29 if (url.pathname === "/exit") {
30 // Simulate a crash: kill the container process with a non-zero exit
31 // code shortly after replying, so the response flushes first. The
32 // Durable Object's monitor observes the exit; the next request must
33 // transparently restart the container.
34 yield* Effect.sync(() => {
35 setTimeout(() => process.exit(1), 50);
36 });
37 return HttpServerResponse.text("exiting");
38 }
39 return HttpServerResponse.text("ok");
40 }),
41 };
42 }),
43);