v3.6.0
Fixed
-
A
@lock()'d call could resolve waiters with another call's result, and one
waiter's timeout rejected all of them.IMQLock.deadlockTimeoutrejected
throughrelease(), which does two things a timeout has no business doing: it
deleted the holder's lock while the holder was still running, and it drained
the whole queue.The first let a later call acquire the freed key and run alongside the original
holder — and when that holder finally finished, its release landed on the new
holder's lock, resolving waiters with a result computed for a call they had
nothing to do with and freeing a lock still in use, letting a third call in
behind it. Silently wrong values, under exactly the overlapping load that
coalescing@lock()exists to collapse. The second meant a call that arrived
a moment ago died for an older call's patience.Locks now carry a token.
release()takes it as an optional fourth argument
and is ignored when a different call owns the key; an unowned key is not a
conflict, so a straggler can still satisfy waiters nobody else will.lock()
reads the token and passes it, so every decorator user is covered with no code
change, and a release without a token behaves exactly as before. The timer now
splices out its own task and rejects only that waiter, while still freeing the
key — a holder that never releases would otherwise poison it for the life of
the process.
About
@imqueue/rpc is the type-safe RPC framework of @imqueue: self-describing service classes over a Redis message queue that generate their own strongly-typed clients — no hand-written client code, no .proto, no service discovery, no load balancer. Delayed calls via IMQDelay, optional caching and locking decorators. Node.js and TypeScript only, Redis only.
- Docs: https://imqueue.org/
- Guide for AI assistants / LLMs: https://imqueue.org/llms.txt
- Commercial license & support: https://imqueue.com/
npm i @imqueue/rpc