Changelog¶
Changelog¶
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
v1.8.7 - 2026-03-07¶
Docs¶
- Rewrote README as a concise entry point (343 → 91 lines): install, one example per feature, link to docs
- Removed duplicate parameter tables, auth/TLS sections, and stats/sharding examples from README (covered in docs site)
- Merged separate Authentication and TLS sections into one in async and sync client guides
- Condensed two-phase acquisition explanations to bullet points in client guides
- Replaced duplicate semaphore parameter tables with cross-references to lock parameters
- Removed "Query server stats" and "What happens under the hood" from quickstart (covered in examples and architecture)
- Tightened docs/index.md feature list
v1.8.6 - 2026-03-07¶
Docs¶
- Added
KW_ONLYmarker to all dataclass definitions in API reference to accurately show keyword-only parameters - Added missing
Signal,AsyncSignalConn,SyncSignalConnto top-level import example in API reference - Added keyword-only parameter notes to lock and semaphore parameter tables in client guides
- Fixed background renewal description: incorrectly stated "sets
token = None" on failure; actually the renewal loop exits and the lease expires server-side
v1.8.5 - 2026-03-07¶
Fixed¶
- Formatting fixes for CI
v1.8.4 - 2026-03-07¶
Fixed¶
SignalConn.connect()did not reset_closedflag or create fresh queues, preventing reconnection afterclose()/aclose()Nonesentinel silently dropped when signal queue was full, causingfor sig in sc:/async for sig in sc:to hang forever- Sync
_read_loopblocked indefinitely on full_resp_queue(changedput()toput_nowait())
v1.8.3 - 2026-03-06¶
Docs¶
- Added signals documentation to README, quickstart, examples, client guides, API reference, and architecture docs
v1.8.1 - 2026-03-06¶
Fixed¶
- Formatting fixes for CI compliance
v1.8.0 - 2026-03-06¶
Added¶
- Signal (pub/sub) support:
AsyncSignalConnandSyncSignalConnhigh-level classes with background reader for push delivery listen(pattern, group=)/unlisten(pattern, group=)for subscribing to channels with NATS-style wildcards (*,>)emit(channel, payload)for publishing signals on literal channels; returns delivery count- Queue group support for load-balanced signal delivery (round-robin within a group)
SignalNamedTuple (channel,payload) for received signals- Low-level
sig_emit()protocol function for fire-and-forget publishing on plain connections - Iteration support:
async for sig in conn:/for sig in conn:with clean termination on disconnect - Context manager support (
async with/with) for signal connections - Signal test suite with unit and integration tests
v1.7.3 - 2026-03-06¶
Fixed¶
- Missing GitHub release for v1.7.2 prevented automated PyPI publish; re-release with no code changes
v1.7.2 - 2026-03-06¶
Fixed¶
stats()protocol: send_placeholder instead of empty string as third argument toencode_lines(async and sync clients)
Docs¶
- Corrected
acquireandsem_acquireexamples to use positional arguments
v1.7.1 - 2026-02-24¶
Fixed¶
- Dead
readlinecheck that could never trigger; lease is now reset to0onclose()
Changed¶
- Unified lock and semaphore protocol functions via
cmd_prefix, reducing code duplication
Added¶
- Strict FIFO ordering tests for locks and semaphores (async and sync), verifying 5 waiters are granted in exact enqueue order
v1.7.0 - 2026-02-24¶
Fixed¶
- Sync renew loop race: replace
_stop_event.clear()with freshEventto prevent lingering threads from ignoring stop signals - Renew loop sends aggressive 1-second intervals when server returns lease=0 (now falls back to 30s)
__del__()now closes leaked sockets/transports withResourceWarninginstead of silently leaking FDs- Async
aclose()boundswait_closed()to 5s to prevent indefinite hangs - Renew loop holds local references to stale connections after reconnect (now cleared in
finally) - Async readline missing 1 MiB length guard (now raises
RuntimeErrorfor oversized responses) - Auth handshake missing timeout (now uses
connect_timeout_s) - Renew loop continues operating on stale connections after reconnect (added identity checks)
_stop_renew()thread orphan when_renew_threadreference is stale- Spurious "lock lost" log messages on normal shutdown
- Sync socket timeouts not set during renew (now scoped to 5s for renew operations)
- Sync
close()stalls waiting for_io_lockheld by renew loop (now interrupts viasock.shutdown()) - Enqueue bounds checks missing for malformed server responses
- Release errors in
__exit__/__aexit__could mask the original exception (now suppressed) - Protocol arguments containing newlines could corrupt the wire format (now rejected by
encode_lines()) renew_ratiooutside (0, 1) not validated (now raisesValueError)
Added¶
- Top-level package exports:
AsyncDistributedLock,AsyncDistributedSemaphore,SyncDistributedLock,SyncDistributedSemaphore,StatsResult,DEFAULT_SERVERS,ShardingStrategy,stable_hash_shard,__version__ - Shared
_commonmodule withencode_lines(),parse_lease(), response size limits, and connect timeout constant - Comprehensive resource cleanup tests (
test_resource_cleanup.py) DEFAULT_SERVERSis now an immutable tuple
Changed¶
- Refactored async and sync clients to share base classes (
_AsyncBase,_SyncBase), eliminating code duplication
v1.6.2 - 2026-02-24¶
Fixed¶
- Sync client leaks socket when calling
acquire()/enqueue()on an already-connected instance (missingclose()before reconnect) - Sync client leaks raw socket when
wrap_socket()ormakefile()fails during_connect() - Sync renew loop leaves socket open on renewal failure (now calls
close()instead of only clearing the token) - Async
aclose()skipswait_closed()ifclose()raises (now each call is independently guarded) - Malformed server lease values cause unhandled
ValueError(now falls back to default) - Malformed JSON in
stats()response causes unhandledJSONDecodeError(now raisesRuntimeError)
Added¶
- Connect timeout (10 s) on sync
socket.create_connection()to prevent blocking on unreachable hosts
v1.6.1 - 2026-02-24¶
Added¶
- GitHub Actions workflow to publish to PyPI on new releases via trusted publishing
v1.6.0 - 2026-02-18¶
Added¶
auth_tokenparameter onDistributedLockandDistributedSemaphorein both async and sync clients for token-based authentication- Auth handshake is sent automatically in
_connect()whenauth_tokenis set; raisesPermissionErroron failure - Auth unit tests verifying
auth_tokendefaults toNoneand can be set - Auth integration tests gated behind
DFLOCKD_TEST_AUTH_TOKENandDFLOCKD_TEST_AUTH_PORTenv vars - Authentication documentation in README, API reference, client guides, and examples
v1.5.1 - 2026-02-18¶
Fixed¶
- Add return types to async
_connect()helpers for pyright type narrowing
v1.5.0 - 2026-02-18¶
Added¶
ssl_contextparameter onDistributedLockandDistributedSemaphorein both async and sync clients for TLS connections_connect()helper in asyncDistributedLockandDistributedSemaphoreto centralize connection logic- TLS unit tests verifying
ssl_contextdefaults toNone - TLS integration tests gated behind
DFLOCKD_TEST_TLS_PORTenv var - TLS documentation in README, API reference, client guides, and examples
v1.4.0 - 2026-02-18¶
Added¶
stats()function in both async and sync clients for querying server state (connections, locks, semaphores, idle entries)- Stats integration tests for both async and sync clients
- Documentation for stats in README, API reference, client guides, quickstart, examples, and architecture docs
Changed¶
- Bumped version to v1.4.0 to align with dflockd server version
v1.1.0 - 2026-02-16¶
Added¶
DistributedSemaphoreclass in both async and sync clients, allowing up to N concurrent holders per key- Semaphore protocol functions (
sem_acquire,sem_release,sem_renew,sem_enqueue,sem_wait) in both async and sync clients - Two-phase semaphore acquisition via
DistributedSemaphore.enqueue()andDistributedSemaphore.wait() - Semaphore integration and unit tests mirroring existing lock test structure
- Documentation for semaphores in README, API reference, client guides, quickstart, examples, and architecture docs
v1.0.1 - 2026-02-16¶
Fixed¶
- Close existing connections before opening new ones in
acquire(),enqueue(), and__aenter__(), preventing socket leaks on repeated calls - Close socket on renew failure instead of only clearing the token, so the connection is properly cleaned up when a lock is lost
- Suppress
release()errors in__aexit__to avoid masking the original exception from theasync withblock - Examples import referenced the old
dflockdpackage name instead ofdflockd_client
Changed¶
- Added documentation site link to README
v1.0.0 - 2026-02-15¶
Changed¶
- Split from dflockd into a standalone client-only package (
dflockd-client) - Server has been ported to Go; this package now contains only the Python client
- Renamed package import from
dflockdtodflockd_client - Integration tests now require an external running dflockd server (configurable via
DFLOCKD_TEST_HOST/DFLOCKD_TEST_PORTenv vars, skipped if unavailable) - Documentation rewritten to focus on client usage; server and wire protocol docs removed
Removed¶
- Server code (
dflockd.server) - Server CLI (
dflockdcommand) - Server configuration docs, wire protocol docs
- TypeScript client (
ts/)
v0.5.0 - 2026-02-14¶
Added¶
- Two-phase lock acquisition with
e(enqueue) andw(wait) protocol commands enqueue()andwait()module-level functions in async and sync clientsDistributedLock.enqueue()andDistributedLock.wait()methods in async and sync clients- Documentation for two-phase flow in client and examples docs
v0.4.1 - 2026-02-07¶
Added¶
--auto-release-on-disconnect/--no-auto-release-on-disconnectCLI flag
Fixed¶
DFLOCKD_DFLOCKD_READ_TIMEOUT_Senv var typo in README (nowDFLOCKD_READ_TIMEOUT_S)- Server configuration env var names in README missing
DFLOCKD_prefix MAX_LOCKSdefault in README corrected from256to1024
v0.4.0 - 2026-02-07¶
Added¶
- Documentation site (MkDocs Material) with architecture, configuration, client, protocol, and sharding guides
Fixed¶
- Pyright CI dependency
- Ruff dev dependency
Changed¶
- Bump
actions/checkoutfrom 4 to 6 - Bump
actions/setup-pythonfrom 5 to 6 - Bump
actions/upload-pages-artifactfrom 3 to 4 - Bump
astral-sh/setup-uvfrom 4 to 7 - Update
uv-buildrequirement from >=0.9.28,<0.10.0 to >=0.9.28,<0.11.0
v0.3.0 - 2026-02-07¶
Added¶
- Async client (
dflockd.client) withDistributedLockcontext manager - Sync client (
dflockd.sync_client) withDistributedLockcontext manager - Background lease renewal for both async and sync clients
- Multi-server sharding with
stable_hash_shard(CRC-32) - Custom sharding strategy support via
ShardingStrategycallable - Configurable
renew_ratiofor controlling renewal frequency - CI workflow with linting, type checking, and tests
- GitHub Pages documentation deployment workflow