fix: retry media materialization after cleanup race

This commit is contained in:
Peter Steinberger
2026-05-16 05:05:25 +01:00
parent 779266ce1d
commit 2a54becd27
2 changed files with 44 additions and 11 deletions

View File

@@ -303,6 +303,37 @@ describe("media store", () => {
});
},
},
{
name: "retries buffer materialization when cleanup prunes the target dir",
run: async () => {
await withTempStore(async (store) => {
const originalMkdir = fs.mkdir.bind(fs);
let pruned = false;
vi.spyOn(fs, "mkdir").mockImplementation(async (...args) => {
const result = await originalMkdir(...args);
const target = args[0];
if (
!pruned &&
typeof target === "string" &&
path.normalize(target).endsWith(`${path.sep}media${path.sep}materialization-race`)
) {
pruned = true;
await fs.rm(target, { force: true, recursive: true });
}
return result;
});
const saved = await store.saveMediaBuffer(
Buffer.from("race bytes"),
"text/plain",
"materialization-race",
);
expect(pruned).toBe(true);
await expect(fs.readFile(saved.path, "utf8")).resolves.toBe("race bytes");
});
},
},
{
name: "rejects traversal media subdirs before saving buffers",
run: async () => {

View File

@@ -661,18 +661,20 @@ async function materializeMediaBufferPath(params: {
buffer: Buffer;
}): Promise<string> {
const dir = resolveMediaScopedDir(params.subdir, "materializeMediaBufferPath");
await fs.mkdir(dir, { recursive: true, mode: 0o700 });
const written = await writeSiblingTempFile({
dir,
mode: MEDIA_FILE_MODE,
tempPrefix: `.${params.id}`,
writeTemp: async (tempPath) => {
await fs.writeFile(tempPath, params.buffer, { mode: MEDIA_FILE_MODE });
return undefined;
},
resolveFinalPath: () => path.join(dir, params.id),
return await retryAfterRecreatingDir(dir, async () => {
await fs.mkdir(dir, { recursive: true, mode: 0o700 });
const written = await writeSiblingTempFile({
dir,
mode: MEDIA_FILE_MODE,
tempPrefix: `.${params.id}`,
writeTemp: async (tempPath) => {
await fs.writeFile(tempPath, params.buffer, { mode: MEDIA_FILE_MODE });
return undefined;
},
resolveFinalPath: () => path.join(dir, params.id),
});
return written.filePath;
});
return written.filePath;
}
async function writeMediaStreamToFile(params: {