From 19c51dd08664dd50c3b852674a821828ef0e2194 Mon Sep 17 00:00:00 2001 From: Kristin Cowalcijk Date: Mon, 13 Apr 2026 15:22:25 +0800 Subject: [PATCH] refactor: align Redis Sentinel kwargs threading --- litellm/_redis.py | 38 +++++++++++--------- tests/test_litellm/test_redis.py | 62 ++++++++++++++++++++++++++------ 2 files changed, 74 insertions(+), 26 deletions(-) diff --git a/litellm/_redis.py b/litellm/_redis.py index 5d884a28162..b3ec3bf8ef8 100644 --- a/litellm/_redis.py +++ b/litellm/_redis.py @@ -303,14 +303,23 @@ def init_redis_cluster(redis_kwargs) -> redis.RedisCluster: return redis.RedisCluster(startup_nodes=new_startup_nodes, **cluster_kwargs) # type: ignore +def _get_redis_sentinel_connection_kwargs(redis_kwargs: dict) -> dict: + connection_kwargs = {} + args = _get_redis_cluster_kwargs() + for arg in redis_kwargs: + if arg in args: + connection_kwargs[arg] = redis_kwargs[arg] + + return connection_kwargs + + def _init_redis_sentinel(redis_kwargs) -> redis.Redis: sentinel_nodes = redis_kwargs.get("sentinel_nodes") sentinel_password = redis_kwargs.get("sentinel_password") service_name = redis_kwargs.get("service_name") - master_kwargs = {} - - if redis_kwargs.get("password") is not None: - master_kwargs["password"] = redis_kwargs.get("password") + connection_kwargs = _get_redis_sentinel_connection_kwargs(redis_kwargs) + sentinel_kwargs = dict(connection_kwargs) + sentinel_kwargs["password"] = sentinel_password if not sentinel_nodes or not service_name: raise ValueError( @@ -323,24 +332,22 @@ def _init_redis_sentinel(redis_kwargs) -> redis.Redis: sentinel = redis.Sentinel( sentinel_nodes, socket_timeout=REDIS_SOCKET_TIMEOUT, - sentinel_kwargs={"password": sentinel_password} - if sentinel_password is not None - else None, + sentinel_kwargs=sentinel_kwargs, + **connection_kwargs, ) # Return the master instance for the given service - return sentinel.master_for(service_name, **master_kwargs) + return sentinel.master_for(service_name) def _init_async_redis_sentinel(redis_kwargs) -> async_redis.Redis: sentinel_nodes = redis_kwargs.get("sentinel_nodes") sentinel_password = redis_kwargs.get("sentinel_password") service_name = redis_kwargs.get("service_name") - master_kwargs = {} - - if redis_kwargs.get("password") is not None: - master_kwargs["password"] = redis_kwargs.get("password") + connection_kwargs = _get_redis_sentinel_connection_kwargs(redis_kwargs) + sentinel_kwargs = dict(connection_kwargs) + sentinel_kwargs["password"] = sentinel_password if not sentinel_nodes or not service_name: raise ValueError( @@ -353,14 +360,13 @@ def _init_async_redis_sentinel(redis_kwargs) -> async_redis.Redis: sentinel = async_redis.Sentinel( sentinel_nodes, socket_timeout=REDIS_SOCKET_TIMEOUT, - sentinel_kwargs={"password": sentinel_password} - if sentinel_password is not None - else None, + sentinel_kwargs=sentinel_kwargs, + **connection_kwargs, ) # Return the master instance for the given service - return sentinel.master_for(service_name, **master_kwargs) + return sentinel.master_for(service_name) def get_redis_client(**env_overrides): diff --git a/tests/test_litellm/test_redis.py b/tests/test_litellm/test_redis.py index b6609ca5939..e5a63f6c5c2 100644 --- a/tests/test_litellm/test_redis.py +++ b/tests/test_litellm/test_redis.py @@ -365,15 +365,36 @@ def test_sync_sentinel_uses_sentinel_password_and_master_password(mock_sentinel_ sentinel_password="sentinel-secret", service_name="mymaster", password="redis-secret", + username="redis-user", + ssl=True, + ssl_cert_reqs="required", + ssl_check_hostname=True, + ssl_ca_certs="/tmp/test-ca.pem", + max_connections=17, ) mock_sentinel_cls.assert_called_once() sentinel_call_kwargs = mock_sentinel_cls.call_args[1] - assert sentinel_call_kwargs["sentinel_kwargs"] == {"password": "sentinel-secret"} - assert "password" not in sentinel_call_kwargs - mock_sentinel.master_for.assert_called_once_with( - "mymaster", password="redis-secret" - ) + assert sentinel_call_kwargs["password"] == "redis-secret" + assert sentinel_call_kwargs["username"] == "redis-user" + assert sentinel_call_kwargs["ssl"] is True + assert sentinel_call_kwargs["ssl_cert_reqs"] == "required" + assert sentinel_call_kwargs["ssl_check_hostname"] is True + assert sentinel_call_kwargs["ssl_ca_certs"] == "/tmp/test-ca.pem" + assert sentinel_call_kwargs["max_connections"] == 17 + assert sentinel_call_kwargs["sentinel_kwargs"] == { + "password": "sentinel-secret", + "username": "redis-user", + "ssl": True, + "ssl_cert_reqs": "required", + "ssl_check_hostname": True, + "ssl_ca_certs": "/tmp/test-ca.pem", + "max_connections": 17, + } + assert "service_name" not in sentinel_call_kwargs["sentinel_kwargs"] + assert "sentinel_nodes" not in sentinel_call_kwargs["sentinel_kwargs"] + assert "sentinel_password" not in sentinel_call_kwargs["sentinel_kwargs"] + mock_sentinel.master_for.assert_called_once_with("mymaster") @patch("litellm._redis.async_redis.Sentinel") @@ -389,15 +410,36 @@ def test_async_sentinel_uses_sentinel_password_and_master_password( sentinel_password="sentinel-secret", service_name="mymaster", password="redis-secret", + username="redis-user", + ssl=True, + ssl_cert_reqs="required", + ssl_check_hostname=True, + ssl_ca_certs="/tmp/test-ca.pem", + max_connections=17, ) mock_sentinel_cls.assert_called_once() sentinel_call_kwargs = mock_sentinel_cls.call_args[1] - assert sentinel_call_kwargs["sentinel_kwargs"] == {"password": "sentinel-secret"} - assert "password" not in sentinel_call_kwargs - mock_sentinel.master_for.assert_called_once_with( - "mymaster", password="redis-secret" - ) + assert sentinel_call_kwargs["password"] == "redis-secret" + assert sentinel_call_kwargs["username"] == "redis-user" + assert sentinel_call_kwargs["ssl"] is True + assert sentinel_call_kwargs["ssl_cert_reqs"] == "required" + assert sentinel_call_kwargs["ssl_check_hostname"] is True + assert sentinel_call_kwargs["ssl_ca_certs"] == "/tmp/test-ca.pem" + assert sentinel_call_kwargs["max_connections"] == 17 + assert sentinel_call_kwargs["sentinel_kwargs"] == { + "password": "sentinel-secret", + "username": "redis-user", + "ssl": True, + "ssl_cert_reqs": "required", + "ssl_check_hostname": True, + "ssl_ca_certs": "/tmp/test-ca.pem", + "max_connections": 17, + } + assert "service_name" not in sentinel_call_kwargs["sentinel_kwargs"] + assert "sentinel_nodes" not in sentinel_call_kwargs["sentinel_kwargs"] + assert "sentinel_password" not in sentinel_call_kwargs["sentinel_kwargs"] + mock_sentinel.master_for.assert_called_once_with("mymaster") @patch("litellm._redis.init_redis_cluster")