5
5
6
6
from redis .asyncio .client import Redis
7
7
from redis .asyncio .connection import (
8
+ BlockingConnectionPool ,
8
9
Connection ,
9
10
ConnectionPool ,
10
11
EncodableT ,
@@ -203,12 +204,38 @@ async def get_master_address(self):
203
204
def rotate_slaves (self ) -> AsyncIterator :
204
205
"""Round-robin slave balancer"""
205
206
return self .proxy .rotate_slaves ()
207
+
208
+
209
+ class SentinelBlockingConnectionPool (BlockingConnectionPool ):
210
+ """
211
+ Sentinel blocking connection pool.
212
+
213
+ If ``check_connection`` flag is set to True, SentinelManagedConnection
214
+ sends a PING command right after establishing the connection.
215
+ """
216
+
217
+ def __init__ (self , service_name , sentinel_manager , ** kwargs ):
218
+ kwargs ["connection_class" ] = kwargs .get (
219
+ "connection_class" ,
220
+ (
221
+ SentinelManagedSSLConnection
222
+ if kwargs .pop ("ssl" , False )
223
+ else SentinelManagedConnection
224
+ ),
225
+ )
226
+ self .is_master = kwargs .pop ("is_master" , True )
227
+ self .check_connection = kwargs .pop ("check_connection" , False )
228
+ self .proxy = SentinelConnectionPoolProxy (
229
+ connection_pool = self ,
230
+ is_master = self .is_master ,
231
+ check_connection = self .check_connection ,
232
+ service_name = service_name ,
233
+ sentinel_manager = sentinel_manager ,
234
+ )
206
235
super ().__init__ (** kwargs )
207
236
self .connection_kwargs ["connection_pool" ] = weakref .proxy (self )
208
237
self .service_name = service_name
209
238
self .sentinel_manager = sentinel_manager
210
- self .master_address = None
211
- self .slave_rr_counter = None
212
239
213
240
def __repr__ (self ):
214
241
return (
@@ -218,8 +245,11 @@ def __repr__(self):
218
245
219
246
def reset (self ):
220
247
super ().reset ()
221
- self .master_address = None
222
- self .slave_rr_counter = None
248
+ self .proxy .reset ()
249
+
250
+ @property
251
+ def master_address (self ):
252
+ return self .proxy .master_address
223
253
224
254
def owns_connection (self , connection : Connection ):
225
255
check = not self .is_master or (
@@ -228,31 +258,11 @@ def owns_connection(self, connection: Connection):
228
258
return check and super ().owns_connection (connection )
229
259
230
260
async def get_master_address (self ):
231
- master_address = await self .sentinel_manager .discover_master (self .service_name )
232
- if self .is_master :
233
- if self .master_address != master_address :
234
- self .master_address = master_address
235
- # disconnect any idle connections so that they reconnect
236
- # to the new master the next time that they are used.
237
- await self .disconnect (inuse_connections = False )
238
- return master_address
261
+ return await self .proxy .get_master_address ()
239
262
240
- async def rotate_slaves (self ) -> AsyncIterator :
263
+ def rotate_slaves (self ) -> AsyncIterator :
241
264
"""Round-robin slave balancer"""
242
- slaves = await self .sentinel_manager .discover_slaves (self .service_name )
243
- if slaves :
244
- if self .slave_rr_counter is None :
245
- self .slave_rr_counter = random .randint (0 , len (slaves ) - 1 )
246
- for _ in range (len (slaves )):
247
- self .slave_rr_counter = (self .slave_rr_counter + 1 ) % len (slaves )
248
- slave = slaves [self .slave_rr_counter ]
249
- yield slave
250
- # Fallback to the master connection
251
- try :
252
- yield await self .get_master_address ()
253
- except MasterNotFoundError :
254
- pass
255
- raise SlaveNotFoundError (f"No slave found for { self .service_name !r} " )
265
+ return self .proxy .rotate_slaves ()
256
266
257
267
258
268
class Sentinel (AsyncSentinelCommands ):
0 commit comments