@@ -493,24 +493,34 @@ async def _disconnect_raise(self, conn: Connection, error: Exception):
493
493
):
494
494
raise error
495
495
496
- # COMMAND EXECUTION AND PROTOCOL PARSING
497
- async def execute_command (self , * args , ** options ):
498
- """Execute a command and return a parsed response"""
499
- await self .initialize ()
500
- pool = self .connection_pool
501
- command_name = args [0 ]
502
- conn = self .connection or await pool .get_connection (command_name , ** options )
503
-
496
+ async def _try_send_command_parse_response (self , conn , * args , ** options ):
504
497
try :
505
498
return await conn .retry .call_with_retry (
506
499
lambda : self ._send_command_parse_response (
507
- conn , command_name , * args , ** options
500
+ conn , args [ 0 ] , * args , ** options
508
501
),
509
502
lambda error : self ._disconnect_raise (conn , error ),
510
503
)
504
+ except asyncio .CancelledError :
505
+ await conn .disconnect (nowait = True )
506
+ raise
511
507
finally :
508
+ if self .single_connection_client :
509
+ self ._single_conn_lock .release ()
512
510
if not self .connection :
513
- await pool .release (conn )
511
+ await self .connection_pool .release (conn )
512
+
513
+ # COMMAND EXECUTION AND PROTOCOL PARSING
514
+ async def execute_command (self , * args , ** options ):
515
+ """Execute a command and return a parsed response"""
516
+ await self .initialize ()
517
+ pool = self .connection_pool
518
+ command_name = args [0 ]
519
+ conn = self .connection or await pool .get_connection (command_name , ** options )
520
+
521
+ return await asyncio .shield (
522
+ self ._try_send_command_parse_response (conn , * args , ** options )
523
+ )
514
524
515
525
async def parse_response (
516
526
self , connection : Connection , command_name : Union [str , bytes ], ** options
@@ -749,10 +759,18 @@ async def _disconnect_raise_connect(self, conn, error):
749
759
is not a TimeoutError. Otherwise, try to reconnect
750
760
"""
751
761
await conn .disconnect ()
762
+
752
763
if not (conn .retry_on_timeout and isinstance (error , TimeoutError )):
753
764
raise error
754
765
await conn .connect ()
755
766
767
+ async def _try_execute (self , conn , command , * arg , ** kwargs ):
768
+ try :
769
+ return await command (* arg , ** kwargs )
770
+ except asyncio .CancelledError :
771
+ await conn .disconnect ()
772
+ raise
773
+
756
774
async def _execute (self , conn , command , * args , ** kwargs ):
757
775
"""
758
776
Connect manually upon disconnection. If the Redis server is down,
@@ -761,9 +779,11 @@ async def _execute(self, conn, command, *args, **kwargs):
761
779
called by the # connection to resubscribe us to any channels and
762
780
patterns we were previously listening to
763
781
"""
764
- return await conn .retry .call_with_retry (
765
- lambda : command (* args , ** kwargs ),
766
- lambda error : self ._disconnect_raise_connect (conn , error ),
782
+ return await asyncio .shield (
783
+ conn .retry .call_with_retry (
784
+ lambda : self ._try_execute (conn , command , * args , ** kwargs ),
785
+ lambda error : self ._disconnect_raise_connect (conn , error ),
786
+ )
767
787
)
768
788
769
789
async def parse_response (self , block : bool = True , timeout : float = 0 ):
@@ -1165,6 +1185,18 @@ async def _disconnect_reset_raise(self, conn, error):
1165
1185
await self .reset ()
1166
1186
raise
1167
1187
1188
+ async def _try_send_command_parse_response (self , conn , * args , ** options ):
1189
+ try :
1190
+ return await conn .retry .call_with_retry (
1191
+ lambda : self ._send_command_parse_response (
1192
+ conn , args [0 ], * args , ** options
1193
+ ),
1194
+ lambda error : self ._disconnect_reset_raise (conn , error ),
1195
+ )
1196
+ except asyncio .CancelledError :
1197
+ await conn .disconnect ()
1198
+ raise
1199
+
1168
1200
async def immediate_execute_command (self , * args , ** options ):
1169
1201
"""
1170
1202
Execute a command immediately, but don't auto-retry on a
@@ -1180,13 +1212,13 @@ async def immediate_execute_command(self, *args, **options):
1180
1212
command_name , self .shard_hint
1181
1213
)
1182
1214
self .connection = conn
1183
-
1184
- return await conn . retry . call_with_retry (
1185
- lambda : self ._send_command_parse_response (
1186
- conn , command_name , * args , ** options
1187
- ),
1188
- lambda error : self . _disconnect_reset_raise ( conn , error ),
1189
- )
1215
+ try :
1216
+ return await asyncio . shield (
1217
+ self ._try_send_command_parse_response ( conn , * args , ** options )
1218
+ )
1219
+ except asyncio . CancelledError :
1220
+ await conn . disconnect ()
1221
+ raise
1190
1222
1191
1223
def pipeline_execute_command (self , * args , ** options ):
1192
1224
"""
@@ -1353,6 +1385,19 @@ async def _disconnect_raise_reset(self, conn: Connection, error: Exception):
1353
1385
await self .reset ()
1354
1386
raise
1355
1387
1388
+ async def _try_execute (self , conn , execute , stack , raise_on_error ):
1389
+ try :
1390
+ return await conn .retry .call_with_retry (
1391
+ lambda : execute (conn , stack , raise_on_error ),
1392
+ lambda error : self ._disconnect_raise_reset (conn , error ),
1393
+ )
1394
+ except asyncio .CancelledError :
1395
+ # not supposed to be possible, yet here we are
1396
+ await conn .disconnect (nowait = True )
1397
+ raise
1398
+ finally :
1399
+ await self .reset ()
1400
+
1356
1401
async def execute (self , raise_on_error : bool = True ):
1357
1402
"""Execute all the commands in the current pipeline"""
1358
1403
stack = self .command_stack
@@ -1375,15 +1420,10 @@ async def execute(self, raise_on_error: bool = True):
1375
1420
1376
1421
try :
1377
1422
return await asyncio .shield (
1378
- conn .retry .call_with_retry (
1379
- lambda : execute (conn , stack , raise_on_error ),
1380
- lambda error : self ._disconnect_raise_reset (conn , error ),
1381
- )
1423
+ self ._try_execute (conn , execute , stack , raise_on_error )
1382
1424
)
1383
- except asyncio .CancelledError :
1384
- # not supposed to be possible, yet here we are
1385
- await conn .disconnect (nowait = True )
1386
- raise
1425
+ except RuntimeError :
1426
+ await self .reset ()
1387
1427
finally :
1388
1428
await self .reset ()
1389
1429
0 commit comments