Files
OmniRoute/tests/unit/executor-map-golden.test.ts
oyi77 77ea656b12 perf(executors): lazy-load the executor registry — defer class imports + construction to first use (#11220)
The executor barrel statically imported ~100 executor modules and
constructed every instance at module load. Measured cold cost on top of
the minimal set: ~0.7–1.2s boot time and ~35MB heap, paid by every
deployment regardless of which providers it uses.

Now:
- executors/index.ts keeps the declarative alias table byte-stable (same
  keys, same order, same ctor args — pinned by the golden lock) but each
  value is a deferred loader using dynamic import; bundlers emit
  on-demand chunks
- registry.ts gains registerLazyExecutor/loadRegisteredExecutor: aliases
  are declared eagerly so hasSpecializedExecutor() and
  listExecutorAliases() stay synchronous, instances materialize once on
  first use and cache into the same registry map
- getExecutor() becomes async; production call sites (chatCore proxy
  resolver, video generation, compression judge/eval clients,
  quotaAutoPing deps, anthropic OAuth validation) await it
- cliproxy wrapper ExecutorLike types drop their index signatures so
  BaseExecutor satisfies them structurally

Measured after (isolated DATA_DIR): barrel boot 712-832ms / ~45MB with
first-use materialization of an executor costing +120-150ms once.

Test impact: 24 unit suites adapted mechanically to the async seam
(await + union narrowing on the Response | {response} execute result);
class imports moved from the barrel to executor module files. The
web-cookie sweep SIGABRT failure is pre-existing (reproduced identically
on the clean base).

Commit gate note: husky lint-staged fails with 'suppressions left that
do not occur anymore' — reproduced identically on a stashed clean tree
(22 baseline problems), independent of this change.
2026-08-24 21:44:22 -03:00

137 lines
5.6 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
// R0.3 GOLDEN LOCK (characterization BEFORE the ExecutorRegistry refactor):
// freeze the full provider-id → executor mapping of open-sse/executors/index.ts —
// every specialized key with its executor class, effective provider identity and
// which PROVIDERS config entry backs it — plus the getExecutor() dispatch rules
// (specialized hit, DefaultExecutor fallback + cache, cloud-agent guard #6699,
// search-provider guard #10274). The registry refactor must keep this snapshot
// byte-identical: any drift in keys, classes, provider identity or guard behavior
// is a golden diff, not a silent routing change.
const TEST_DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-executor-golden-"));
process.env.DATA_DIR = TEST_DATA_DIR;
// Dynamic imports AFTER DATA_DIR is set so db/core.ts picks up the temp path.
const { getExecutor, hasSpecializedExecutor, DefaultExecutor } = await import(
"../../open-sse/executors/index.ts"
);
const { PROVIDERS } = await import("../../open-sse/config/constants.ts");
const { SEARCH_PROVIDERS } = await import("../../open-sse/config/searchRegistry.ts");
const { goldenSnapshot } = await import("../helpers/goldenSnapshot.ts");
test.after(() => {
fs.rmSync(TEST_DATA_DIR, { recursive: true, force: true });
});
// The specialized keys are not exported; enumerate them through the public
// surface by probing every plausible id source AND the literal keys read from
// the module source. Reading the source keeps the golden honest: a key added
// to (or removed from) the hard-coded map cannot hide from the snapshot.
function readSpecializedKeys(): string[] {
const src = fs.readFileSync(
path.resolve(path.dirname(new URL(import.meta.url).pathname), "../../open-sse/executors/index.ts"),
"utf8"
);
const mapMatch = src.match(/const lazyExecutors[^\n]*= \{([\s\S]*?)\n\};/);
assert.ok(mapMatch, "lazyExecutors map literal not found in open-sse/executors/index.ts");
const keys: string[] = [];
for (const line of mapMatch[1].split("\n")) {
const m = line.match(/^\s*(?:"([^"]+)"|([A-Za-z0-9_$-]+)):\s*(?:async )?\(\)\s*=>/);
if (m) keys.push(m[1] ?? m[2]);
}
return keys;
}
// Map a ProviderConfig object back to its PROVIDERS key by identity, so the
// snapshot records WHICH config backs each executor without freezing the whole
// (huge, frequently-edited) config content.
const providerConfigKeyByRef = new Map<object, string>();
for (const [key, cfg] of Object.entries(PROVIDERS)) {
if (cfg && typeof cfg === "object" && !providerConfigKeyByRef.has(cfg)) {
providerConfigKeyByRef.set(cfg, key);
}
}
function describeExecutor(instance: unknown): {
className: string;
provider: string | null;
configSource: string | null;
} {
const inst = instance as { constructor: { name: string }; provider?: string; config?: object };
const cfg = inst.config;
return {
className: inst.constructor.name,
provider: typeof inst.provider === "string" ? inst.provider : null,
configSource:
cfg == null ? null : (providerConfigKeyByRef.get(cfg) ?? "<custom-config>"),
};
}
const specializedKeys = readSpecializedKeys();
test("golden: specialized executor map — key → class + provider identity + config source", async () => {
assert.ok(specializedKeys.length >= 100, `suspiciously few keys: ${specializedKeys.length}`);
const entries: Record<
string,
{ className: string; provider: string | null; configSource: string | null }
> = {};
const byInstance = new Map<unknown, string[]>();
for (const key of [...specializedKeys].sort()) {
assert.equal(hasSpecializedExecutor(key), true, `hasSpecializedExecutor(${key})`);
const instance = await getExecutor(key);
entries[key] = describeExecutor(instance);
const group = byInstance.get(instance) ?? [];
group.push(key);
byInstance.set(instance, group);
}
// Keys sharing the SAME instance share per-instance state (session pools,
// rotation cooldowns); today every map entry is its own `new X()`. Freeze that.
const sharedInstances = [...byInstance.values()]
.filter((keys) => keys.length > 1)
.map((keys) => keys.sort())
.sort((a, b) => a[0].localeCompare(b[0]));
goldenSnapshot("executors/executor-map", {
keyCount: specializedKeys.length,
entries,
sharedInstances,
});
});
test("golden: getExecutor dispatch rules — fallback, cache and 400-guards", async () => {
// 1. Unknown provider → DefaultExecutor for that provider, memoized.
const unknown = "golden-test-unknown-provider";
assert.equal(hasSpecializedExecutor(unknown), false);
const fallback = await getExecutor(unknown);
assert.ok(fallback instanceof DefaultExecutor, "fallback must be DefaultExecutor");
assert.equal(await getExecutor(unknown), fallback, "DefaultExecutor fallback must be cached");
// 2. Cloud-agent guard (#6699) and search guard (#10274) → status-400 throw.
const guardOutcome = async (provider: string) => {
try {
await getExecutor(provider);
return { throws: false as const };
} catch (err) {
const e = err as Error & { status?: number };
return { throws: true as const, status: e.status ?? null, message: e.message };
}
};
const searchProviders = Object.keys(SEARCH_PROVIDERS).sort();
goldenSnapshot("executors/dispatch-rules", {
fallback: describeExecutor(fallback),
cloudAgentGuard: { jules: await guardOutcome("jules") },
searchGuard: Object.fromEntries(
await Promise.all(searchProviders.map(async (p) => [p, await guardOutcome(p)]))
),
});
});