7
7
import random
8
8
import string
9
9
import time
10
+ import types
10
11
11
12
import aioredis
12
13
import msgpack
15
16
from channels .layers import BaseChannelLayer
16
17
17
18
19
+ def _wrap_close (loop , pool ):
20
+ """
21
+ Decorate an event loop's close method with our own.
22
+ """
23
+ original_impl = loop .close
24
+
25
+ def _wrapper (self , * args , ** kwargs ):
26
+ # If the event loop was closed, there's nothing we can do anymore.
27
+ if not self .is_closed ():
28
+ self .run_until_complete (pool .close_loop (self ))
29
+ # Restore the original close() implementation after we're done.
30
+ self .close = original_impl
31
+ return self .close (* args , ** kwargs )
32
+
33
+ loop .close = types .MethodType (_wrapper , loop )
34
+
35
+
18
36
class ConnectionPool :
19
37
"""
20
38
Connection pool manager for the channel layer.
@@ -36,6 +54,9 @@ def _ensure_loop(self, loop):
36
54
loop = asyncio .get_event_loop ()
37
55
38
56
if loop not in self .conn_map :
57
+ # Swap the loop's close method with our own so we get
58
+ # a chance to do some cleanup.
59
+ _wrap_close (loop , self )
39
60
self .conn_map [loop ] = []
40
61
41
62
return self .conn_map [loop ], loop
@@ -57,8 +78,9 @@ def push(self, conn):
57
78
"""
58
79
loop = self .in_use [conn ]
59
80
del self .in_use [conn ]
60
- conns , _ = self ._ensure_loop (loop )
61
- conns .append (conn )
81
+ if loop is not None :
82
+ conns , _ = self ._ensure_loop (loop )
83
+ conns .append (conn )
62
84
63
85
def conn_error (self , conn ):
64
86
"""
@@ -74,6 +96,20 @@ def reset(self):
74
96
self .conn_map = {}
75
97
self .in_use = {}
76
98
99
+ async def close_loop (self , loop ):
100
+ """
101
+ Close all connections owned by the pool on the given loop.
102
+ """
103
+ if loop in self .conn_map :
104
+ for conn in self .conn_map [loop ]:
105
+ conn .close ()
106
+ await conn .wait_closed ()
107
+ del self .conn_map [loop ]
108
+
109
+ for k , v in self .in_use .items ():
110
+ if v is loop :
111
+ self .in_use [k ] = None
112
+
77
113
async def close (self ):
78
114
"""
79
115
Close all connections owned by the pool.
@@ -732,7 +768,7 @@ def consistent_hash(self, value):
732
768
"""
733
769
if isinstance (value , str ):
734
770
value = value .encode ("utf8" )
735
- bigval = binascii .crc32 (value ) & 0xfff
771
+ bigval = binascii .crc32 (value ) & 0xFFF
736
772
ring_divisor = 4096 / float (self .ring_size )
737
773
return int (bigval / ring_divisor )
738
774
0 commit comments