mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-11 06:30:03 +00:00
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:
@@ -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`);
|
||||
|
||||
Reference in New Issue
Block a user