django / asgi_ipc

IPC-based ASGI channel layer
BSD 3-Clause "New" or "Revised" License
37 stars 13 forks source link

catch key error that is result of non existing groups #32

Closed Bartzi closed 7 years ago

Bartzi commented 7 years ago

We are using channels and asgi_ipc in our project for sending a live preview of a document to a group of users. We recently updated all of our dependencies and found that the live preview sending via asgi_ipc does not work anymore.

We are basically sending html through the websocket to everyone interested and subscribed to that group. In previous releases it was no problem to send the message to a group without any members, but with the most current version of the code this is not possible anymore and our workers crash in store.py when they try to remove members from the non existing group. We are able to reproduce this error on a range of different Linux based systems in different configurations, I was not able to compile a small standalone code version, that reproduces this error, but I will provide with a step by step list on how to reproduce the error using our system, if there is anybody interested in reproducing the error.

This PR tries to fix this problem, but I'm really not sure whether this is the right way to go.

Steps to reproduce:

  1. Clone our repository
  2. Create a Python 3 virtualenv
  3. Install all requirements from the files requirements.txt, and requirements-deploy.txt
  4. Create a file localsettings.py in the folder _1327 and add the following:
CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "asgi_ipc.IPCChannelLayer",
        "ROUTING": "_1327.routing.channel_routing",
        "CONFIG": {
            "prefix": "1327",
        },
    },
}
  1. run the command python manage.py createsuperuser to create a user
  2. run daphne _1327.asgi:channel_layer
  3. start a worker with python manage.py runworker
  4. open localhost:8000 and login
  5. go to the menu and create a new InformationPage
  6. Enter some text in the text area and wait for the worker to crash with a KeyError

I know these are quite some steps, but I'm really not sure why this is happening and maybe the reason is something else, than my quick and dirty fix.

Please also see the ticket in our repository with the error message.

Please let me know if you need more information

proofit404 commented 7 years ago

Hi, thanks for the contribution!

We need some time to investigate this issue. Make this problem reproduce will be our first goal.

Before that, you can install your fix from PR VCS branch with pip since it already affects your production environment.

mrazzari commented 7 years ago

I'm running into this as well.

Assuming the IPCChannelLayer is set up in settings, here's a simpler way to repro using the manage.py shell:

>>> from channels import Group
>>> Group("does_not_exist").send({"text": "yada yada"})

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/var/www/xyz/.env/local/lib/python2.7/site-packages/channels/channel.py", line 88, in send
    self.channel_layer.send_group(self.name, content)
  File "/var/www/xyz/.env/local/lib/python2.7/site-packages/asgi_ipc/core.py", line 130, in send_group
    for channel in self.group_channels(group):
  File "/var/www/xyz/.env/local/lib/python2.7/site-packages/asgi_ipc/core.py", line 137, in group_channels
    return self.group_store.flush_expired(group)
  File "/var/www/xyz/.env/local/lib/python2.7/site-packages/asgi_ipc/store.py", line 195, in flush_expired
    for item, expiry in value[name].items()
KeyError: u'does_not_exist'

That is, just try to send a message to a non existing group name.

If I try the same using the in-memory layer, nothing happens (ie, no key error - just fails gracefully).

Bartzi commented 7 years ago

Oh yeah, right I can reproduce the error in the same way... funny that I did not think about this easy way earlier...

andrewgodwin commented 7 years ago

This makes sense to me - I'll pull it in, and see if I can add a test to the conformance suite for it. Thanks!

mheppner commented 6 years ago

Is this planned on being added to a release at some point? It didn't make it into 1.4.1.

andrewgodwin commented 6 years ago

I've just put out a 1.4.2 release with this fix in it.