feat(studio-server): bound the proxy cache with LRU accounting (#2588)

Adds cache accounting and bounded cleanup for transcoded proxies, and keeps
.transcode-cache out of git. Standalone: the transcoder consumes it next.
This commit is contained in:
Miguel Ángel
2026-07-16 21:05:08 -04:00
committed by GitHub
parent 9ca1e17101
commit 1d3d20450d
3 changed files with 245 additions and 0 deletions
@@ -0,0 +1,96 @@
import { existsSync, mkdirSync, mkdtempSync, rmSync, utimesSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import { cleanupProxyCache } from "./proxyCache.js";
const tempDirs: string[] = [];
function cacheDir(): string {
const root = mkdtempSync(join(tmpdir(), "hf-proxy-cache-"));
tempDirs.push(root);
const cache = join(root, ".transcode-cache");
mkdirSync(cache);
return cache;
}
function writeEntry(path: string, bytes: number, modifiedAt: number): void {
writeFileSync(path, Buffer.alloc(bytes));
const date = new Date(modifiedAt);
utimesSync(path, date, date);
}
afterEach(() => {
for (const dir of tempDirs.splice(0)) rmSync(dir, { recursive: true, force: true });
});
describe("cleanupProxyCache", () => {
it("removes idle and oldest entries until the cache is within its byte budget", () => {
const cache = cacheDir();
const now = 1_800_000_000_000;
const expired = join(cache, "expired.mp4");
const oldest = join(cache, "oldest.mp4");
const newest = join(cache, "newest.mp4");
writeEntry(expired, 4, now - 31 * 24 * 60 * 60 * 1000);
writeEntry(oldest, 6, now - 3_000);
writeEntry(newest, 6, now - 1_000);
const result = cleanupProxyCache(cache, {
now,
maxBytes: 8,
maxIdleMs: 30 * 24 * 60 * 60 * 1000,
minSweepIntervalMs: 0,
});
expect(result.removed).toEqual([expired, oldest]);
expect(result.bytesAfter).toBe(6);
expect(existsSync(expired)).toBe(false);
expect(existsSync(oldest)).toBe(false);
expect(existsSync(newest)).toBe(true);
});
it("preserves in-flight entries and removes stale temporary files", () => {
const cache = cacheDir();
const now = 1_800_000_000_000;
const inFlight = join(cache, "active.mp4");
const staleTemp = join(cache, ".tmp-crashed-active.mp4");
writeEntry(inFlight, 12, now - 40 * 24 * 60 * 60 * 1000);
writeEntry(staleTemp, 3, now - 2 * 60 * 60 * 1000);
const result = cleanupProxyCache(cache, {
now,
maxBytes: 1,
maxIdleMs: 30 * 24 * 60 * 60 * 1000,
staleTempMs: 60 * 60 * 1000,
minSweepIntervalMs: 0,
protectedPaths: new Set([inFlight]),
});
expect(result.removed).toEqual([staleTemp]);
expect(result.bytesAfter).toBe(12);
expect(existsSync(inFlight)).toBe(true);
});
it("rate-limits repeated directory sweeps", () => {
const cache = cacheDir();
const path = join(cache, "entry.mp4");
writeEntry(path, 2, 1_000);
const first = cleanupProxyCache(cache, {
now: 2_000,
maxBytes: 10,
maxIdleMs: 10_000,
minSweepIntervalMs: 5_000,
});
const second = cleanupProxyCache(cache, {
now: 3_000,
maxBytes: 1,
maxIdleMs: 10_000,
minSweepIntervalMs: 5_000,
});
expect(first.skipped).toBe(false);
expect(second.skipped).toBe(true);
expect(existsSync(path)).toBe(true);
});
});