You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bull队列:如何标记任务为失败并实现手动重试?

问题

我司采用Bull队列系统接收API请求,待每个请求完成后依次转发至ERP系统(避免用户批量发起请求导致ERP崩溃)。当前ERP处理API命令失败时,任务会被标记为Bull队列的「已完成」状态,仅自定义失败标识。

现需实现:

  1. 当ERP处理失败时,将对应任务标记为Bull的「失败」状态,且不影响其他任务执行;
  2. 支持手动重试失败任务(需用户手动调整后重试,而非自动重试)。

查看Bull文档得知done回调可传入Error实例标记任务失败,但无示例。现有处理代码如下:

queue.process(async (job, done) => {
    switch (job.data.type) {
      case 'API_Type':
        const workOrder = await createWorkOrder(job.data)
        socketService.emiter('API_Type', workOrder, job.data.socketId)
        workOrder.status === 'success' ? done(null, workOrder) : placeJobInFailedStatus
        break
      //...
      default:
        done()
    }
  })

请问如何替换代码中的placeJobInFailedStatus以标记任务为失败状态?另外,Bull是否原生支持手动重试失败任务?文档中的job.retry和job.promote如何调用?是否需自行实现重试逻辑?

解决方案

一、替换placeJobInFailedStatus标记任务失败

直接调用done回调并传入Error实例即可,Bull会自动将该任务标记为失败状态,且不会影响其他任务执行(Bull的任务是独立隔离处理的)。

修改后的代码片段如下:

queue.process(async (job, done) => {
    switch (job.data.type) {
      case 'API_Type':
        const workOrder = await createWorkOrder(job.data)
        socketService.emiter('API_Type', workOrder, job.data.socketId)
        if (workOrder.status === 'success') {
          done(null, workOrder)
        } else {
          // 传入Error实例,可携带ERP返回的失败详情
          done(new Error(`ERP处理失败: ${workOrder.errorMsg || '未知错误'}`))
        }
        break
      //...
      default:
        done()
    }
  })

这里用if-else替代三元表达式可读性更强,Error消息可以根据实际场景传入具体失败信息,方便后续排查问题。

二、Bull原生支持手动重试失败任务,无需自行实现核心逻辑

Bull提供了现成API处理失败任务的手动重试,具体用法如下:

  1. 获取失败任务
    先从队列中查询失败任务列表,或根据任务ID直接获取单个任务:

    // 获取所有失败任务,可添加过滤条件(如按类型、时间范围)
    const failedJobs = await queue.getFailed()
    // 根据任务ID获取单个失败任务
    const failedJob = await queue.getJob('任务ID')
    
  2. 调用job.retry()发起重试
    获取到失败任务后,直接调用retry()即可将任务重新放回待处理队列。如果需要在重试前修改任务数据(比如用户调整了参数),可以先更新数据再重试:

    // 示例:修改任务参数后重试
    failedJob.data = { ...failedJob.data, targetParam: '新参数值' }
    await failedJob.save()
    // 发起重试
    await failedJob.retry()
    
  3. job.promote()的作用
    promote()主要用于将被延迟(delayed)的任务提前加入待处理队列,一般手动重试失败任务时不需要调用。只有当重试后的任务处于延迟状态时,才需要用它立即触发处理。

内容的提问来源于stack exchange,提问作者Ben in CA

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 14:35:20