55
66try :
77 import redis
8+ from redis .exceptions import RedisError
89except ImportError :
910 redis = None
11+ RedisError = None
12+
13+ try :
14+ import valkey
15+ from valkey .exceptions import ValkeyError
16+ except ImportError :
17+ valkey = None
18+ ValkeyError = None
1019
1120from .pubsub_manager import PubSubManager
1221
@@ -18,7 +27,7 @@ def parse_redis_sentinel_url(url):
1827 redis+sentinel://[:password]@host1:port1,host2:port2,.../db/service_name
1928 """
2029 parsed_url = urlparse (url )
21- if parsed_url .scheme != 'redis+sentinel' :
30+ if parsed_url .scheme not in { 'redis+sentinel' , 'valkey+sentinel' } :
2231 raise ValueError ('Invalid Redis Sentinel URL' )
2332 sentinels = []
2433 for host_port in parsed_url .netloc .split ('@' )[- 1 ].split (',' ):
@@ -71,10 +80,10 @@ class RedisManager(PubSubManager): # pragma: no cover
7180
7281 def __init__ (self , url = 'redis://localhost:6379/0' , channel = 'socketio' ,
7382 write_only = False , logger = None , redis_options = None ):
74- if redis is None :
83+ if redis is None and valkey is None :
7584 raise RuntimeError ('Redis package is not installed '
76- '(Run "pip install redis" in your '
77- 'virtualenv).' )
85+ '(Run "pip install redis" or "pip install valkey" '
86+ 'in your virtualenv).' )
7887 super ().__init__ (channel = channel , write_only = write_only , logger = logger )
7988 self .redis_url = url
8089 self .redis_options = redis_options or {}
@@ -95,27 +104,46 @@ def initialize(self):
95104 'Redis requires a monkey patched socket library to work '
96105 'with ' + self .server .async_mode )
97106
107+ def _get_redis_module_and_error (self ):
108+ parsed_url = urlparse (self .redis_url )
109+ schema = parsed_url .scheme .split ('+' , 1 )[0 ].lower ()
110+ if schema == 'redis' :
111+ if redis is None or RedisError is None :
112+ raise RuntimeError ('Redis package is not installed '
113+ '(Run "pip install redis" in your virtualenv).' )
114+ return redis , RedisError
115+ if schema == 'valkey' :
116+ if valkey is None or ValkeyError is None :
117+ raise RuntimeError ('Valkey package is not installed '
118+ '(Run "pip install valkey" in your virtualenv).' )
119+ return valkey , ValkeyError
120+ error_msg = f'Unsupported Redis URL schema: { schema } '
121+ raise ValueError (error_msg )
122+
98123 def _redis_connect (self ):
99- if not self .redis_url .startswith ('redis+sentinel://' ):
100- self .redis = redis .Redis .from_url (self .redis_url ,
101- ** self .redis_options )
102- else :
124+ module , _ = self ._get_redis_module_and_error ()
125+ parsed_url = urlparse (self .redis_url )
126+ if parsed_url .scheme in {"redis+sentinel" , "valkey+sentinel" }:
103127 sentinels , service_name , connection_kwargs = \
104128 parse_redis_sentinel_url (self .redis_url )
105129 kwargs = self .redis_options
106130 kwargs .update (connection_kwargs )
107- sentinel = redis .sentinel .Sentinel (sentinels , ** kwargs )
131+ sentinel = module .sentinel .Sentinel (sentinels , ** kwargs )
108132 self .redis = sentinel .master_for (service_name or self .channel )
133+ else :
134+ self .redis = module .Redis .from_url (self .redis_url ,
135+ ** self .redis_options )
109136 self .pubsub = self .redis .pubsub (ignore_subscribe_messages = True )
110137
111138 def _publish (self , data ):
112139 retry = True
140+ _ , error = self ._get_redis_module_and_error ()
113141 while True :
114142 try :
115143 if not retry :
116144 self ._redis_connect ()
117145 return self .redis .publish (self .channel , pickle .dumps (data ))
118- except redis . exceptions . RedisError :
146+ except error :
119147 if retry :
120148 logger .error ('Cannot publish to redis... retrying' )
121149 retry = False
@@ -126,16 +154,17 @@ def _publish(self, data):
126154 def _redis_listen_with_retries (self ):
127155 retry_sleep = 1
128156 connect = False
157+ _ , error = self ._get_redis_module_and_error ()
129158 while True :
130159 try :
131160 if connect :
132161 self ._redis_connect ()
133162 self .pubsub .subscribe (self .channel )
134163 retry_sleep = 1
135164 yield from self .pubsub .listen ()
136- except redis . exceptions . RedisError :
165+ except error :
137166 logger .error ('Cannot receive from redis... '
138- 'retrying in {} secs' . format ( retry_sleep ) )
167+ f 'retrying in { retry_sleep } secs' )
139168 connect = True
140169 time .sleep (retry_sleep )
141170 retry_sleep *= 2
0 commit comments