1
1
import os
2
- from typing import Any , Dict , List , Optional , Type , TypeVar , Union , overload
3
- from urllib .parse import urlparse
2
+ from typing import Any , Dict , List , Optional , Tuple , Type , TypeVar , Union , overload
3
+ from urllib .parse import parse_qs , urlencode , urlparse , urlunparse
4
4
from warnings import warn
5
5
6
6
from redis import Redis , RedisCluster
21
21
from redisvl .utils .utils import deprecated_function
22
22
23
23
24
+ def _strip_cluster_from_url_and_kwargs (
25
+ url : str , ** kwargs
26
+ ) -> Tuple [str , Dict [str , Any ]]:
27
+ """Remove 'cluster' parameter from URL query string and kwargs.
28
+
29
+ AsyncRedisCluster doesn't accept 'cluster' parameter, but it might be
30
+ present in the URL or kwargs for compatibility with other Redis clients.
31
+
32
+ Args:
33
+ url: Redis URL that might contain cluster parameter
34
+ **kwargs: Keyword arguments that might contain cluster parameter
35
+
36
+ Returns:
37
+ Tuple of (cleaned_url, cleaned_kwargs)
38
+ """
39
+ # Parse the URL
40
+ parsed = urlparse (url )
41
+
42
+ # Parse query parameters
43
+ query_params = parse_qs (parsed .query )
44
+
45
+ # Remove 'cluster' parameter if present
46
+ query_params .pop ("cluster" , None )
47
+
48
+ # Reconstruct the query string
49
+ new_query = urlencode (query_params , doseq = True )
50
+
51
+ # Reconstruct the URL
52
+ cleaned_url = urlunparse (
53
+ (
54
+ parsed .scheme ,
55
+ parsed .netloc ,
56
+ parsed .path ,
57
+ parsed .params ,
58
+ new_query ,
59
+ parsed .fragment ,
60
+ )
61
+ )
62
+
63
+ # Remove 'cluster' from kwargs if present
64
+ cleaned_kwargs = kwargs .copy ()
65
+ cleaned_kwargs .pop ("cluster" , None )
66
+
67
+ return cleaned_url , cleaned_kwargs
68
+
69
+
24
70
def compare_versions (version1 : str , version2 : str ):
25
71
"""
26
72
Compare two Redis version strings numerically.
@@ -311,9 +357,17 @@ async def _get_aredis_connection(
311
357
url , AsyncRedis , ** kwargs
312
358
)
313
359
elif is_cluster_url (url , ** kwargs ):
314
- client = AsyncRedisCluster .from_url (url , ** kwargs )
360
+ # Strip 'cluster' parameter as AsyncRedisCluster doesn't accept it
361
+ cleaned_url , cleaned_kwargs = _strip_cluster_from_url_and_kwargs (
362
+ url , ** kwargs
363
+ )
364
+ client = AsyncRedisCluster .from_url (cleaned_url , ** cleaned_kwargs )
315
365
else :
316
- client = AsyncRedis .from_url (url , ** kwargs )
366
+ # Also strip cluster parameter for AsyncRedis to avoid connection issues
367
+ cleaned_url , cleaned_kwargs = _strip_cluster_from_url_and_kwargs (
368
+ url , ** kwargs
369
+ )
370
+ client = AsyncRedis .from_url (cleaned_url , ** cleaned_kwargs )
317
371
318
372
# Module validation removed - operations will fail naturally if modules are missing
319
373
# Set client library name only
@@ -351,11 +405,23 @@ def get_async_redis_connection(
351
405
DeprecationWarning ,
352
406
)
353
407
url = url or get_address_from_env ()
408
+
354
409
if url .startswith ("redis+sentinel" ):
355
410
return RedisConnectionFactory ._redis_sentinel_client (
356
411
url , AsyncRedis , ** kwargs
357
412
)
358
- return AsyncRedis .from_url (url , ** kwargs )
413
+ elif is_cluster_url (url , ** kwargs ):
414
+ # Strip 'cluster' parameter as AsyncRedisCluster doesn't accept it
415
+ cleaned_url , cleaned_kwargs = _strip_cluster_from_url_and_kwargs (
416
+ url , ** kwargs
417
+ )
418
+ return AsyncRedisCluster .from_url (cleaned_url , ** cleaned_kwargs )
419
+ else :
420
+ # Also strip cluster parameter for AsyncRedis to avoid connection issues
421
+ cleaned_url , cleaned_kwargs = _strip_cluster_from_url_and_kwargs (
422
+ url , ** kwargs
423
+ )
424
+ return AsyncRedis .from_url (cleaned_url , ** cleaned_kwargs )
359
425
360
426
@staticmethod
361
427
def get_redis_cluster_connection (
@@ -373,7 +439,9 @@ def get_async_redis_cluster_connection(
373
439
) -> AsyncRedisCluster :
374
440
"""Creates and returns an asynchronous Redis client for a Redis cluster."""
375
441
url = redis_url or get_address_from_env ()
376
- return AsyncRedisCluster .from_url (url , ** kwargs )
442
+ # Strip 'cluster' parameter as AsyncRedisCluster doesn't accept it
443
+ cleaned_url , cleaned_kwargs = _strip_cluster_from_url_and_kwargs (url , ** kwargs )
444
+ return AsyncRedisCluster .from_url (cleaned_url , ** cleaned_kwargs )
377
445
378
446
@staticmethod
379
447
def sync_to_async_redis (
0 commit comments