fix: preserve live runtime dependency locks

This commit is contained in:
Peter Steinberger
2026-04-24 20:39:09 +01:00
parent 56e299cbca
commit d43b3b3b70
2 changed files with 33 additions and 9 deletions

View File

@@ -4,6 +4,7 @@ import os from "node:os";
import path from "node:path";
import { afterEach, describe, expect, it, vi } from "vitest";
import {
__testing as bundledRuntimeDepsTesting,
createBundledRuntimeDependencyAliasMap,
createBundledRuntimeDepsInstallArgs,
createBundledRuntimeDepsInstallEnv,
@@ -656,6 +657,16 @@ describe("ensureBundledPluginRuntimeDeps", () => {
]);
});
it("does not expire active runtime-deps install locks by age alone", () => {
expect(
bundledRuntimeDepsTesting.shouldRemoveRuntimeDepsLock(
{ pid: 123, createdAtMs: 0 },
Number.MAX_SAFE_INTEGER,
() => true,
),
).toBe(false);
});
it("removes stale runtime-deps install locks before repairing deps", () => {
const packageRoot = makeTempDir();
const pluginRoot = path.join(packageRoot, "dist", "extensions", "openai");
@@ -670,10 +681,7 @@ describe("ensureBundledPluginRuntimeDeps", () => {
);
const lockDir = path.join(pluginRoot, ".openclaw-runtime-deps.lock");
fs.mkdirSync(lockDir, { recursive: true });
fs.writeFileSync(
path.join(lockDir, "owner.json"),
JSON.stringify({ pid: process.pid, createdAtMs: 0 }),
);
fs.writeFileSync(path.join(lockDir, "owner.json"), JSON.stringify({ pid: 0, createdAtMs: 0 }));
const calls: BundledRuntimeDepsInstallParams[] = [];
const result = ensureBundledPluginRuntimeDeps({

View File

@@ -199,15 +199,31 @@ function readRuntimeDepsLockOwner(lockDir: string): { pid?: number; createdAtMs?
};
}
function shouldRemoveRuntimeDepsLock(
owner: { pid?: number; createdAtMs?: number },
nowMs: number,
isAlive: (pid: number) => boolean = isProcessAlive,
): boolean {
if (typeof owner.pid === "number") {
return !isAlive(owner.pid);
}
return (
typeof owner.createdAtMs === "number" &&
nowMs - owner.createdAtMs > BUNDLED_RUNTIME_DEPS_LOCK_STALE_MS
);
}
export const __testing = {
shouldRemoveRuntimeDepsLock,
};
function removeRuntimeDepsLockIfStale(lockDir: string, nowMs: number): boolean {
const owner = readRuntimeDepsLockOwner(lockDir);
const createdAtMs = owner.createdAtMs;
const staleByTime =
typeof createdAtMs === "number" && nowMs - createdAtMs > BUNDLED_RUNTIME_DEPS_LOCK_STALE_MS;
const staleByPid = typeof owner.pid === "number" && !isProcessAlive(owner.pid);
if (!staleByTime && !staleByPid) {
if (!shouldRemoveRuntimeDepsLock(owner, nowMs)) {
return false;
}
try {
fs.rmSync(lockDir, { recursive: true, force: true });
return true;