fix(media-use): clean failed asset reservations (#2627)

* fix(media-use): clean failed asset reservations

* test(media-use): pin installer guidance exactly
This commit is contained in:
Miguel Ángel
2026-07-18 04:36:36 -04:00
committed by GitHub
parent 7f76170956
commit 49113eb084
8 changed files with 306 additions and 95 deletions
+68 -54
View File
@@ -4,7 +4,14 @@ import { spawnSync } from "node:child_process";
import { existsSync, statSync, writeFileSync, renameSync, rmSync } from "node:fs";
import { resolve, join, extname, basename } from "node:path";
import { parseArgs } from "node:util";
import { appendRecord, findByPrompt, findByEntity, nextId, allocateId } from "./lib/manifest.mjs";
import {
appendRecord,
findByPrompt,
findByEntity,
nextId,
withReservedFile,
withReservedFileSync,
} from "./lib/manifest.mjs";
import { regenerateIndex } from "./lib/index-gen.mjs";
import { cacheGet, cacheGetByEntity, importFromCache, cachePut } from "./lib/cache.mjs";
import { runCapability, listTypes, providerMatches, providerNamesFor } from "./lib/registry.mjs";
@@ -326,10 +333,8 @@ async function run() {
const cacheHit = forced ? null : cacheGet(intent, type);
if (cacheHit) {
const ext = extname(cacheHit.cached_path);
const { id, localPath } = allocateId(projectDir, type, ext);
const imported = localizeImportedRecord(
importFromCache(cacheHit, projectDir, id, localPath),
localPath,
const imported = withReservedFileSync(projectDir, type, ext, ({ id, localPath }) =>
localizeImportedRecord(importFromCache(cacheHit, projectDir, id, localPath), localPath),
);
if (imported) {
appendRecord(projectDir, imported);
@@ -342,10 +347,11 @@ async function run() {
const entityCacheHit = cacheGetByEntity(entity);
if (entityCacheHit && typesMatch(entityCacheHit.type, type)) {
const ext = extname(entityCacheHit.cached_path);
const { id, localPath } = allocateId(projectDir, type, ext);
const imported = localizeImportedRecord(
importFromCache(entityCacheHit, projectDir, id, localPath),
localPath,
const imported = withReservedFileSync(projectDir, type, ext, ({ id, localPath }) =>
localizeImportedRecord(
importFromCache(entityCacheHit, projectDir, id, localPath),
localPath,
),
);
if (imported) {
appendRecord(projectDir, imported);
@@ -456,17 +462,21 @@ async function run() {
// 5. freeze + register (atomic id+file reservation so concurrent resolves
// can't collide on an id during the download — MU-23)
const ext = searchResult.ext || extFromUrl(searchResult.url || "") || defaultExt(type);
const { id, localPath } = allocateId(projectDir, type, ext);
const fullPath = join(projectDir, localPath);
if (searchResult.localPath) {
freezeLocalFile(searchResult.localPath, fullPath);
} else if (searchResult.url) {
await freezeUrl(searchResult.url, fullPath);
} else {
console.error("error: provider returned no url or localPath");
process.exit(1);
}
const { id, localPath, fullPath } = await withReservedFile(
projectDir,
type,
ext,
async (reservation) => {
if (searchResult.localPath) {
freezeLocalFile(searchResult.localPath, reservation.fullPath);
} else if (searchResult.url) {
await freezeUrl(searchResult.url, reservation.fullPath);
} else {
throw new Error("provider returned no url or localPath");
}
return reservation;
},
);
const record = {
id,
@@ -545,32 +555,32 @@ function freezeGeneratedLut(
validationErrorPrefix = "generated LUT failed validation",
},
) {
const { id, localPath } = allocateId(projectDir, type, ".cube");
const fullPath = join(projectDir, localPath);
const tmpPath = `${fullPath}.tmp`;
try {
// Write + validate at .tmp, then atomic rename, so a crash between write and
// validate can't leave an invalid .cube at the final path.
writeFileSync(tmpPath, buildCube(params));
const check = validateCubeFile(tmpPath);
if (!check.ok) throw new Error(check.error);
renameSync(tmpPath, fullPath);
} catch (err) {
rmSync(tmpPath, { force: true });
throw new Error(`${validationErrorPrefix}: ${err.message}`);
}
return {
id,
localPath,
fullPath,
lut: { src: localPath, intensity: 1 },
source: "generated",
description,
metadata: {
provider: "cube_lut.builder",
provenance: { params },
},
};
return withReservedFileSync(projectDir, type, ".cube", ({ id, localPath, fullPath }) => {
const tmpPath = `${fullPath}.tmp`;
try {
// Write + validate at .tmp, then atomic rename, so a crash between write and
// validate can't leave an invalid .cube at the final path.
writeFileSync(tmpPath, buildCube(params));
const check = validateCubeFile(tmpPath);
if (!check.ok) throw new Error(check.error);
renameSync(tmpPath, fullPath);
} catch (err) {
rmSync(tmpPath, { force: true });
throw new Error(`${validationErrorPrefix}: ${err.message}`);
}
return {
id,
localPath,
fullPath,
lut: { src: localPath, intensity: 1 },
source: "generated",
description,
metadata: {
provider: "cube_lut.builder",
provenance: { params },
},
};
});
}
function exitError(message, status = 1) {
@@ -818,10 +828,16 @@ async function ingest(src) {
process.exit(2);
}
const ext = extname(isUrl ? new URL(src).pathname : src) || defaultExt(type);
const { id, localPath } = allocateId(projectDir, type, ext);
const fullPath = join(projectDir, localPath);
if (isUrl) await freezeUrl(src, fullPath);
else freezeLocalFile(resolve(src), fullPath);
const { id, localPath, fullPath } = await withReservedFile(
projectDir,
type,
ext,
async (reservation) => {
if (isUrl) await freezeUrl(src, reservation.fullPath);
else freezeLocalFile(resolve(src), reservation.fullPath);
return reservation;
},
);
if (type === "lut" || type === "grade") {
try {
const check = validateCubeFile(fullPath);
@@ -1135,10 +1151,8 @@ async function reuseGlobal(shaArg) {
process.exit(2);
}
const ext = extname(rec.cached_path || "") || defaultExt(type);
const { id, localPath } = allocateId(projectDir, type, ext);
const imported = localizeImportedRecord(
importFromCache(rec, projectDir, id, localPath),
localPath,
const imported = withReservedFileSync(projectDir, type, ext, ({ id, localPath }) =>
localizeImportedRecord(importFromCache(rec, projectDir, id, localPath), localPath),
);
if (!imported) {
console.error(`error: cache entry for "${shaArg}" is incomplete or missing on disk`);