mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-26 12:26:38 -06:00
perf: cache bundled channel entry resolution
This commit is contained in:
@@ -404,6 +404,54 @@ describe("loadBundledEntryExportSync", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("reuses resolved bundled sidecar paths before cached module exports", async () => {
|
||||
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-channel-entry-contract-"));
|
||||
tempDirs.push(tempRoot);
|
||||
|
||||
const pluginRoot = path.join(tempRoot, "dist", "extensions", "telegram");
|
||||
fs.mkdirSync(pluginRoot, { recursive: true });
|
||||
|
||||
const importerPath = path.join(pluginRoot, "index.js");
|
||||
const helperPath = path.join(pluginRoot, "helper.cjs");
|
||||
fs.writeFileSync(importerPath, "export default {};\n", "utf8");
|
||||
fs.writeFileSync(helperPath, "module.exports = { sentinel: 42 };\n", "utf8");
|
||||
|
||||
const openRootFileSync = vi.fn(() => ({
|
||||
ok: true,
|
||||
path: helperPath,
|
||||
fd: fs.openSync(helperPath, "r"),
|
||||
}));
|
||||
vi.doMock("../infra/boundary-file-read.js", () => ({
|
||||
openRootFileSync,
|
||||
}));
|
||||
|
||||
try {
|
||||
const channelEntryContract = await importFreshModule<
|
||||
typeof import("./channel-entry-contract.js")
|
||||
>(import.meta.url, "./channel-entry-contract.js?scope=resolved-sidecar-cache");
|
||||
|
||||
const ref = {
|
||||
specifier: "./helper.cjs",
|
||||
exportName: "sentinel",
|
||||
};
|
||||
expect(
|
||||
channelEntryContract.loadBundledEntryExportSync<number>(
|
||||
pathToFileURL(importerPath).href,
|
||||
ref,
|
||||
),
|
||||
).toBe(42);
|
||||
expect(
|
||||
channelEntryContract.loadBundledEntryExportSync<number>(
|
||||
pathToFileURL(importerPath).href,
|
||||
ref,
|
||||
),
|
||||
).toBe(42);
|
||||
expect(openRootFileSync).toHaveBeenCalledTimes(1);
|
||||
} finally {
|
||||
vi.doUnmock("../infra/boundary-file-read.js");
|
||||
}
|
||||
});
|
||||
|
||||
it("emits non-negative source-loader sub-step timings on the built-artifact load path", async () => {
|
||||
// Built artifacts prefer `nodeRequire`, but Node can still reject a sidecar
|
||||
// and fall back through jiti. The profile line must never report negative
|
||||
|
||||
@@ -144,6 +144,8 @@ export type BundledEntryModuleLoadOptions = {
|
||||
|
||||
const nodeRequire = createRequire(import.meta.url);
|
||||
const moduleLoaders: PluginModuleLoaderCache = new Map();
|
||||
const entryBoundaryInfoCache = new Map<string, BundledEntryBoundaryInfo>();
|
||||
const resolvedModulePaths = new Map<string, string>();
|
||||
const loadedModuleExports = new Map<string, unknown>();
|
||||
const disableBundledEntrySourceFallbackEnv = "OPENCLAW_DISABLE_BUNDLED_ENTRY_SOURCE_FALLBACK";
|
||||
|
||||
@@ -174,6 +176,38 @@ type BundledEntryModuleCandidate = {
|
||||
boundaryRoot: string;
|
||||
};
|
||||
|
||||
type BundledEntryBoundaryInfo = {
|
||||
importerPath: string;
|
||||
importerDir: string;
|
||||
boundaryRoot: string;
|
||||
packageRoot: string | null;
|
||||
};
|
||||
|
||||
function resolveBundledEntryBoundaryInfo(importMetaUrl: string): BundledEntryBoundaryInfo {
|
||||
const cacheKey = `${process.argv[1] ?? ""}\0${importMetaUrl}`;
|
||||
const cached = entryBoundaryInfoCache.get(cacheKey);
|
||||
if (cached) {
|
||||
return cached;
|
||||
}
|
||||
const importerPath = fileURLToPath(importMetaUrl);
|
||||
const importerDir = path.dirname(importerPath);
|
||||
const boundaryRoot = path.dirname(importerPath);
|
||||
const info = {
|
||||
importerPath,
|
||||
importerDir,
|
||||
boundaryRoot,
|
||||
packageRoot:
|
||||
resolveLoaderPackageRoot({
|
||||
modulePath: importerPath,
|
||||
moduleUrl: importMetaUrl,
|
||||
cwd: importerDir,
|
||||
argv1: process.argv[1],
|
||||
}) ?? null,
|
||||
};
|
||||
entryBoundaryInfoCache.set(cacheKey, info);
|
||||
return info;
|
||||
}
|
||||
|
||||
function addBundledEntryCandidates(
|
||||
candidates: BundledEntryModuleCandidate[],
|
||||
basePath: string,
|
||||
@@ -193,9 +227,8 @@ function resolveBundledEntryModuleCandidates(
|
||||
importMetaUrl: string,
|
||||
specifier: string,
|
||||
): BundledEntryModuleCandidate[] {
|
||||
const importerPath = fileURLToPath(importMetaUrl);
|
||||
const importerDir = path.dirname(importerPath);
|
||||
const boundaryRoot = resolveEntryBoundaryRoot(importMetaUrl);
|
||||
const { importerPath, importerDir, boundaryRoot, packageRoot } =
|
||||
resolveBundledEntryBoundaryInfo(importMetaUrl);
|
||||
const candidates: BundledEntryModuleCandidate[] = [];
|
||||
const primaryResolved = path.resolve(importerDir, specifier);
|
||||
addBundledEntryCandidates(candidates, primaryResolved, boundaryRoot);
|
||||
@@ -209,12 +242,6 @@ function resolveBundledEntryModuleCandidates(
|
||||
);
|
||||
}
|
||||
|
||||
const packageRoot = resolveLoaderPackageRoot({
|
||||
modulePath: importerPath,
|
||||
moduleUrl: importMetaUrl,
|
||||
cwd: importerDir,
|
||||
argv1: process.argv[1],
|
||||
});
|
||||
if (!packageRoot) {
|
||||
return candidates;
|
||||
}
|
||||
@@ -282,7 +309,17 @@ function formatBundledEntryModuleOpenFailure(params: {
|
||||
].join(" ");
|
||||
}
|
||||
|
||||
function createBundledEntryModulePathCacheKey(importMetaUrl: string, specifier: string): string {
|
||||
const sourceFallbackDisabled = isTruthyEnvFlag(process.env[disableBundledEntrySourceFallbackEnv]);
|
||||
return `${sourceFallbackDisabled ? "1" : "0"}\0${importMetaUrl}\0${specifier}`;
|
||||
}
|
||||
|
||||
function resolveBundledEntryModulePath(importMetaUrl: string, specifier: string): string {
|
||||
const cacheKey = createBundledEntryModulePathCacheKey(importMetaUrl, specifier);
|
||||
const cached = resolvedModulePaths.get(cacheKey);
|
||||
if (cached) {
|
||||
return cached;
|
||||
}
|
||||
const candidates = resolveBundledEntryModuleCandidates(importMetaUrl, specifier);
|
||||
const fallbackCandidate = candidates[0] ?? {
|
||||
path: path.resolve(path.dirname(fileURLToPath(importMetaUrl)), specifier),
|
||||
@@ -304,6 +341,7 @@ function resolveBundledEntryModulePath(importMetaUrl: string, specifier: string)
|
||||
});
|
||||
if (opened.ok) {
|
||||
fs.closeSync(opened.fd);
|
||||
resolvedModulePaths.set(cacheKey, opened.path);
|
||||
return opened.path;
|
||||
}
|
||||
firstFailure ??= { candidate, failure: opened };
|
||||
|
||||
Reference in New Issue
Block a user