Skip to content

Commit a623e78

Browse files
committed
respect channel layer capacity in RedisChannelLayer.receive_buffer
respect the capacity setting so that the receive_buffer does not grow without bounds see: #212
1 parent 2075071 commit a623e78

File tree

1 file changed

+17
-1
lines changed

1 file changed

+17
-1
lines changed

channels_redis/core.py

+17-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import base64
33
import binascii
44
import collections
5+
import functools
56
import hashlib
67
import itertools
78
import logging
@@ -179,6 +180,19 @@ class UnsupportedRedis(Exception):
179180
pass
180181

181182

183+
class BoundedQueue(asyncio.Queue):
184+
def put_nowait(self, item):
185+
if self.full():
186+
# see: https://github.com/django/channels_redis/issues/212
187+
# if we actually get into this code block, it likely means that
188+
# this specific consumer has stopped reading
189+
# if we get into this code block, it's better to drop messages
190+
# that exceed the channel layer capacity than to continue to
191+
# malloc() forever
192+
self.get_nowait()
193+
return super(BoundedQueue, self).put_nowait(item)
194+
195+
182196
class RedisChannelLayer(BaseChannelLayer):
183197
"""
184198
Redis channel layer.
@@ -226,7 +240,9 @@ def __init__(
226240
# Event loop they are trying to receive on
227241
self.receive_event_loop = None
228242
# Buffered messages by process-local channel name
229-
self.receive_buffer = collections.defaultdict(asyncio.Queue)
243+
self.receive_buffer = collections.defaultdict(
244+
functools.partial(BoundedQueue, self.capacity)
245+
)
230246
# Detached channel cleanup tasks
231247
self.receive_cleaners = []
232248
# Per-channel cleanup locks to prevent a receive starting and moving

0 commit comments

Comments
 (0)