fix: Found one bug in the new compile-cache prune path: it removes a d (#74067)

* fix: Found one bug in the new compile-cache prune path: it removes a d

* fix(postinstall): keep compile cache pruning resilient

---------

Co-authored-by: openclaw-clownfish[bot] <280122609+openclaw-clownfish[bot]@users.noreply.github.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
This commit is contained in:
openclaw-clownfish[bot]
2026-04-29 01:12:59 -07:00
committed by GitHub
parent 4d43daa7bb
commit 1a936f225e
2 changed files with 80 additions and 14 deletions

View File

@@ -104,6 +104,7 @@ const BAILEYS_MEDIA_DISPATCHER_HEADER_REPLACEMENT = [
const BAILEYS_MEDIA_ONCE_IMPORT_RE = /import\s+\{\s*once\s*\}\s+from\s+['"]events['"]/u;
const BAILEYS_MEDIA_ASYNC_CONTEXT_RE =
/async\s+function\s+encryptedStream|encryptedStream\s*=\s*async/u;
const NODE_COMPILE_CACHE_VERSION_DIR_RE = /^v\d+\.\d+\.\d+-/u;
function hasEnvFlag(env, key) {
const value = env?.[key]?.trim().toLowerCase();
@@ -865,6 +866,7 @@ function shouldRunBundledPluginPostinstall(params) {
export function pruneOpenClawCompileCache(params = {}) {
const env = params.env ?? process.env;
const pathExists = params.existsSync ?? existsSync;
const readDir = params.readdirSync ?? readdirSync;
const remove = params.rmSync ?? rmSync;
const log = params.log ?? console;
const baseDirs = [
@@ -873,12 +875,25 @@ export function pruneOpenClawCompileCache(params = {}) {
].filter((value, index, values) => value && values.indexOf(value) === index);
for (const baseDir of baseDirs) {
const cacheRoot = join(baseDir, "openclaw");
if (!pathExists(cacheRoot)) {
if (!pathExists(baseDir)) {
continue;
}
try {
remove(cacheRoot, { recursive: true, force: true, maxRetries: 2, retryDelay: 100 });
for (const entry of readDir(baseDir, { withFileTypes: true })) {
if (!entry.isDirectory() || !NODE_COMPILE_CACHE_VERSION_DIR_RE.test(entry.name)) {
continue;
}
try {
remove(join(baseDir, entry.name), {
recursive: true,
force: true,
maxRetries: 2,
retryDelay: 100,
});
} catch (error) {
log.warn?.(`[postinstall] could not prune OpenClaw compile cache: ${String(error)}`);
}
}
} catch (error) {
log.warn?.(`[postinstall] could not prune OpenClaw compile cache: ${String(error)}`);
}

View File

@@ -1,4 +1,5 @@
import fs from "node:fs/promises";
import { tmpdir } from "node:os";
import path from "node:path";
import { describe, expect, it, vi } from "vitest";
import {
@@ -181,29 +182,79 @@ describe("bundled plugin postinstall", () => {
expect(spawnSync).not.toHaveBeenCalled();
});
it("prunes OpenClaw compile cache during package postinstall", () => {
it("prunes Node versioned compile cache dirs during package postinstall", () => {
const configuredBase = path.join("/tmp", "openclaw-cache");
const defaultBase = path.join(tmpdir(), "node-compile-cache");
const removed: string[] = [];
const existsSync = vi.fn((value: string) =>
value.endsWith(path.join("openclaw-cache", "openclaw")),
);
const existsSync = vi.fn((value: string) => value === configuredBase || value === defaultBase);
const readdirSync = vi.fn((value: string) => {
if (value === configuredBase) {
return [
{ name: "v22.13.1-x64-efe9a9df-1001", isDirectory: () => true },
{ name: "openclaw", isDirectory: () => true },
{ name: "README", isDirectory: () => false },
];
}
if (value === defaultBase) {
return [{ name: "v24.14.1-x64-efe9a9df-1001", isDirectory: () => true }];
}
throw new Error(`unexpected readdir: ${value}`);
});
const rmSync = vi.fn((value: string) => {
removed.push(value);
});
pruneOpenClawCompileCache({
env: { NODE_COMPILE_CACHE: path.join("/tmp", "openclaw-cache") },
env: { NODE_COMPILE_CACHE: configuredBase },
existsSync,
readdirSync,
rmSync,
log: { warn: vi.fn() },
});
expect(removed).toEqual([path.join("/tmp", "openclaw-cache", "openclaw")]);
expect(rmSync).toHaveBeenCalledWith(path.join("/tmp", "openclaw-cache", "openclaw"), {
recursive: true,
force: true,
maxRetries: 2,
retryDelay: 100,
expect(removed).toEqual([
path.join(configuredBase, "v22.13.1-x64-efe9a9df-1001"),
path.join(defaultBase, "v24.14.1-x64-efe9a9df-1001"),
]);
expect(removed).not.toContain(path.join(configuredBase, "openclaw"));
for (const cacheDir of removed) {
expect(rmSync).toHaveBeenCalledWith(cacheDir, {
recursive: true,
force: true,
maxRetries: 2,
retryDelay: 100,
});
}
});
it("keeps pruning sibling compile cache dirs after one removal fails", () => {
const configuredBase = path.join("/tmp", "openclaw-cache");
const attempted: string[] = [];
const warn = vi.fn();
const firstCacheDir = path.join(configuredBase, "v22.13.1-x64-efe9a9df-1001");
const secondCacheDir = path.join(configuredBase, "v22.13.1-x64-efe9a9df-1002");
const rmSync = vi.fn((value: string) => {
attempted.push(value);
if (value === firstCacheDir) {
throw new Error("locked");
}
});
pruneOpenClawCompileCache({
env: { NODE_COMPILE_CACHE: configuredBase },
existsSync: vi.fn((value: string) => value === configuredBase),
readdirSync: vi.fn(() => [
{ name: path.basename(firstCacheDir), isDirectory: () => true },
{ name: path.basename(secondCacheDir), isDirectory: () => true },
]),
rmSync,
log: { warn },
});
expect(attempted).toEqual([firstCacheDir, secondCacheDir]);
expect(warn).toHaveBeenCalledWith(
"[postinstall] could not prune OpenClaw compile cache: Error: locked",
);
});
it("prunes source-checkout bundled plugin node_modules", async () => {