fix(natives): refresh active cache directories

(cherry picked from commit c62702b89d1f29bc48067d64575c739c65456bc8)
This commit is contained in:
can1357
2026-08-05 02:27:08 +02:00
parent 817a3648f9
commit f687a074d8
3 changed files with 21 additions and 2 deletions
+2
View File
@@ -88,6 +88,8 @@ export interface CleanupStaleNativeVersionsInput {
export function cleanupStaleNativeVersions(input: CleanupStaleNativeVersionsInput): string[];
export function prepareNativeVersionDir(versionedDir: string): void;
export interface ExtractEmbeddedAddonArchiveInput {
archivePath: string;
files: EmbeddedAddonFile[];
+16 -2
View File
@@ -202,6 +202,20 @@ function isOlderReleaseVersion(candidate, current) {
// stale.
const NATIVE_CACHE_CLEANUP_GRACE_MS = 10 * 60_000;
/**
* Create a version cache directory and refresh its activity timestamp before
* extraction or staging begins. Recursive mkdir does not update the mtime of
* an existing directory, so the explicit touch is what protects interrupted
* or partially populated caches from concurrent cleanup.
*
* @param {string} versionedDir
*/
export function prepareNativeVersionDir(versionedDir) {
fs.mkdirSync(versionedDir, { recursive: true });
const now = new Date();
fs.utimesSync(versionedDir, now, now);
}
/**
* Remove version-pinned native cache directories older than the loaded package.
* Best-effort by design: permission errors and concurrent processes must not
@@ -522,7 +536,7 @@ function maybeExtractEmbeddedAddon(ctx, errors) {
startupMarker("native:extractEmbeddedAddon:start");
try {
fs.mkdirSync(ctx.versionedDir, { recursive: true });
prepareNativeVersionDir(ctx.versionedDir);
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
errors.push(`embedded addon dir: ${message}`);
@@ -589,7 +603,7 @@ function maybeStageNodeModulesAddon(ctx, errors) {
if (!fs.existsSync(sourcePath)) continue;
try {
fs.mkdirSync(ctx.versionedDir, { recursive: true });
prepareNativeVersionDir(ctx.versionedDir);
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
errors.push(`staged addon dir: ${message}`);
@@ -27,6 +27,7 @@ import {
cleanupStaleNativeVersions,
getAddonFilenames,
initLoaderContext,
prepareNativeVersionDir,
resolveLoaderCandidates,
shouldStageNodeModulesAddon,
} from "../native/loader-state.js";
@@ -205,6 +206,8 @@ describe("windows native addon staging", () => {
await fs.mkdir(path.join(nativesDir, "not-a-version"));
await Bun.write(path.join(nativesDir, "README.txt"), "not a version directory");
await fs.utimes(path.join(nativesDir, staleVersion), new Date(0), new Date(0));
await fs.utimes(path.join(nativesDir, freshVersion), new Date(0), new Date(0));
prepareNativeVersionDir(path.join(nativesDir, freshVersion));
const removed = cleanupStaleNativeVersions({ nativesDir, currentVersion: packageJson.version });