feat: accept RedisCluster in Distributed lock#1
Closed
premtsd-code wants to merge 1 commit intoutopia-php:mainfrom
Closed
feat: accept RedisCluster in Distributed lock#1premtsd-code wants to merge 1 commit intoutopia-php:mainfrom
premtsd-code wants to merge 1 commit intoutopia-php:mainfrom
Conversation
The lock primitive uses only single-key operations (SET NX EX, GET, and single-key Lua EVAL via runScript), all of which behave identically on \Redis and \RedisCluster — the cluster client routes by hash slot transparently. Widening the type lets clustered Dragonfly/Redis deployments use the same Distributed lock without an external client wrapper. No algorithmic changes; same TTL, same compare-and-delete release script, same correctness properties per key. Multi-master quorum guarantees (Redlock) remain out of scope — single-key locks on cluster mode have the same per-key failover semantics as single-instance Redis.
premtsd-code
added a commit
to appwrite/appwrite
that referenced
this pull request
Apr 29, 2026
Cloud production runs four separate single-master+replica Dragonfly deployments (cache, queue-dragonfly, queue-usage, pubsub-dragonfly), not sharded Redis Cluster topology — confirmed by deploy/cloud/values + environments/production/*.values.yaml (Dragonfly Operator with replicas=2 = 1 primary + 1 read replica), and by the dev DSN scheme 'redis://' (not 'redis-cluster://'). So a standard \Redis client suffices for the direct redis resource (timelimit, Lock). Cloud just needs to pass _APP_REDIS_HOST/PORT/USER/ PASS through to the appwrite container — handled in the cloud PR's docker-compose.yml change. This reverts the resource to its original pre-PR shape. The utopia-php/lock cluster-support PR (utopia-php/lock#1) stays open at upstream as a future-ready option if cloud ever moves to actual Redis Cluster mode.
10 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Widens the type accepted by
Distributed::__constructfrom\Redisto\Redis | \RedisClusterso the lock primitive can be used against clustered Redis/Dragonfly deployments.Why
Utopia\Lock\Distributeduses three single-key operations:set($key, $token, ['NX', 'EX' => $ttl])— acquire (line 88)get($key)—isHeld()check (line 139)eval($script, [$key, $token], 1)— atomic compare-and-delete release / TTL refresh (line 149)All three are slot-deterministic single-key ops that the PHP
\RedisClusterclient routes transparently via CRC16-based slot routing. Both client classes implement these methods with effectively identical signatures for single-key operations, so no algorithmic change is required — the lock's correctness, TTL semantics, and compare-and-delete release behaviour all hold unchanged on cluster mode.What does NOT change
What's not addressed here
{group}:keyA,{group}:keyB) to force same-slot placement. This PR makes no change there because the lock primitive is single-key by design.Test plan
composer analyze(PHPStan) passescomposer lint(Pint) passesDistributedTestunit tests pass against\Redis(no behavioural change for the standalone path)\RedisClusterconnected to a 3-master Dragonfly/Redis cluster and verify acquire / release / refresh /isHeld/withLockall behave correctly. (Adding an automated cluster test requires CI infrastructure changes beyond this PR's scope; happy to follow up.)Downstream
This unblocks
Appwrite\Locking\Lockinappwrite/appwrite#12062— the appwrite-side resource can then return\Redis | \RedisClusterfrom_APP_CONNECTIONS_CACHEbased on the DSN scheme (redis://vsredis-cluster://), matching how the cache pool already works.