gongxiangp2/lib/image-processing-limiter.ts
2026-07-31 10:40:00 +08:00

47 lines
1.3 KiB
TypeScript

const DEFAULT_MAX_CONCURRENT_IMAGE_JOBS = 1
const MAX_ALLOWED_IMAGE_JOBS = 2
function readMaxConcurrentImageJobs(): number {
const configured = Number.parseInt(process.env.IMAGE_PROCESSING_MAX_CONCURRENT || '', 10)
if (!Number.isFinite(configured)) {
return DEFAULT_MAX_CONCURRENT_IMAGE_JOBS
}
return Math.max(1, Math.min(MAX_ALLOWED_IMAGE_JOBS, configured))
}
const maxConcurrentImageJobs = readMaxConcurrentImageJobs()
let activeImageJobs = 0
const waitingImageJobs: Array<() => void> = []
async function acquireImageProcessingSlot(): Promise<void> {
if (activeImageJobs < maxConcurrentImageJobs) {
activeImageJobs += 1
return
}
await new Promise<void>((resolve) => waitingImageJobs.push(resolve))
activeImageJobs += 1
}
function releaseImageProcessingSlot(): void {
activeImageJobs = Math.max(0, activeImageJobs - 1)
const next = waitingImageJobs.shift()
if (next) {
next()
}
}
/**
* 跨请求限制 Sharp 任务数。单个请求内串行并不能阻止多个请求同时解码大图,
* 所以白底图、预览图和长图处理都必须共用这个进程级门闩。
*/
export async function withImageProcessingSlot<T>(task: () => Promise<T>): Promise<T> {
await acquireImageProcessingSlot()
try {
return await task()
} finally {
releaseImageProcessingSlot()
}
}