Spontaneous websocket disconnect with Valkey, Django-valkey and/or Channels-valkey

@amirreza8002

I am working on the project from chapters 12 - 17 of the book Django5 by Example. The book uses redis, however I have swapped-out redis for valkey in dockerized and non-dockerized versions of the project. My requirements include valkey, django-valkey, and channels-valkey.

I also have non-dockerized and dockerized project versions that employ redis.

Generally, the valkey version of the project performs the same as the redis version. However there is one issue.

The project has a chatroom with the standard channels/daphne server set-up one sees in so many channels tutorials.

I have encountered a bug in the valkey versions, and I do not know which part of the codebase of all the different valkey packages is responsible.

The bug:
When a chatroom is open, the websocket disconnects spontaneously - no user input necessary - after exactly 5 secs.

In my investigation I found, at around line 555 of site-packages/valkey/asyncio/connection.py, read_timeout is set to 5 (seconds) and self.protocol is set to 2. Inserting this code:

read_timeout = None
self.protocol = 3

… corrects the issue in the non-dockerized version, but not the dockerized version.

The valkey code is sprinkled at several points with a timeout variable of some type that is set to 5.

channels_valkey.core.py has this line:

brpop_timeout = 5

… however it has no other hard-coded timeout variables.

django-valkey does not appear to have any hard-coded timeout variables.

Microsoft Copilot and I are exhausted from troubleshooting this issue. I have made a bug report at valkey.io. Any insights from the collective membership here is appreciated.

Working with Devin AI on valkey.io, I seem to have come up with a solution.

Changes to settings.py:


from channels_valkey.core import ValkeyChannelLayer

CACHES = {
    'default': {
        'BACKEND': 'django_valkey.cache.ValkeyCache',
        'LOCATION': 'redis://cache:6379/1',
        'CONNECTION_POOL_KWARGS': {  
            'socket_timeout': 300,  # 5 minutes for ongoing operations  
            'socket_connect_timeout': 30,  # 30 seconds for connection establishment  
        },
        'OPTIONS': {
            'CLIENT_CLASS': 'django_valkey.client.DefaultClient',
            # Optional extras:
            # 'PASSWORD': 'your-valkey-password',
            # 'SERIALIZER': 'django_valkey.serializers.pickle.PickleSerializer',
        },
    }
}

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_valkey.core.ValkeyChannelLayer",
        "CONFIG": {
            "hosts": ["redis://cache:6379/0?socket_timeout=300&socket_connect_timeout=30"],  
        },
    },
}

Devin seems to think channels-valkey has different variables from channels-redis, necessitating this line of code:

"hosts": ["redis://cache:6379/0?socket_timeout=300&socket_connect_timeout=30"],

I used ‘diff’ on all the channel modules and I do not see any difference in the variable names. Not sure what exactly is causing the bug, However the application now behaves as expected.

hi, thanks for reaching out :raising_hands:

channels-valkey is a mirror of channels-redis, and there are no different variables

you probably can pass socket_timeout as a dictionary, something like:

            "hosts":[{
                "address": "valkey://user@host:port",
                "socket_timeout": 300,
            }]

which is cleaner, imo

about django-valkey, you might consider settings socket timeout like Basic configuration - django valkey since it adds some safety checks

also, if not, i recommend using the latest version ofchannels-valkey, since it has some changes to match the new channels variables

the reason changing the source code didn’t work with docker, is probably because you changed the wrong source code, since docker installs packages in it’s own space (usually), tho can’t say for sure without more info.
anyway you almost never want to rely on modifying package source code in your projects, unless for debugging.

if you have more problems, let me know

Tried that. Error came back with socket_timeout as an unrecognized variable.

Did that. 0.3.0

I switched this back to the original code once I found a working solution. It was all part of trying to figure-out why a 5 second time-out is occurring.

do you have the traceback?
i tested, it worked without problem