Cut worker isolate baseline memory: stub just-bash, lazy-load cheerio (#340)
Production OOM triage: every 'Worker exceeded memory limit' burst hits unrelated cheap routes right after a deploy — the 128MB limit is per isolate, and the main worker's eagerly-evaluated module graph is what crowds it, not any single request. - Alias just-bash to a throwing stub (worker never uses it): removes just-bash + turndown + @mixmark-io/domino from the bundle. The chain was pulled in eagerly by @cloudflare/think via the SamChatAgent re-export in src/server.ts; SAM only uses its own MCP tools. - Disable Think's workspace bash tool on SamChatAgent so the stub is unreachable at runtime. - Dynamic-import page-analyzer (cheerio) in the site-audit crawl step so it evaluates only when an audit runs, not in every isolate. - Drop the turndown CJS alias workaround (#339): turndown is no longer in the graph at all. Main eager server chunk: 14,434 kB -> 11,712 kB (-19%); cheerio's 503 kB now a lazy chunk.
This commit is contained in:
parent
93cf32081a
commit
1a74904b67
@ -78,6 +78,12 @@ type SamContext = {
|
|||||||
* the app DB, so every session in a project shares them.
|
* the app DB, so every session in a project shares them.
|
||||||
*/
|
*/
|
||||||
export class SamChatAgent extends Think {
|
export class SamChatAgent extends Think {
|
||||||
|
// SAM's toolset is the MCP tools from beforeTurn; it has no use for Think's
|
||||||
|
// workspace bash tool, whose just-bash dependency is stubbed out of the
|
||||||
|
// bundle anyway (see vite.config.ts) to keep ~30 MB of eagerly-evaluated
|
||||||
|
// source out of every isolate's baseline heap.
|
||||||
|
override workspaceBash = false;
|
||||||
|
|
||||||
// Session row + project, resolved once per DO lifetime (the binding is
|
// Session row + project, resolved once per DO lifetime (the binding is
|
||||||
// immutable). Null until a turn/provider needs it — and left null when the
|
// immutable). Null until a turn/provider needs it — and left null when the
|
||||||
// registry row is gone, which beforeTurn turns into a polite refusal.
|
// registry row is gone, which beforeTurn turns into a polite refusal.
|
||||||
|
|||||||
33
src/server/lib/just-bash-stub.ts
Normal file
33
src/server/lib/just-bash-stub.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* Build-time stand-in for `just-bash`, wired up via the vite.config.ts alias.
|
||||||
|
*
|
||||||
|
* `@cloudflare/think` eagerly imports just-bash (~21 MB of source, plus
|
||||||
|
* turndown and the 8.6 MB @mixmark-io/domino DOM implementation) at module
|
||||||
|
* init, and SamChatAgent is re-exported from src/server.ts, so the whole chain
|
||||||
|
* lands in the main worker's startup module graph — raising every isolate's
|
||||||
|
* baseline heap toward the 128 MB limit (production OOM bursts on unrelated
|
||||||
|
* routes after each deploy). SAM only uses its own MCP toolset and disables
|
||||||
|
* Think's workspace bash tool (`workspaceBash = false`), so the real library
|
||||||
|
* is unreachable; this stub keeps it out of the bundle entirely.
|
||||||
|
*
|
||||||
|
* Remove once https://github.com/cloudflare/agents/issues/1673 lands and
|
||||||
|
* @cloudflare/think loads just-bash lazily.
|
||||||
|
*/
|
||||||
|
const STUBBED_MESSAGE =
|
||||||
|
"just-bash is stubbed out of the worker bundle (see vite.config.ts); " +
|
||||||
|
"the workspace bash tool is disabled for this deployment";
|
||||||
|
|
||||||
|
// Covers every named import in the dependency graph: `Bash` (Think's
|
||||||
|
// workspace bash tool) and `defineCommand` (agents/skills bash scripts).
|
||||||
|
// Both are only reached when a model invokes bash, which SAM never exposes.
|
||||||
|
// Must stay a class: call sites construct it with `new Bash({...})`.
|
||||||
|
// oxlint-disable-next-line typescript-eslint/no-extraneous-class
|
||||||
|
export class Bash {
|
||||||
|
constructor() {
|
||||||
|
throw new Error(STUBBED_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function defineCommand(): never {
|
||||||
|
throw new Error(STUBBED_MESSAGE);
|
||||||
|
}
|
||||||
@ -1,4 +1,3 @@
|
|||||||
import { analyzeHtml } from "@/server/lib/audit/page-analyzer";
|
|
||||||
import type { StepPageResult } from "@/server/lib/audit/types";
|
import type { StepPageResult } from "@/server/lib/audit/types";
|
||||||
import { isSameOrigin, normalizeUrl } from "@/server/lib/audit/url-utils";
|
import { isSameOrigin, normalizeUrl } from "@/server/lib/audit/url-utils";
|
||||||
|
|
||||||
@ -31,6 +30,11 @@ export async function crawlPage(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const html = await response.text();
|
const html = await response.text();
|
||||||
|
// Dynamic import keeps cheerio (page-analyzer's HTML parser) out of the
|
||||||
|
// worker's startup module graph: SiteAuditWorkflow is re-exported from
|
||||||
|
// src/server.ts, so a static import would evaluate cheerio in every
|
||||||
|
// isolate's baseline heap, not just when an audit actually crawls.
|
||||||
|
const { analyzeHtml } = await import("@/server/lib/audit/page-analyzer");
|
||||||
const analysis = analyzeHtml(
|
const analysis = analyzeHtml(
|
||||||
html,
|
html,
|
||||||
finalUrl,
|
finalUrl,
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { fileURLToPath } from "node:url";
|
||||||
import { tanstackStart } from "@tanstack/react-start/plugin/vite";
|
import { tanstackStart } from "@tanstack/react-start/plugin/vite";
|
||||||
import { defineConfig, loadEnv } from "vite";
|
import { defineConfig, loadEnv } from "vite";
|
||||||
import tsConfigPaths from "vite-tsconfig-paths";
|
import tsConfigPaths from "vite-tsconfig-paths";
|
||||||
@ -23,17 +24,19 @@ export default defineConfig(({ mode }) => {
|
|||||||
return {
|
return {
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
// TODO: Remove this workaround once fixed upstream — either turndown
|
// TODO: Remove this workaround once @cloudflare/think stops eagerly
|
||||||
// drops the bare require from its ESM build, or @cloudflare/think
|
// importing just-bash at module init
|
||||||
// stops eagerly importing just-bash/turndown at module init
|
|
||||||
// (https://github.com/cloudflare/agents/issues/1673).
|
// (https://github.com/cloudflare/agents/issues/1673).
|
||||||
//
|
//
|
||||||
// turndown's ESM build (pulled in via just-bash's html-to-markdown
|
// just-bash (plus its turndown → @mixmark-io/domino chain, ~30 MB of
|
||||||
// command) contains a bare CommonJS `require("@mixmark-io/domino")`
|
// source) is only used by Think's workspace bash tool, which SAM
|
||||||
// that the Cloudflare Workers runtime rejects at deploy time (error
|
// disables — but the eager import drags it into the main worker's
|
||||||
// 10021). Its CJS build goes through Vite's CommonJS transform, which
|
// startup module graph, inflating every isolate's baseline heap
|
||||||
// rewrites that require into a bundled import.
|
// toward the 128 MB limit (production OOM bursts on unrelated
|
||||||
turndown: "turndown/lib/turndown.cjs.js",
|
// routes). Alias it to a throwing stub so it never ships.
|
||||||
|
"just-bash": fileURLToPath(
|
||||||
|
new URL("./src/server/lib/just-bash-stub.ts", import.meta.url),
|
||||||
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
envPrefix: [
|
envPrefix: [
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user