fix(media): clean expired files in subdirectories

cleanOldMedia() only scanned the top-level media directory, but
saveMediaBuffer() writes to subdirs (inbound/, outbound/, browser/).
Files in those subdirs were never cleaned up.

Now recurses one level into subdirectories, deleting expired files
while preserving the subdirectory folders themselves.
This commit is contained in:
Hudson
2026-02-16 15:23:02 -05:00
committed by Peter Steinberger
parent c89eb351ea
commit 441401221d
2 changed files with 36 additions and 1 deletions

View File

@@ -102,6 +102,21 @@ describe("media store", () => {
});
});
it("cleans old media files in first-level subdirectories", async () => {
await withTempStore(async (store) => {
const saved = await store.saveMediaBuffer(Buffer.from("nested"), "text/plain", "inbound");
const inboundDir = path.dirname(saved.path);
const past = Date.now() - 10_000;
await fs.utimes(saved.path, past / 1000, past / 1000);
await store.cleanOldMedia(1);
await expect(fs.stat(saved.path)).rejects.toThrow();
const inboundStat = await fs.stat(inboundDir);
expect(inboundStat.isDirectory()).toBe(true);
});
});
it("sets correct mime for xlsx by extension", async () => {
await withTempStore(async (store, home) => {
const xlsxPath = path.join(home, "sheet.xlsx");

View File

@@ -88,6 +88,22 @@ export async function cleanOldMedia(ttlMs = DEFAULT_TTL_MS) {
const mediaDir = await ensureMediaDir();
const entries = await fs.readdir(mediaDir).catch(() => []);
const now = Date.now();
const removeExpiredFilesInDir = async (dir: string) => {
const dirEntries = await fs.readdir(dir).catch(() => []);
await Promise.all(
dirEntries.map(async (entry) => {
const full = path.join(dir, entry);
const stat = await fs.stat(full).catch(() => null);
if (!stat || !stat.isFile()) {
return;
}
if (now - stat.mtimeMs > ttlMs) {
await fs.rm(full).catch(() => {});
}
}),
);
};
await Promise.all(
entries.map(async (file) => {
const full = path.join(mediaDir, file);
@@ -95,7 +111,11 @@ export async function cleanOldMedia(ttlMs = DEFAULT_TTL_MS) {
if (!stat) {
return;
}
if (now - stat.mtimeMs > ttlMs) {
if (stat.isDirectory()) {
await removeExpiredFilesInDir(full);
return;
}
if (stat.isFile() && now - stat.mtimeMs > ttlMs) {
await fs.rm(full).catch(() => {});
}
}),