← 中文资源

简体中文版本

失败任务死信队列

对失败任务进行有限次重试,超过上限后移入可检查的死信队列,并记录错误信息与失败时间。

阅读英文原文

功能说明

后台任务失败后立即丢弃会丢失数据,无限重试又会阻塞队列。该队列在内存中重试任务,达到最大次数后移入死信队列,记录错误信息与失败时间,便于人工检查或补偿。它适合邮件发送、Webhook 投递和批量导入等需要保留失败现场的场景。

关键代码

Job 保存 id、payload 与尝试次数。drain 循环取出任务并递增 attempts,成功计入 processed;失败且未达上限时重新入队,达到上限则写入 deadLetters。maxAttempts 与时钟均可注入,便于测试。listDeadLetters 返回副本,避免外部直接修改内部数组。

if (job.attempts < this.maxAttempts) {
  this.pending.push(job);
} else {
  this.deadLetters.push({ job, error: message, failedAt: this.now() });
  deadLettered += 1;
}

使用注意

该实现是单进程内存队列,重启会丢失任务。重试没有退避延迟,可能快速耗尽次数。处理器应保证幂等,因为失败任务可能已产生部分副作用。死信只保存在内存中,生产环境应持久化到数据库或专用队列。drain 会一直处理到队列为空。

验证方式

断言处理器连续失败三次后任务进入死信,deadLetterCount 为 1,错误信息与时间被记录。maxAttempts 为 1 时首次失败即进入死信。成功任务使 processed 加一。maxAttempts 为 0 抛 RangeError,空 id 抛 TypeError,处理器非函数抛 TypeError。