背景与价值后台队列易出现重复与泄漏。统一重试、去重与TTL策略可保障稳定与可控。统一规范去重:基于任务键与窗口去重。重试:指数退避与上限控制,记录尝试数。泄漏防护:TTL到期清理,超时任务回收。核心实现队列与去重type Job = { id: string; key: string; payload: any; attempts: number; ttlMs: number; enqueuedAt: number }
class Queue {
list: Job[] = []
seen = new Map<string, number>()
now(): number { return Date.now() }
enqueue(key: string, payload: any, ttlMs = 600000): Job | null {
const last = this.seen.get(key) || 0
if (this.now() - last < 30000) return null
const j: Job = { id: Math.random().toString(36).slice(2), key, payload, attempts: 0, ttlMs, enqueuedAt: this.now() }
this.list.push(j)
this.seen.set(key, this.now())
return j
}
dequeue(): Job | undefined { const j = this.list.shift(); return j }
cleanup() { this.list = this.list.filter(j => this.now() - j.enqueuedAt <= j.ttlMs) }
}
重试与退避function backoff(baseMs: number, attempt: number, maxMs: number): number { const exp = Math.min(maxMs, baseMs * Math.pow(2, attempt)); const jitter = Math.random() * exp * 0.5; return Math.floor(exp * 0.75 + jitter) }
async function runJob(job: Job, handler: (p: any) => Promise<void>, baseMs = 100, maxMs = 5000, maxAttempts = 5): Promise<boolean> {
let ok = false
for (let i = 0; i < maxAttempts; i++) {
try { await handler(job.payload); ok = true; break } catch { const delay = backoff(baseMs, i, maxMs); await new Promise(r => setTimeout(r, delay)); job.attempts++ }
}
return ok
}
落地建议为后台任务引入去重窗口与TTL治理,避免重复与泄漏。使用指数退避与尝试上限,记录尝试数用于审计与优化。验证清单同键任务是否在窗口内去重;TTL到期是否清理;重试是否有上限与退避。

发表评论 取消回复