1import * as Cloudflare from "alchemy/Cloudflare";
2import * as Effect from "effect/Effect";
3import { HttpServerRequest } from "effect/http/HttpServerRequest";
4import * as HttpServerResponse from "effect/http/HttpServerResponse";
5import { BunObject } from "./bun-object.ts";
6import { EffectfulObject } from "./effectful-object.ts";
7import { OpencodeObject } from "./opencode-object.ts";
8import { RemoteObject } from "./remote-object.ts";
9
10/**
11 * Cloudflare Worker host for the container cold-start benchmark. Each request
12 * names a fresh DO instance (`?name=`), which boots its own container.
13 *
14 * - `GET /boot?variant=effectful|bun|remote|opencode&name=K` boots one
15 * container and returns `{ readyMs }`. It does NOT shut down.
16 * - `GET /shutdown?variant=…&name=K` tears the container down so the next boot
17 * is an independent cold start and the account's container cap isn't exhausted.
18 *
19 * TIMING: the clock runs HERE in the Worker, around the entire DO call — not
20 * inside the DO. The container layer eagerly calls `container.start()` during
21 * DO construction, so a clock started inside `boot()` would miss instance
22 * allocation and start entirely, undercounting the cold start. Wrapping the
23 * `getByName(name).boot()` call captures DO creation + container start +
24 * readiness probe, while staying inside Cloudflare (no client network in the
25 * number) — symmetric with the MicroVM hosts, which start the clock before
26 * `RunMicrovm`.
27 */
28export default class ContainerWorker extends Cloudflare.Worker<ContainerWorker>()(
29 "BenchContainerWorker",
30 {
31 main: import.meta.filename,
32 },
33 Effect.gen(function* () {
34 const effectful = yield* EffectfulObject;
35 const remote = yield* RemoteObject;
36 const bun = yield* BunObject;
37 const opencode = yield* OpencodeObject;
38
39 const objectFor = (variant: string) =>
40 variant === "remote"
41 ? remote
42 : variant === "bun"
43 ? bun
44 : variant === "opencode"
45 ? opencode
46 : effectful;
47
48 return {
49 fetch: Effect.gen(function* () {
50 const request = yield* HttpServerRequest;
51 const url = new URL(request.url, "http://x");
52 const name = url.searchParams.get("name") ?? "default";
53 const variant = url.searchParams.get("variant") ?? "effectful";
54
55 if (url.pathname === "/boot") {
56 // Time the WHOLE thing: DO creation, eager container start during
57 // layer construction, and the readiness probe inside boot().
58 const start = yield* Effect.sync(() => Date.now());
59 yield* objectFor(variant).getByName(name).boot();
60 const readyMs = (yield* Effect.sync(() => Date.now())) - start;
61 return yield* HttpServerResponse.json({ readyMs });
62 }
63 if (url.pathname === "/shutdown") {
64 yield* objectFor(variant).getByName(name).shutdown();
65 return yield* HttpServerResponse.json({ ok: true });
66 }
67 return HttpServerResponse.text("ok");
68 }).pipe(
69 Effect.catch((err) =>
70 Effect.succeed(HttpServerResponse.text(String(err), { status: 500 })),
71 ),
72 ),
73 };
74 }),
75) {}