Skip to content

Version 5.1.0: release mutex locks with await using - #81

Merged
freshlogic merged 2 commits into
mainfrom
mutex-lock-handle
Oct 26, 2026
Merged

freshlogic merged 2 commits into
mainfrom
mutex-lock-handle

Conversation

@freshlogic

Copy link
Copy Markdown
Member

Summary

  • mutex.lock(key, options) now resolves with a lock handle (AsyncDisposable). Declare it with await using and the lock is released when the block exits, including when it throws:
    await using lock = await pettyCache.mutex.lock('some-key', { ttl: 60000 });
  • The lock now stores a random value from crypto.randomUUID() instead of '1'. The handle releases it with a small Lua compare-and-delete script, so a holder whose TTL expired can't delete a newer holder's lock.
  • mutex.lock still rejects when the lock is held, and mutex.unlock(key) still deletes the key whoever holds it, so existing callers don't change.
  • The semaphore functions and fetchAndRefresh ignore what mutex.lock resolves with and release through mutex.unlock (or let the TTL expire), so they behave the same.
  • ESLint: turned on no-unused-vars' ignoreUsingDeclarations. Without it, every await using lock = … is reported as unused even though disposing it is the point.
  • README, CHANGELOG, JSDoc @returns, and package.json version 5.1.0 (5.0.0 is already on npm).

Tests

  • The lock is released when an await using block throws
  • A second lock succeeds after the first handle is disposed
  • An expired holder's dispose doesn't delete a newer holder's lock
  • Dispose rejects when Redis EVAL fails

Not published to npm.

🤖 Generated with Claude Code

freshlogic and others added 2 commits October 26, 2026 14:34
mutex.lock now stores a random value and resolves with an
AsyncDisposable handle. Disposing it deletes the key only if it still
holds that value, so a holder whose TTL expired can't release a newer
holder's lock. mutex.unlock still deletes the key unconditionally.

Version 5.1.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coveralls

coveralls commented Oct 26, 2026 •

Copy link
Copy Markdown

Coverage Report for CI Build 40387987955

Coverage remained the same at 100.0%

Details

  • Coverage remained the same as the base build.
  • Patch coverage: 14 of 14 lines across 1 file are fully covered (100%).
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 860
Covered Lines: 860
Line Coverage: 100.0%
Relevant Branches: 227
Covered Branches: 227
Branch Coverage: 100.0%
Branches in Coverage %: Yes
Coverage Strength: 53.35 hits per line

💛 - Coveralls

@freshlogic
freshlogic merged commit 36e9d0f into main Oct 26, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants