@@ -500,28 +500,37 @@ async def _disconnect_raise(self, conn: Connection, error: Exception):
500
500
):
501
501
raise error
502
502
503
- # COMMAND EXECUTION AND PROTOCOL PARSING
504
- async def execute_command (self , * args , ** options ):
505
- """Execute a command and return a parsed response"""
506
- await self .initialize ()
507
- pool = self .connection_pool
508
- command_name = args [0 ]
509
- conn = self .connection or await pool .get_connection (command_name , ** options )
510
-
511
- if self .single_connection_client :
512
- await self ._single_conn_lock .acquire ()
503
+ async def _try_send_command_parse_response (self , conn , * args , ** options ):
513
504
try :
514
505
return await conn .retry .call_with_retry (
515
506
lambda : self ._send_command_parse_response (
516
- conn , command_name , * args , ** options
507
+ conn , args [ 0 ] , * args , ** options
517
508
),
518
509
lambda error : self ._disconnect_raise (conn , error ),
519
510
)
511
+ except asyncio .CancelledError :
512
+ await conn .disconnect (nowait = True )
513
+ raise
520
514
finally :
521
515
if self .single_connection_client :
522
516
self ._single_conn_lock .release ()
523
517
if not self .connection :
524
- await pool .release (conn )
518
+ await self .connection_pool .release (conn )
519
+
520
+ # COMMAND EXECUTION AND PROTOCOL PARSING
521
+ async def execute_command (self , * args , ** options ):
522
+ """Execute a command and return a parsed response"""
523
+ await self .initialize ()
524
+ pool = self .connection_pool
525
+ command_name = args [0 ]
526
+ conn = self .connection or await pool .get_connection (command_name , ** options )
527
+
528
+ if self .single_connection_client :
529
+ await self ._single_conn_lock .acquire ()
530
+
531
+ return await asyncio .shield (
532
+ self ._try_send_command_parse_response (conn , * args , ** options )
533
+ )
525
534
526
535
async def parse_response (
527
536
self , connection : Connection , command_name : Union [str , bytes ], ** options
@@ -765,10 +774,18 @@ async def _disconnect_raise_connect(self, conn, error):
765
774
is not a TimeoutError. Otherwise, try to reconnect
766
775
"""
767
776
await conn .disconnect ()
777
+
768
778
if not (conn .retry_on_timeout and isinstance (error , TimeoutError )):
769
779
raise error
770
780
await conn .connect ()
771
781
782
+ async def _try_execute (self , conn , command , * arg , ** kwargs ):
783
+ try :
784
+ return await command (* arg , ** kwargs )
785
+ except asyncio .CancelledError :
786
+ await conn .disconnect ()
787
+ raise
788
+
772
789
async def _execute (self , conn , command , * args , ** kwargs ):
773
790
"""
774
791
Connect manually upon disconnection. If the Redis server is down,
@@ -777,9 +794,11 @@ async def _execute(self, conn, command, *args, **kwargs):
777
794
called by the # connection to resubscribe us to any channels and
778
795
patterns we were previously listening to
779
796
"""
780
- return await conn .retry .call_with_retry (
781
- lambda : command (* args , ** kwargs ),
782
- lambda error : self ._disconnect_raise_connect (conn , error ),
797
+ return await asyncio .shield (
798
+ conn .retry .call_with_retry (
799
+ lambda : self ._try_execute (conn , command , * args , ** kwargs ),
800
+ lambda error : self ._disconnect_raise_connect (conn , error ),
801
+ )
783
802
)
784
803
785
804
async def parse_response (self , block : bool = True , timeout : float = 0 ):
@@ -1181,6 +1200,18 @@ async def _disconnect_reset_raise(self, conn, error):
1181
1200
await self .reset ()
1182
1201
raise
1183
1202
1203
+ async def _try_send_command_parse_response (self , conn , * args , ** options ):
1204
+ try :
1205
+ return await conn .retry .call_with_retry (
1206
+ lambda : self ._send_command_parse_response (
1207
+ conn , args [0 ], * args , ** options
1208
+ ),
1209
+ lambda error : self ._disconnect_reset_raise (conn , error ),
1210
+ )
1211
+ except asyncio .CancelledError :
1212
+ await conn .disconnect ()
1213
+ raise
1214
+
1184
1215
async def immediate_execute_command (self , * args , ** options ):
1185
1216
"""
1186
1217
Execute a command immediately, but don't auto-retry on a
@@ -1196,13 +1227,13 @@ async def immediate_execute_command(self, *args, **options):
1196
1227
command_name , self .shard_hint
1197
1228
)
1198
1229
self .connection = conn
1199
-
1200
- return await conn . retry . call_with_retry (
1201
- lambda : self ._send_command_parse_response (
1202
- conn , command_name , * args , ** options
1203
- ),
1204
- lambda error : self . _disconnect_reset_raise ( conn , error ),
1205
- )
1230
+ try :
1231
+ return await asyncio . shield (
1232
+ self ._try_send_command_parse_response ( conn , * args , ** options )
1233
+ )
1234
+ except asyncio . CancelledError :
1235
+ await conn . disconnect ()
1236
+ raise
1206
1237
1207
1238
def pipeline_execute_command (self , * args , ** options ):
1208
1239
"""
@@ -1369,6 +1400,19 @@ async def _disconnect_raise_reset(self, conn: Connection, error: Exception):
1369
1400
await self .reset ()
1370
1401
raise
1371
1402
1403
+ async def _try_execute (self , conn , execute , stack , raise_on_error ):
1404
+ try :
1405
+ return await conn .retry .call_with_retry (
1406
+ lambda : execute (conn , stack , raise_on_error ),
1407
+ lambda error : self ._disconnect_raise_reset (conn , error ),
1408
+ )
1409
+ except asyncio .CancelledError :
1410
+ # not supposed to be possible, yet here we are
1411
+ await conn .disconnect (nowait = True )
1412
+ raise
1413
+ finally :
1414
+ await self .reset ()
1415
+
1372
1416
async def execute (self , raise_on_error : bool = True ):
1373
1417
"""Execute all the commands in the current pipeline"""
1374
1418
stack = self .command_stack
@@ -1391,15 +1435,10 @@ async def execute(self, raise_on_error: bool = True):
1391
1435
1392
1436
try :
1393
1437
return await asyncio .shield (
1394
- conn .retry .call_with_retry (
1395
- lambda : execute (conn , stack , raise_on_error ),
1396
- lambda error : self ._disconnect_raise_reset (conn , error ),
1397
- )
1438
+ self ._try_execute (conn , execute , stack , raise_on_error )
1398
1439
)
1399
- except asyncio .CancelledError :
1400
- # not supposed to be possible, yet here we are
1401
- await conn .disconnect (nowait = True )
1402
- raise
1440
+ except RuntimeError :
1441
+ await self .reset ()
1403
1442
finally :
1404
1443
await self .reset ()
1405
1444
0 commit comments