channels 3.0.0: Only last connected socket receives all socket messages

Created on 30 Oct 2020  路  17Comments  路  Source: django/channels

Hi, thank you for the great new release. I'm new to channels and therefore I built the tutorial chat app in v2.4.0. This worked perfectly fine.
Now I switched to v.3.0.0, adapted the routing.py as well as asgi.py and have now a strange behaviour:

  1. Open one browser window. Sent messages are displayed just fine
  2. Add browser window. Messages displayed in the last window and there twice. Regardless which side sent them.
  3. Add browser window. Messages appear again only in the last window and displayed three times.

As CHANNEL_LAYERS I tested both 'channels_redis.core.RedisChannelLayer' as well as 'channels.layers.InMemoryChannelLayer' to sort this out.

I use the testserver with 'python3 manage.py runserver'.
There is no error message I could give as starting point.

Rolling back to v2.4.0 and removing '.as_asgi()' in routing.py makes it work again...
websocket_urlpatterns = [
re_path(r'ws/chat/(?P\w+)/$', consumers.ChatConsumer.as_asgi()),
]

Environment: python 3.8.5
aioredis==1.3.1
asgiref==3.3.0
async-timeout==3.0.1
attrs==20.2.0
autobahn==20.7.1
Automat==20.2.0
cffi==1.14.3
channels==3.0.0
channels-redis==3.2.0
constantly==15.1.0
cryptography==3.2.1
daphne==3.0.0
Django==3.1.2
hiredis==1.1.0
hyperlink==20.0.1
idna==2.10
incremental==17.5.0
msgpack==1.0.0
pyasn1==0.4.8
pyasn1-modules==0.2.8
pycparser==2.20
PyHamcrest==2.0.2
pyOpenSSL==19.1.0
pytz==2020.1
service-identity==18.1.0
six==1.15.0
sqlparse==0.4.1
Twisted==20.3.0
txaio==20.4.1
zope.interface==5.1.2

bug

Most helpful comment

Channels 2 will not work with Django 3.1's async def views, since AsgiHandler doesn't have an async request pathway. But other than that it continues to work without issue.

Channels 3 works fine apart from SessionMiddleware. I'm looking at the error here and will release a fix for that as soon as it's ready.

All 17 comments

I agree with you. The same problem here. Probably there is any kind of bug...

I have tested with Django 3.1 and Django 3.1.2 and Channels3.

@carltongibson I think the issue is with SessionMiddleware - scope (and other variables) gets overwritten as it's stored on the instance.

Yes, SessionMiddleware is still wrongly holding and manipulating the scope on self.

https://github.com/django/channels/blob/3ab3f42d34da51e4d7c514c88ce6f49b722c58bf/channels/sessions.py#L149

That needs regression tests and a rework.

So this basically means whole thing doesn't work, right? Can we expect an update soon?

So this basically means whole thing doesn't work, right? Can we expect an update soon?

I suggest using channels ver. 2.4.0 until that bug gets fixed.

@KStenK thanks, doing that now. So far seems to be OK, but in general should 2.4.0 be working fine with Django 3.1?

@KStenK thanks, doing that now. So far seems to be OK, but in general should 2.4.0 be working fine with Django 3.1?

I guess so. Works fine for me so far. There are few problems in the development environment, which I hope gets fixed in version 3.0 but otherwise, everything works fine.

Channels 2 will not work with Django 3.1's async def views, since AsgiHandler doesn't have an async request pathway. But other than that it continues to work without issue.

Channels 3 works fine apart from SessionMiddleware. I'm looking at the error here and will release a fix for that as soon as it's ready.

I also encountered this error, tried to overcome it all morning, then still looked here...
Until I roll back to 2.4.0

Hi all. I've got #1553, which I'm hoping will resolve this. Can I ask if anyone can give that a run to confirm? Thanks.

The error I am getting which is related to SessionMiddleware is this (may be of help)

RuntimeError: Unexpected ASGI message 'http.response.start' sent, after response already completed.

If I bypass SessionMiddleware's send call, everything starts working fine. I am running Ariandne Graphql server, which works fine for normal graphql queries but fails for introspection queries. Some basic debugging reveals that there is an
http.response.start followed by http.response.body followed by another http.response.start with Content-Length of exactly one more than the previous start.

My app routing is this

graphql_app = get_protected_app(
    AuthMiddlewareStack(
        get_graphql_app(),
    ),
)


application = ProtocolTypeRouter(
    {
        'http': URLRouter(
            [
                path(
                    'graphql/',
                    cast(Callable[..., HttpResponseBase], graphql_app),
                ),
                re_path(r'', get_asgi_application()),
            ],
        ),
    },
)

@carltongibson Didn't test it live, but my tests are passing now. Thanks for the fix!

@gghildyal is this with 3.0.0 or my branch in #1553? It might be worth a separate issue as it doesn't look necessarily like the same thing. It would be helpful if we could reduce it to a smaller example.

@laevilgenius Thanks for testing!

@carltongibson My scenario is also fixed by #1553 .

This is fixed in the main development branch. I'll prepare 3.0.1 shortly.

Thanks all!

3.0.1 is available on PyPI now: https://pypi.org/project/channels/3.0.1/

Was this page helpful?
0 / 5 - 0 ratings

Related issues

joshua-s picture joshua-s  路  30Comments

agateblue picture agateblue  路  29Comments

Ya2s picture Ya2s  路  22Comments

ahaltindis picture ahaltindis  路  41Comments

ostcar picture ostcar  路  29Comments