| 1 | import * as Cloudflare from "@/Cloudflare"; |
| 2 | import * as Effect from "effect/Effect"; |
| 3 | import * as HttpClientRequest from "effect/http/HttpClientRequest"; |
| 4 | import { RestartContainer } from "./container.ts"; |
| 5 | |
| 6 | /** |
| 7 | * Durable Object backing one {@link RestartContainer} instance, exposing the |
| 8 | * levers the restart tests need: |
| 9 | * - `ping` — RPC into the container (forces start + proves it's up) |
| 10 | * - `running` — the raw `container.running` flag |
| 11 | * - `stop` — hard stop from the DO side (`destroy` = SIGKILL) |
| 12 | * - `crash` — make the container process exit on its own (non-zero) |
| 13 | */ |
| 14 | export class RestartObject extends Cloudflare.DurableObject<RestartObject>()( |
| 15 | "RestartObject", |
| 16 | Effect.gen(function* () { |
| 17 | const container = yield* RestartContainer; |
| 18 | |
| 19 | return Effect.gen(function* () { |
| 20 | return { |
| 21 | ping: () => container.ping(), |
| 22 | running: () => container.running, |
| 23 | // Hard stop from the DO side. Exercises the "container stopped, then |
| 24 | // requested again" auto-restart path. |
| 25 | stop: () => container.destroy(), |
| 26 | // Crash from inside the container process. Exercises the |
| 27 | // monitor-observed-exit auto-restart path. |
| 28 | crash: () => |
| 29 | Effect.gen(function* () { |
| 30 | const { fetch } = yield* container.getTcpPort(3000); |
| 31 | const response = yield* fetch( |
| 32 | HttpClientRequest.get("http://container/exit"), |
| 33 | ); |
| 34 | return yield* response.text; |
| 35 | }).pipe(Effect.orDie), |
| 36 | }; |
| 37 | }); |
| 38 | }).pipe( |
| 39 | Effect.provide( |
| 40 | Cloudflare.Containers.layer(RestartContainer, { |
| 41 | enableInternet: true, |
| 42 | }), |
| 43 | ), |
| 44 | ), |
| 45 | ) {} |