diff --git a/apps/cloud/src/edge/production-config.test.ts b/apps/cloud/src/edge/production-config.test.ts index 700e3634ff..03075e641d 100644 --- a/apps/cloud/src/edge/production-config.test.ts +++ b/apps/cloud/src/edge/production-config.test.ts @@ -35,10 +35,10 @@ const shipped: V2EdgeEnv = { }; describe("production v2 edge settings", () => { - it("binds V2 to exactly one Worker", () => { + it("binds V2 to the unplaced marketing gateway", () => { const bindings = config.services.filter((service) => service.binding === "V2"); expect(bindings).toHaveLength(1); - expect(bindings[0]?.service).toMatch(/^[a-z0-9-]+$/); + expect(bindings[0]?.service).toBe("executor-next-marketing-v2"); }); it("redirects sign-up to v2's sign-up page on app.executor.sh", async () => { diff --git a/apps/cloud/src/server.ts b/apps/cloud/src/server.ts index 6e3cad473a..ca00c5132b 100644 --- a/apps/cloud/src/server.ts +++ b/apps/cloud/src/server.ts @@ -308,16 +308,6 @@ const cloudflareHandler = { fetch: async (request, env, ctx) => { isolateRequestSeq += 1; - // Public pages must not enter TanStack Start: its first-request dynamic - // import loads the entire React + Effect server graph and can take seconds - // on a cold isolate. Classify and service-bind marketing at the Worker - // entry, before telemetry or fetchHandler touches that graph. - // Everything that returns before the app-plane dispatch below leaves the - // graph unevaluated for the next request; warm it in the background. - if (!servedByAppPlane(new URL(request.url).pathname, request.method)) { - prewarmAppPlane(ctx); - } - // On `executor.sh`, v2 answers marketing (including `/docs` and its // telemetry proxies), sign-up, the fixed list of v2 paths and v2's // connected-account callbacks; v1's legal pages stay on v1's marketing @@ -329,6 +319,13 @@ const cloudflareHandler = { const marketing: Fetcher | undefined = env.MARKETING; if (marketingRequest && marketing) return marketing.fetch(marketingRequest); + // Only v1-owned requests may warm v1's application. A dynamic import still + // evaluates JavaScript on this isolate's thread under waitUntil; starting it + // for a forwarded page or stylesheet delays the otherwise independent response. + if (!servedByAppPlane(new URL(request.url).pathname, request.method)) { + prewarmAppPlane(ctx); + } + // Same reasoning, same seam: `/docs` and the PostHog proxy forward to an // external origin and never touch the router, React, or the Effect app. // Left in Start's middleware they still paid its lazy `loadEntries` import diff --git a/apps/cloud/wrangler.jsonc b/apps/cloud/wrangler.jsonc index 3fc0f540a1..21cba7aac1 100644 --- a/apps/cloud/wrangler.jsonc +++ b/apps/cloud/wrangler.jsonc @@ -98,7 +98,7 @@ "binding": "MARKETING", "service": "executor-marketing", }, - // v2's API Worker (the executor-next `v2` stage, same account). The edge + // v2's unplaced marketing Worker (the executor-next `v2` stage, same account). The edge // (src/edge/marketing.ts) forwards marketing and a fixed list of // executor.sh paths to it with the URL unchanged, so v2 sees host // `executor.sh`. @@ -106,7 +106,7 @@ "binding": "V2", // v2's Worker name. It must equal the name v2's deployment pins for // this binding; this is the only place v1 names it. - "service": "executor-next-hosted-api-v2-qs32brgjwvt7ytx4", + "service": "executor-next-marketing-v2", }, ], "hyperdrive": [