mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-06 02:48:13 +00:00
Merge 5fe80fd063 into c39bf62936
This commit is contained in:
commit
d78d4075a6
3 changed files with 52 additions and 1 deletions
|
|
@ -1370,7 +1370,8 @@ class RedisCache(BaseCache):
|
|||
self.redis_client.flushall()
|
||||
|
||||
async def disconnect(self):
|
||||
await self.async_redis_conn_pool.disconnect(inuse_connections=True)
|
||||
if self.async_redis_conn_pool is not None:
|
||||
await self.async_redis_conn_pool.disconnect(inuse_connections=True)
|
||||
try:
|
||||
self.redis_client.close()
|
||||
except Exception as e:
|
||||
|
|
|
|||
|
|
@ -56,6 +56,19 @@ class RedisClusterCache(RedisCache):
|
|||
async_redis_cluster_client: Final = self.init_async_client()
|
||||
return await async_redis_cluster_client.mget_nonatomic(keys=keys)
|
||||
|
||||
async def disconnect(self):
|
||||
"""
|
||||
Overrides `disconnect` in redis_cache.py.
|
||||
|
||||
In cluster mode ``get_redis_connection_pool`` returns ``None`` (the
|
||||
``RedisCluster`` client builds its own per-node pools), so the base-class
|
||||
implementation would dereference ``None``. Close the cluster client instead,
|
||||
then let the base class tear down the sync client.
|
||||
"""
|
||||
if self.redis_async_redis_cluster_client is not None:
|
||||
await self.redis_async_redis_cluster_client.aclose()
|
||||
await super().disconnect()
|
||||
|
||||
async def test_connection(self) -> dict:
|
||||
"""
|
||||
Test the Redis Cluster connection.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import asyncio
|
||||
import json
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
|
@ -1478,3 +1479,39 @@ def test_async_sentinel_keeps_the_credential_provider_off_the_monitors(markers,
|
|||
master_kwargs = mock_sentinel_cls.return_value.master_for.call_args[1]
|
||||
assert isinstance(master_kwargs["credential_provider"], provider_cls)
|
||||
assert "password" not in master_kwargs
|
||||
def _make_cluster_cache() -> RedisClusterCache:
|
||||
"""Build a RedisClusterCache without hitting a real Redis server."""
|
||||
cache = RedisClusterCache.__new__(RedisClusterCache)
|
||||
cache.async_redis_conn_pool = None
|
||||
cache.redis_async_redis_cluster_client = None
|
||||
cache.redis_client = MagicMock()
|
||||
return cache
|
||||
|
||||
|
||||
def test_redis_cluster_cache_disconnect_without_pool():
|
||||
"""
|
||||
In cluster mode ``get_redis_connection_pool`` returns ``None`` (the
|
||||
RedisCluster client builds its own per-node pools), so the base-class
|
||||
``disconnect`` must not dereference the pool. Regression for #37137.
|
||||
"""
|
||||
cache = _make_cluster_cache()
|
||||
|
||||
asyncio.run(cache.disconnect())
|
||||
|
||||
cache.redis_client.close.assert_called_once()
|
||||
|
||||
|
||||
def test_redis_cluster_cache_disconnect_closes_cluster_client():
|
||||
"""
|
||||
When a cluster client was created, ``disconnect`` must tear it down via
|
||||
``aclose`` (the same primitive ``test_connection`` uses) before delegating
|
||||
to the base class. Regression for #37137.
|
||||
"""
|
||||
cache = _make_cluster_cache()
|
||||
cluster_client = AsyncMock()
|
||||
cache.redis_async_redis_cluster_client = cluster_client
|
||||
|
||||
asyncio.run(cache.disconnect())
|
||||
|
||||
cluster_client.aclose.assert_awaited_once()
|
||||
cache.redis_client.close.assert_called_once()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue