import * as Effect from "effect/Effect"; import { WebDeadline, withResearchBrowser } from "../../worker/browser-session"; import { WebFailure } from "../../worker/web-errors"; export async function browserRace(scenario: string) { const records = { creates: 0, connects: 0, deletes: [] as string[], closed: 0, commands: 0, error: "", result: false, }; const pending: Promise[] = []; const caller = new AbortController(); const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); const binding = { async fetch( input: RequestInfo | URL, init?: RequestInit, ): Promise { if (init?.method === "POST") { records.creates++; if (scenario.startsWith("late-create")) await wait(80); return Response.json({ sessionId: `session-${records.creates}` }); } if (init?.method === "DELETE") { records.deletes.push(String(input).split("/").at(-1)!); return new Response(null, { status: scenario === "cleanup-fail" ? 503 : 200, }); } records.connects++; if (scenario === "late-connect") await wait(80); const pair = new WebSocketPair(); pair[1].accept(); pair[1].addEventListener("close", () => { records.closed++; pair[1].close(); }); pair[1].addEventListener("message", (event) => { records.commands++; const command = JSON.parse(String(event.data)); if (!["cancel-command", "timeout-command"].includes(scenario)) pair[1].send( JSON.stringify({ id: command.id, result: { ok: true } }), ); }); return new Response(null, { status: 101, webSocket: pair[0] }); }, }; if (scenario === "pre-abort") caller.abort(); const deadline = new WebDeadline( scenario === "cleanup-fail" || scenario === "success" || scenario === "metadata-stall" ? 1_000 : 30, caller.signal, ); const timer = scenario === "cancel-command" ? setTimeout(() => caller.abort(), 15) : undefined; try { await Effect.runPromise( withResearchBrowser( binding, deadline, (promise) => pending.push(promise), (cdp) => cdp.send("Target.getTargets").pipe( Effect.tap(() => Effect.sync(() => { records.result = true; }), ), ), scenario.includes("register") || scenario === "metadata-stall" ? { acquired: async () => { if (scenario === "register-delay") await wait(80); if (scenario.includes("fail")) throw new Error("Registration rejected"); }, closed: async () => { if (scenario === "metadata-stall") await new Promise(() => {}); }, } : undefined, ), ); } catch (error) { records.error = error instanceof WebFailure ? error.code : deadline.signal.aborted ? "cancelled" : "unexpected"; } finally { deadline.dispose(); if (timer) clearTimeout(timer); } if (scenario !== "metadata-stall") await Promise.all(pending); await wait(10); return records; }