Skip to content

Commit 55e203f

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 55e203f

File tree

1 file changed

+18
-1
lines changed

1 file changed

+18
-1
lines changed

channels_redis/core.py

+18-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,20 @@ class UnsupportedRedis(Exception):
179180
pass
180181

181182

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

0 commit comments

Comments
 (0)