功能说明
同一资源的并发写操作需要串行化,但全局锁会阻塞无关任务。KeyedMutex 为每个字符串键维护一条 Promise 链,同一键的任务排队执行,不同键可以并行。它适合按用户、订单或文件路径加锁,避免重复写入和竞态条件。
关键代码
run 读取该键当前的 tail,创建 current Promise 并通过 release 控制完成;新的 tail 是 previous.then 返回的 Promise,立即写回 Map。等待 previous 后执行任务,finally 中释放 current,并在没有后续任务时删除键,避免 Map 无限增长。
const previous = this.tails.get(key) ?? Promise.resolve();
const current = new Promise<void>((resolve) => { release = resolve; });
const tail = previous.then(() => current);
this.tails.set(key, tail);
await previous;
try { return await task(); }
finally { release(); if (this.tails.get(key) === tail) this.tails.delete(key); }
使用注意
锁只在单进程内有效,多实例部署需要分布式锁。任务抛错不会阻塞后续任务,但错误会传给调用方。键为空字符串会抛 TypeError。长时间运行的任务会持续占用该键,应设置超时或取消机制。任务不应递归获取同一个键,否则会死锁。
验证方式
断言同一键的两个任务按提交顺序执行,不同键可以交错完成。任务失败后下一个任务仍能运行。全部完成后 size 归零,isLocked 在执行期间为 true、结束后为 false。空键抛 TypeError,非函数任务抛 TypeError。