feat: add Redis Cluster support via REDIS_CLUSTER_MODE setting#3890
Open
feat: add Redis Cluster support via REDIS_CLUSTER_MODE setting#3890
Conversation
8e53d94 to
0f9ccda
Compare
added 2 commits
March 27, 2026 09:54
When deploying against a Redis Cluster (e.g. Bitnami redis-cluster Helm chart), the current standalone redis.asyncio.Redis client cannot handle MOVED/ASK redirects, causing the application to crash-loop with redis.exceptions.MovedError. This commit adds a REDIS_CLUSTER_MODE boolean setting (default: false). When enabled, the redis_client factory creates a redis.asyncio.RedisCluster instance instead of a standalone Redis client. The cluster client automatically discovers all shards and routes commands to the correct node. Changes: - config.py: Add redis_cluster_mode setting with Field descriptor - utils/redis_client.py: Add _create_cluster_client() and _create_standalone_client() helpers; strip /N database path from URL in cluster mode (Redis Cluster only supports db 0); select client type based on redis_cluster_mode setting Usage: REDIS_CLUSTER_MODE=true REDIS_URL=redis://:password@redis-cluster:6379 # no /0 Fixes crash-loop caused by MovedError when REDIS_URL points to a Redis Cluster service with multiple shards. Signed-off-by: bbakouma <bakoumaema@gmail.com>
…ation - _strip_db_from_url now raises ValueError for non-zero database numbers (e.g. /1, /2) instead of silently stripping them, so misconfigurations fail fast - Add TestStripDbFromUrl: tests for /0 stripping, no-path, slash-only, and non-zero DB rejection - Add TestClusterMode: tests for cluster_mode=true (RedisCluster), cluster_mode=false (standalone), and missing attr fallback - Update .env.example with REDIS_CLUSTER_MODE documentation Signed-off-by: bbakouma <bakoumaema@gmail.com>
0f9ccda to
3a3dc63
Compare
Member
|
Thanks @bebakouma — clean implementation. The cluster/standalone factory split, One security issue to fix: The cluster-mode log line logs the full URL: f"url={_strip_db_from_url(settings.redis_url)}"If Minor suggestions (non-blocking):
DCO: Otherwise this looks ready for review. Nice work! |
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.
Problem
When deploying ContextForge against a Redis Cluster (e.g. Bitnami
redis-clusterHelm chart with multiple shards), the current standaloneredis.asyncio.Redisclient cannot handleMOVED/ASKredirects. This causes the application to crash-loop withredis.exceptions.MovedErroron startup during leader election.The error occurs because
redis.asyncio.from_url()always creates a standalone client that connects to a single node. When a key lives on a different shard, Redis responds with aMOVEDredirect that the standalone client cannot follow.Solution
Add a
REDIS_CLUSTER_MODEboolean environment variable (default:false). When set totrue, theredis_clientfactory creates aredis.asyncio.RedisClusterinstance that automatically discovers all shards and routes commands to the correct node.Changes
config.py— newredis_cluster_modesetting with Field descriptorutils/redis_client.py— refactored into_create_cluster_client()and_create_standalone_client()helpers; strips/Ndatabase path from URL in cluster mode (Redis Cluster only supports db 0); selects client type based onredis_cluster_modesettingUsage
REDIS_CLUSTER_MODE=true REDIS_URL=redis://:password@redis-cluster:6379 # no /0Compatibility
false, existing standalone deployments are unaffectedRedisClustersupports the same.set(),.get(),.ping(),.eval(),.publish(),.pubsub()APIs used throughout the codebaseRedisCluster(broadcasts to all nodes)Environment
Tested against Bitnami
redis-clusterHelm chart v12.0.2 (3 nodes) where theredis-clusterClusterIP service load-balances across shards.