Picset/文章中心/AI玩法
AI玩法

批量出图别无限重试:实现有限并发的任务执行器

批量图片任务可以用有限并发执行器保留逐项结果,并只重试明确标为暂时性的错误。下面实现并发上限、最大尝试次数与原输入顺序结果。它不调用模型接口,不取消外部请求,也不具备进程重启恢复能力,适合解释任务控制,不能直接当完整生产队列。

Picset 内容研究组 · 发布/核验于 2026年10月9日 · 约 3 分钟阅读
批量出图别无限重试:实现有限并发的任务执行器
简要回答

批量图片任务可以用有限并发执行器保留逐项结果,并只重试明确标为暂时性的错误。下面实现并发上限、最大尝试次数与原输入顺序结果。它不调用模型接口,不取消外部请求,也不具备进程重启恢复能力,适合解释任务控制,不能直接当完整生产队列。

  批量图片任务可以用有限并发执行器保留逐项结果,并只重试明确标为暂时性的错误。下面实现并发上限、最大尝试次数与原输入顺序结果。它不调用模型接口,不取消外部请求,也不具备进程重启恢复能力,适合解释任务控制,不能直接当完整生产队列。

  如果一个任务失败后无限重试,会占住工作位置,也可能重复触发付费请求。若只有一张图失败就终止全部,则其他商品被无必要阻塞。执行器应该为每项记录fulfilled或rejected,让批次汇总保留可追查的身份,再由上层决定下一步。

将任务作为函数传入

  tasks是异步函数数组,limit和maxAttempts必须是正整数。每个worker取出一个输入序号,在完成或放弃后继续下一项。结果写回原序号,因此完成快慢不会改变商品与结果的对应。实际业务还应在外层绑定稳定任务id,不能只依靠数组下标跨批次识别。

批量出图别无限重试:实现有限并发的任务执行器:并发上限、有限重试、逐项结果示意
并发上限 · 有限重试 · 逐项结果
export async function runLimited(tasks,limit=2,maxAttempts=2) {
  if (!Number.isInteger(limit)||limit<1||!Number.isInteger(maxAttempts)||maxAttempts<1) throw Error('limits');
  let cursor=0;
  const results=new Array(tasks.length);
  async function worker() {
    while (cursor<tasks.length) {
      const i=cursor++; let last;
      for (let attempt=1;attempt<=maxAttempts;attempt++) {
        try { results[i]={status:'fulfilled',value:await tasks[i](),attempts:attempt}; break; }
        catch(error) {
          last=error;
          if (!error.transient || attempt===maxAttempts) {
            results[i]={status:'rejected',reason:last.message,attempts:attempt}; break;
          }
        }
      }
    }
  }
  await Promise.all(Array.from({length:Math.min(limit,tasks.length)},worker));
  return results;
}

  保存为 run-limited.mjs,在另一模块导入 runLimited。任务失败时,只有error.transient为真才在剩余次数内重试;永久错误立即保留rejected。transient必须由可信错误分类提供,不能将所有异常都设为真,更不能把参数无效或鉴权失败当作不断重试的临时情况。

验证并发与失败边界

  本次在Node.js v24.16.0用构造任务检查:普通任务完成,第一次暂时失败的任务第二次成功,永久错误只尝试一次;空数组返回空结果,非法limit被拒绝。测试用计数记录活跃任务未超过设置值,验证没有调用付费图像或第三方发布接口。

  演示没有退避等待,真实网络服务还应按响应条件设计退避和重试时机。超时后请求可能已在服务端完成,盲目重新提交会产生重复结果或费用;需要结合任务幂等标识与提供方行为确认。不能因为最大尝试次数有限,就称重复调用风险已经解决。

  任务永不返回时仍会占住worker。生产实现需要超时、取消和状态恢复,但取消客户端等待不等于服务端停止执行。本文没有加入这些机制,运行记录也不支持重启后的继续执行。边界说明应和代码一起交付,避免小示例被当成可直接部署的队列系统。

  如果Picset或其他制作流程需要任务组织,[1] 执行器可以放在独立上层,按实际接口协议提供任务函数;本文没有验证任何产品内置队列或并发策略。业务的素材证据、质量验收和平台预览仍是另外阶段,fulfilled只说明函数成功返回,不表示文章或图片合格。

  保留逐项错误、尝试次数与稳定id,单篇失败就能回到具体任务,而其他项继续完成。修订材料、修改参数与暂时重试应分别处理。一个可解释的执行器,价值在于不隐藏失败、不打乱身份,也不让技术成功响应越过事实审核边界。

参考资料