标准答案

  1. 提交时超过队列上限应拒绝或转入可靠队列。
  2. 任务开始前和执行中都检查取消与 deadline;无法取消的外部操作要记录最终状态。
  3. 任务结束、失败、取消都释放执行槽并更新状态,不能只在成功路径释放。

题目解析

执行器至少有三个容量边界:等待队列、运行中的执行槽和下游资源。提交时要有界,任务开始前要检查 deadline,执行中要通过 AbortSignal 或等价协议协作取消。

超时并不等于代码已经停止,尤其是不可取消的数据库、文件或外部 HTTP 调用。执行器要把“调用方不再等待”和“业务副作用最终结果未知”分别记录。

成功、失败、取消、异常和关闭路径都必须释放执行槽并更新状态。停机时先拒绝新任务,再排空、转移或取消已有任务,并设置总 deadline。

代码示例

任务函数应接收取消和截止时间:

TypeScript
type Job<T> = (ctx: { signal: AbortSignal; deadline: number }) => Promise<T>
// executor: bounded queue + semaphore + finally release
await job({ signal, deadline })

常见误区

  • 误区:队列无界。改正:设置任务数量、字节数和最大等待时间,容量耗尽时拒绝或转可靠存储。
  • 误区:超时后不释放并发槽。改正:在 finally 中释放执行许可,并处理后台仍在运行的不可取消任务。
  • 误区:关闭时新任务仍能入队。改正:关闭状态与提交操作使用同一同步边界,关闭后明确拒绝新任务。

作者信息