fix: dedupe concurrent watermark rendering

This commit is contained in:
FengLee
2026-06-06 00:09:03 +08:00
parent 23c13f8274
commit 2dfbd7098e
2 changed files with 29 additions and 0 deletions

View File

@@ -111,6 +111,14 @@ await runTest('image watermark renderer visibly changes raster media', async ()
assert.equal(metadata.height, 360);
});
await runTest('watermark renderer dedupes concurrent generation for the same media', () => {
const source = read('src/lib/media-watermark.ts');
assert.match(source, /inflightWatermarkJobs/);
assert.match(source, /inflightWatermarkJobs\.get\(outputKey\)/);
assert.match(source, /inflightWatermarkJobs\.delete\(outputKey\)/);
});
await runTest('local storage route uses watermark access instead of exposing raw object URLs by default', () => {
const source = read('src/app/api/local-storage/[...path]/route.ts');

View File

@@ -13,6 +13,11 @@ import {
const WATERMARK_LOGO_PATH = path.join(process.cwd(), 'public', 'watermark', 'miaojing-watermark-logo.png');
const WATERMARK_TEXT = 'MIAOJING AI';
const WATERMARK_OPACITY = 0.5;
const inflightWatermarkJobs = new Map<string, Promise<{
key: string;
buffer: Buffer;
contentType: string;
}>>();
export async function serveWatermarkedStorageFile(key: string, contentType: string): Promise<{
key: string;
@@ -59,7 +64,23 @@ async function createWatermarkedFile(key: string, contentType: string): Promise<
contentType,
};
}
const inflight = inflightWatermarkJobs.get(outputKey);
if (inflight) return inflight;
const job = createWatermarkedFileUncached(key, contentType, outputKey);
inflightWatermarkJobs.set(outputKey, job);
try {
return await job;
} finally {
inflightWatermarkJobs.delete(outputKey);
}
}
async function createWatermarkedFileUncached(key: string, contentType: string, outputKey: string): Promise<{
key: string;
buffer: Buffer;
contentType: string;
}> {
const kind = getMediaKindFromContentType(key, contentType);
if (kind === 'image') {
const input = await localStorage.readFileAsync(key);