Skip to content

Commit 2dfc892

Browse files
Rusox89originmarkets-antoniodudarev
authored andcommitted
ConnectionPool.pop must ensure active connections are returned. (#178)
Co-authored-by: originmarkets-antoniodudarev <[email protected]>
1 parent 8efee75 commit 2dfc892

File tree

2 files changed

+36
-4
lines changed

2 files changed

+36
-4
lines changed

channels_redis/core.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ async def pop(self, loop=None):
6969
if not conns:
7070
conns.append(await aioredis.create_redis(**self.host, loop=loop))
7171
conn = conns.pop()
72+
if conn.closed:
73+
conn = await self.pop(loop=loop)
74+
return conn
7275
self.in_use[conn] = loop
7376
return conn
7477

@@ -615,9 +618,11 @@ async def group_send(self, group, message):
615618
x.decode("utf8") for x in await connection.zrange(key, 0, -1)
616619
]
617620

618-
connection_to_channel_keys, channel_keys_to_message, channel_keys_to_capacity = self._map_channel_keys_to_connection(
619-
channel_names, message
620-
)
621+
(
622+
connection_to_channel_keys,
623+
channel_keys_to_message,
624+
channel_keys_to_capacity,
625+
) = self._map_channel_keys_to_connection(channel_names, message)
621626

622627
for connection_index, channel_redis_keys in connection_to_channel_keys.items():
623628

tests/test_core.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from async_generator import async_generator, yield_
66

77
from asgiref.sync import async_to_sync
8-
from channels_redis.core import ChannelFull, RedisChannelLayer
8+
from channels_redis.core import ChannelFull, ConnectionPool, RedisChannelLayer
99

1010
TEST_HOSTS = [("localhost", 6379)]
1111

@@ -323,6 +323,33 @@ async def test_group_send_capacity(channel_layer):
323323
await channel_layer.receive(channel)
324324

325325

326+
@pytest.mark.asyncio
327+
async def test_connection_pool_pop():
328+
"""
329+
Makes sure that the connection pool does not return closed connections
330+
"""
331+
332+
# Setup scenario
333+
connection_pool = ConnectionPool({"address": TEST_HOSTS[0]})
334+
conn = await connection_pool.pop()
335+
336+
# Emualte a disconnect and return it to the pool
337+
conn.close()
338+
assert conn.closed == True
339+
connection_pool.push(conn)
340+
341+
# Ensure the closed connection is inside the pool
342+
conn_map_values = list(connection_pool.conn_map.values())
343+
assert len(conn_map_values) == 1
344+
conns = conn_map_values[0]
345+
assert len(conns) == 1
346+
assert conns[0].closed == True
347+
348+
# Retrieve new connection
349+
conn = await connection_pool.pop()
350+
assert conn.closed == False
351+
352+
326353
@pytest.mark.asyncio
327354
async def test_receive_cancel(channel_layer):
328355
"""

0 commit comments

Comments
 (0)