Skip to content

Commit 2cb1c08

Browse files
astutejoecarltongibson
authored andcommitted
Used UUID4 to guarantee unique channel names.
1 parent 132efcf commit 2cb1c08

File tree

3 files changed

+34
-12
lines changed

3 files changed

+34
-12
lines changed

CHANGELOG.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ Unreleased
33

44
* Updated msgpack requirement to `~=1.0`.
55

6+
* Ensured channel names are unique using UUIDs.
7+
68

79
2.4.2 (2020-02-19)
810
------------------

channels_redis/core.py

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@
55
import hashlib
66
import itertools
77
import logging
8-
import random
9-
import string
108
import sys
119
import time
1210
import types
11+
import uuid
1312

1413
import aioredis
1514
import msgpack
@@ -216,10 +215,7 @@ def __init__(
216215
self._receive_index_generator = itertools.cycle(range(len(self.hosts)))
217216
self._send_index_generator = itertools.cycle(range(len(self.hosts)))
218217
# Decide on a unique client prefix to use in ! sections
219-
# TODO: ensure uniqueness better, e.g. Redis keys with SETNX
220-
self.client_prefix = "".join(
221-
random.choice(string.ascii_letters) for i in range(8)
222-
)
218+
self.client_prefix = uuid.uuid4().hex
223219
# Set up any encryption objects
224220
self._setup_encryption(symmetric_encryption_keys)
225221
# Number of coroutines trying to receive right now
@@ -533,12 +529,7 @@ async def new_channel(self, prefix="specific"):
533529
Returns a new channel name that can be used by something in our
534530
process as a specific channel.
535531
"""
536-
# TODO: Guarantee uniqueness better?
537-
return "%s.%s!%s" % (
538-
prefix,
539-
self.client_prefix,
540-
"".join(random.choice(string.ascii_letters) for i in range(12)),
541-
)
532+
return "%s.%s!%s" % (prefix, self.client_prefix, uuid.uuid4().hex,)
542533

543534
### Flush extension ###
544535

tests/test_core.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import asyncio
2+
import random
23

34
import async_timeout
45
import pytest
@@ -416,3 +417,31 @@ async def test_receive_cancel(channel_layer):
416417
await asyncio.wait_for(task, None)
417418
except asyncio.CancelledError:
418419
pass
420+
421+
422+
@pytest.mark.asyncio
423+
async def test_random_reset__channel_name(channel_layer):
424+
"""
425+
Makes sure resetting random seed does not make us reuse channel names.
426+
"""
427+
428+
channel_layer = RedisChannelLayer()
429+
random.seed(1)
430+
channel_name_1 = await channel_layer.new_channel()
431+
random.seed(1)
432+
channel_name_2 = await channel_layer.new_channel()
433+
434+
assert channel_name_1 != channel_name_2
435+
436+
437+
@pytest.mark.asyncio
438+
async def test_random_reset__client_prefix(channel_layer):
439+
"""
440+
Makes sure resetting random seed does not make us reuse client_prefixes.
441+
"""
442+
443+
random.seed(1)
444+
channel_layer_1 = RedisChannelLayer()
445+
random.seed(1)
446+
channel_layer_2 = RedisChannelLayer()
447+
assert channel_layer_1.client_prefix != channel_layer_2.client_prefix

0 commit comments

Comments
 (0)