Giter Site home page Giter Site logo

channels_redis's Introduction

Django

Django is a high-level Python web framework that encourages rapid development and clean, pragmatic design. Thanks for checking it out.

All documentation is in the "docs" directory and online at https://docs.djangoproject.com/en/stable/. If you're just getting started, here's how we recommend you read the docs:

  • First, read docs/intro/install.txt for instructions on installing Django.
  • Next, work through the tutorials in order (docs/intro/tutorial01.txt, docs/intro/tutorial02.txt, etc.).
  • If you want to set up an actual deployment server, read docs/howto/deployment/index.txt for instructions.
  • You'll probably want to read through the topical guides (in docs/topics) next; from there you can jump to the HOWTOs (in docs/howto) for specific problems, and check out the reference (docs/ref) for gory details.
  • See docs/README for instructions on building an HTML version of the docs.

Docs are updated rigorously. If you find any problems in the docs, or think they should be clarified in any way, please take 30 seconds to fill out a ticket here: https://code.djangoproject.com/newticket

To get more help:

To contribute to Django:

To run Django's test suite:

Supporting the Development of Django

Django's development depends on your contributions.

If you depend on Django, remember to support the Django Software Foundation: https://www.djangoproject.com/fundraising/

channels_redis's People

Contributors

acu192 avatar adamchainz avatar agronick avatar andrewgodwin avatar andriilahuta avatar astutejoe avatar bbrowning918 avatar carltongibson avatar d-s-e avatar furious-luke avatar jalaziz avatar jberci avatar kradem avatar krukov avatar maiksprenger avatar marksweb avatar michael-k avatar mmcardle avatar nbhargava avatar ngnpope avatar nicois avatar nikolas avatar pirate avatar proofit404 avatar qeternity avatar sevdog avatar tarikki avatar vanschelven avatar vartec avatar wmorrell avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

channels_redis's Issues

asgiref.base_layer.BaseChannelLayer.ChannelFull

I am doing some pen testing on my machine with django_channels. I use asyncio in Python 3.5 to parse UDP packages and send data into the redis channel layer. I sent around 120 packages (nearly) at once and get the following error:

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/asyncio/tasks.py", line 239, in _step
    result = coro.send(None)
  File "udpreceiver/UDPserver.py", line 18, in send_to_redis
    channel_layer.send(channel=channel,message=message)
  File "/Users/sush/ownCloud/server/channel_server/channeled_server/lib/python3.5/site-packages/asgi_redis/core.py", line 103, in send
    raise self.ChannelFull
asgiref.base_layer.BaseChannelLayer.ChannelFull
Task exception was never retrieved
future: <Task finished coro=<send_to_redis() done, defined at udpreceiver/UDPserver.py:8> exception=ChannelFull()>
Traceback (most recent call last):
  File "/Users/sush/ownCloud/server/channel_server/channeled_server/lib/python3.5/site-packages/asgi_redis/core.py", line 98, in send
    args=[self.serialize(message), self.expiry, self.get_capacity(channel)],
  File "/Users/sush/ownCloud/server/channel_server/channeled_server/lib/python3.5/site-packages/redis/client.py", line 2694, in __call__
    return client.evalsha(self.sha, len(keys), *args)
  File "/Users/sush/ownCloud/server/channel_server/channeled_server/lib/python3.5/site-packages/redis/client.py", line 1944, in evalsha
    return self.execute_command('EVALSHA', sha, numkeys, *keys_and_args)
  File "/Users/sush/ownCloud/server/channel_server/channeled_server/lib/python3.5/site-packages/redis/client.py", line 573, in execute_command
    return self.parse_response(connection, command_name, **options)
  File "/Users/sush/ownCloud/server/channel_server/channeled_server/lib/python3.5/site-packages/redis/client.py", line 585, in parse_response
    response = connection.read_response()
  File "/Users/sush/ownCloud/server/channel_server/channeled_server/lib/python3.5/site-packages/redis/connection.py", line 582, in read_response
    raise response
redis.exceptions.ResponseError: full

following versions are installed:

asgi-redis==0.13.1
asgiref==0.14.0
channels==0.17.2
daphne==0.14.3
Django==1.10.3

Any suggestions why this error occurs and what i can do about that?

Questions about license

Hello,

I am sorry, I have already asked a same question about Channels but I have always a doubt for asgi_redis :

Have I to mentione the authors name in my website (using asgi_redis) ?
Have I to mentione something else ?

Thank you !

Encrypt messages

It lacks encryption packets transmitted packets between Django and redis. It would be very cool if it would be possible to encrypt the packets to someone overheard critical data on the channel.
How to look at here is the library?

1.4.3 release notes?

Both Github and Pypi show there is a 1.4.3 release of asgi_redis, but don't see any changelog details for it.

Can you share or update the changelog with what's new in 1.4.3?

Thanks!

python2.7 and python3 working hand in hand

So...

Quite recently I've started moving from python2.7 env to a python3.6. We've re-written the code, everything was working properly and the only thing to do is to put the project on prod and battle-test it.

So I spawned a server, deployed the upgraded app, connected everything to production db and production redis server. And everything seemed to work properly. But there was a problem. There was quite a lot of 502 errors from channels connector. A lot of reconnects. From what I saw, about 25% of websocket connections to that server was failing (I based it on my own experiences, but nginx logs pretty much confirmed it). There was unnaturally more errors on python3 server then on python2.7 server.

When I did manual testing - it turned out, that I had those errors when I refreshed the web page. So basically - I was having trouble establishing the initial connection. I didn't found any problems with websockets when that connection has been established.

So at first I checked the code - but I actually didn't change anything for websocket-serving part. Well, I did have some code for reformatting byte stream into a unicode, but nothing more.

I checked the behavior of daphne and runworker - it seemed to me, that daphne received messages for my requests, but workers didn't receive it at all. I even tried running those commands in debug manually. This shown to me, that runworker command didn't receive connect/disconnect messages sometimes.

This seemed weird to me, as I couldn't replicate that situation in my local environment. I had always 100% success rate in python3 env for connecting.

So today, I've tried spawning another local server, with python2.7 environment and connecting it to my redis db, which I use in python3.6 environment. And to my astonishment - the sheer fact that I connected to redis with python2.7 env (without any traffic), broke python3.6 connection flow.

When I disconnect (disable both daphne and webworkers on python2.7 env) - I'm not having problems connecting to my python3.6 instance.

But as soon as the connection is made from python2.7 servers - it seems to break everything for python3.6 servers.

In the same time - python2.7 servers seem to be unaffected at all.

Has anyone encountered such problems before? I'm actually not sure where the problem is - is it in asgi_redis layer, or somewhere else. Just opening an issue to ask around and let the community know that there might be problems with connecting python2.7 and python3.6 apps in one redis instance.

asgi_redis version I'm using: 1.4.2

Let me know if you need anything else.

Performance improvements.

  1. Some of dependent packages have performance optimizations related with cythonized or C-implemented parts:
    a) msgpack-python, if cython installed then shared C-library built and msgpack used it instead python fallback.
    b) redis, if hiredis installed then fast HiredisParser used.
    So first question is may be we should specify this requirements in dependencies or at least write about them in Readme?

  2. What about asyncio? I see https://github.com/django/asgiref/blob/master/asgiref/inmemory_async.py and extension part in docs (PS. I don't understand why twisted there, if in world may be a lot of frameworks should we write some adapter for each of them) and second question:
    What if I wan't to use aioredis in server part? Should I need add new asgi_aioredis for server and use asgi_redis in django workers, or should I add it to asgi_redis as a extension? And what if I wan't use pub sub in redis as channels backend?

AssertionError: assert pattern.endswith("!")

This line tests that patterns end with a "!".

However, in the django-channels demo project, that is exploding against patterns like:

  • !http.response.?
  • !websocket.send.?

Should it potentially be startswith('!') ?

I did not encounter this problem before upgrading to asgi_redis==0.10.0.

AttributeError: 'RedisChannelLayer' object has no attribute 'ChannelFull'

I am using web sockets with RedisChannelLayer. Frequently get following error:

: Traceback (most recent call last): 
May 19 11:19:14  app/web.1:   File "/app/.heroku/python/lib/python2.7/site-packages/twisted/python/log.py", line 101, in callWithLogger 
May 19 11:19:14  app/web.1:     return callWithContext({"system": lp}, func, *args, **kw) 
May 19 11:19:14  app/web.1:   File "/app/.heroku/python/lib/python2.7/site-packages/twisted/python/log.py", line 84, in callWithContext 
May 19 11:19:14  app/web.1:     return context.call({ILogContext: newCtx}, func, *args, **kw) 
May 19 11:19:14  app/web.1:   File "/app/.heroku/python/lib/python2.7/site-packages/twisted/python/context.py", line 118, in callWithContext 
May 19 11:19:14  app/web.1:     return self.currentContext().callWithContext(ctx, func, *args, **kw) 
May 19 11:19:14  app/web.1:   File "/app/.heroku/python/lib/python2.7/site-packages/twisted/python/context.py", line 81, in callWithContext 
May 19 11:19:14  app/web.1:     return func(*args,**kw) 
May 19 11:19:14  app/web.1: --- <exception caught here> --- 
May 19 11:19:14  app/web.1:   File "/app/.heroku/python/lib/python2.7/site-packages/twisted/internet/posixbase.py", line 597, in _doReadOrWrite 
May 19 11:19:14  app/web.1:     why = selectable.doRead() 
May 19 11:19:14  app/web.1:   File "/app/.heroku/python/lib/python2.7/site-packages/twisted/internet/tcp.py", line 209, in doRead 
May 19 11:19:14  app/web.1:     return self._dataReceived(data) 
May 19 11:19:14  app/web.1:   File "/app/.heroku/python/lib/python2.7/site-packages/twisted/internet/tcp.py", line 215, in _dataReceived 
May 19 11:19:14  app/web.1:     rval = self.protocol.dataReceived(data) 
May 19 11:19:14  app/web.1:   File "/app/.heroku/python/lib/python2.7/site-packages/twisted/protocols/basic.py", line 571, in dataReceived 
May 19 11:19:14  app/web.1:     why = self.lineReceived(line) 
May 19 11:19:14  app/web.1:   File "/app/.heroku/python/lib/python2.7/site-packages/twisted/web/http.py", line 1688, in lineReceived 
May 19 11:19:14  app/web.1:     self.allContentReceived() 
May 19 11:19:14  app/web.1:   File "/app/.heroku/python/lib/python2.7/site-packages/twisted/web/http.py", line 1767, in allContentReceived 
May 19 11:19:14  app/web.1:     req.requestReceived(command, path, version) 
May 19 11:19:14  app/web.1:   File "/app/.heroku/python/lib/python2.7/site-packages/twisted/web/http.py", line 768, in requestReceived 
May 19 11:19:14  app/web.1:     self.process() 
May 19 11:19:14  app/web.1:   File "/app/.heroku/python/lib/python2.7/site-packages/daphne/http_protocol.py", line 128, in process 
May 19 11:19:14  app/web.1:     except self.factory.channel_layer.ChannelFull: 
May 19 11:19:14  app/web.1: exceptions.AttributeError: 'RedisChannelLayer' object has no attribute 'ChannelFull' 

As i understand RedisChannelLayer(object) base class is object but it expects to be of type BaseChannelLayer in daphne http_protocol.py.
Or it is just incompatible with django channels and im using it wrong. Thanks.

Support for redis slave connections

The sentinel-based channel can give you a handle to the current redis master (_master_for())
We would like a way to retrieve and connect to the slaves as well for certain lower-priority things
such as our solution to issue #54. A _slaves_for() would be nice!

Improve sending efficiency for large Groups

This is really just the continuation of django/channels#763, as it was determined that the redis channel layer was causing the issue.

At smaller Group sizes (less than 100) it is not really noticeable. Once you get to 200, some messages are occasionally dropped. At around 400+ it becomes very evident and can even approach a 50% failure rate.

I've created a repo to reproduce this issue very easily: https://github.com/lsapan/channels-mass-broadcast

The repo's README explains everything in depth, but here's everything you need to reproduce it:

git clone https://github.com/lsapan/channels-mass-broadcast.git
cd channels-mass-broadcast
docker-compose pull
docker-compose up

That will start daphne, a worker, redis, etc. Then simply navigate to http://localhost:8000/ in 1-3 unique web browsers and watch the number of messages coming in through the console.

Performance question: while True: lpopmany ?

Hi !

I've been playing with channels and asgi_redis, and what I see in redis-cli monitor is a huge lot of calls to the lua script in lua_lpopmany, which is called in a while True loop : ~100 calls per second.

Do I need to be concerned about performance/load issues when running redis on a very small VM because of the high amount of commands being run ?

I imagine there might be a way to use redis pub/sub features somehow to implement this differently ? https://redis.io/commands#pubsub

Thanks !

Question: Does it work on Python 3.6?

We are using this asgi_redis with python 3.6 and we are having problems setting this up. The docs say:

Redis >= 2.6 is required for asgi_redis. All Channels projects currently support Python 2.7, 3.4 and 3.5.

So not sure it it will work in 3.6. May someone more experienced please confirm?

Remove useless 'continue's

diff --git a/asgi_redis/sentinel.py b/asgi_redis/sentinel.py
--- a/asgi_redis/sentinel.py
+++ b/asgi_redis/sentinel.py
@@ -114,7 +114,6 @@ class RedisSentinelChannelLayer(BaseRedisChannelLayer):
                 break
             except (redis.ConnectionError, redis.TimeoutError) as e:
                 connection_errors.append("Failed to connect to {}: {}".format(sentinel, e))
-                continue
         if master_info is None:
             raise redis.ConnectionError(
                 "Could not get master info from sentinel\n{}.".format("\n".join(connection_errors))
diff --git a/asgi_redis/core.py b/asgi_redis/core.py
index 479411e..506d2dd 100644
--- a/asgi_redis/core.py
+++ b/asgi_redis/core.py
@@ -184,9 +183,7 @@ class BaseRedisChannelLayer(BaseChannelLayer):
                         del message['__asgi_channel__']
                     return channel, message
             # If we only got expired content, try again
-            if got_expired_content:
-                continue
-            else:
+            if not got_expired_content:
                 return None, None
 
     def _receive_list_names(self, channels):
@@ -344,9 +341,7 @@ class BaseRedisChannelLayer(BaseChannelLayer):
                 finally:
                     yield twisted_connection.disconnect()
             # If we only got expired content, try again
-            if got_expired_content:
-                continue
-            else:
+            if not got_expired_content:
                 defer.returnValue((None, None))
 
     ### statistics extension ###

Expose more redis-py configuration options

There are a number of redis-py configuration options that are useful and should be exposed by asgi_redis. Some of them can already be configured via a connection URL, but there are others which cannot.

  • socket_connect_timeout: Integer. Number of seconds to wait for the connection to be established.
  • socket_timeout: Integer. Number of seconds to wait for a response to a Redis command. Has to be higher than 5 otherwise the BLPOP operation used by the workers will always timeout.
  • socket_keepalive: Boolean. Wether to turn on TCP keepalives.
  • socket_keepalive_options: Dict with values used to configure the keepalive mechanism. It is supposed to use as keys the socket options (socket.TCP_KEEPIDLE, socket.TCP_KEEPCNT, socket.TCP_KEEPINTVL) however, in MacOS, the socket.TCP_KEEPIDLE constant does not exist. According to https://opensource.apple.com/source/xnu/xnu-2422.115.4/bsd/netinet/tcp.h the constant that we need is TCP_KEEPALIVE, which has a value of 0x10, so in theory we can pass that value as key in the dict to set the correct value. But maybe it's better to hide this mess from users.

Related to #26.

Cluster configuration

I don't need a completely fault tolerant cluster, but I need each web servers (IP listed below) to appear as a single resource/store for asgi_redis.

2ad4b07c712c9c40c9845dc6d673baaf0a1318e7 10.0.3.11:6379@16379 master - 0 1514391205000 3 connected 8192-12287
82ea477823891419705780d70e5d83f89aeffb17 10.0.3.13:6379@16379 master - 0 1514391205879 4 connected 12288-16383
8bcb722e24dd67b06008beca347ea0b3bac40111 10.0.1.10:6379@16379 master - 0 1514391204577 1 connected 0-4095
28dafba3059b4b9e6343e8fb1cf771aedca560bb 10.0.1.12:6379@16379 myself,master - 0 1514391205000 2 connected 4096-8191

What would I set 'hosts' to in CHANNEL_LAYERS?

Multiple servers, node down handling

I've pitched asgi_rabbitmq in favor of asgi_redis and I have this working using the normal sharding algorithm, worried what happens if one of the nodes goes down and how that is managed?
I know libs like PyLibMC are smart enough to handle nodes that stop responding, and manage them accordingly. Just wondering when a node stops responding how can I expect asgi_redis and channels to react till I scramble around and get the node up again. Thanks.

PaaS Redis connection string is a bit awkward to work with

If I get a Redis connection string that looks like:

redis://h:[email protected]:29739

I can't just pass it as:

 "CONFIG": {"hosts": ["redis://h:[email protected]:29739"]},

I get the following error:

  File "/home/lwm/.local/share/virtualenvs/carbondoomsday-IdcgiUO9/lib/python3.5/site-packages/asgi_redis/core.py", line 102, in _setup_hosts
    final_hosts.append("redis://%s:%d/0" % (entry[0], entry[1]))
TypeError: 'Value' object does not support indexing

So, I need to parse the connection string and split it into host and port? I did see the full string being passed in the documentation but I assume that is out of date or?

pip install fails on Python 2.7

(liveblog)$ pip install asgi_redis
Collecting asgi_redis
Using cached asgi_redis-0.14.1-py2.py3-none-any.whl
Collecting msgpack-python (from asgi_redis)
Using cached msgpack-python-0.4.8.tar.gz
Could not import setuptools which is required to install from a source distribution.
Traceback (most recent call last):
File "/Users/ssteiner/.virtualenvs/liveblog/lib/python2.7/site-packages/pip/req/req_install.py", line 372, in setup_py
import setuptools # noqa
File "/Users/ssteiner/.virtualenvs/liveblog/lib/python2.7/site-packages/setuptools/init.py", line 13, in
from setuptools.extension import Extension
File "/Users/ssteiner/.virtualenvs/liveblog/lib/python2.7/site-packages/setuptools/extension.py", line 9, in
from .monkey import get_unpatched
File "/Users/ssteiner/.virtualenvs/liveblog/lib/python2.7/site-packages/setuptools/monkey.py", line 10, in
from . import msvc
File "/Users/ssteiner/.virtualenvs/liveblog/lib/python2.7/site-packages/setuptools/msvc.py", line 27, in
from . import monkey
ImportError: cannot import name monkey

(liveblog) $ python -V
Python 2.7.12

(liveblog) $pip list
pip (8.1.2)
setuptools (27.1.1)
wheel (0.29.0)

(liveblog)$ pip install --upgrade pip setuptools wheel
Requirement already up-to-date: pip in /Users/ssteiner/.virtualenvs/liveblog/lib/python2.7/site-packages
Requirement already up-to-date: setuptools in /Users/ssteiner/.virtualenvs/liveblog/lib/python2.7/site-packages
Requirement already up-to-date: wheel in /Users/ssteiner/.virtualenvs/liveblog/lib/python2.7/site-packages

Configuration with Unix sockets not working

Afaik I'm up-to-date and configured correctly. I suspect that asgi_redis hasn't been updated with recent Redis changes. I'll let the logs speak for themselves.

Versions:

asgi-redis==1.2.1
asgiref==1.1.1
channels==1.1.2
daphne==1.2.0
Django==1.11
redis==2.10.5
redis-structures==0.1.6

Python 3.4

Configuration:

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "asgi_redis.RedisChannelLayer",
        "CONFIG": {
            "hosts": ["unix:///var/run/redis/redis.sock"],
        },
        "ROUTING": "community.routing.channel_routing",
    },
}

Daphne log:

2017-04-07 02:49:30,515 INFO     Starting server at unix:/var/www/next/community/daphne.sock, channel layer community.asgi:channel_layer.
2017-04-07 02:49:30,516 INFO     HTTP/2 support not enabled (install the http2 and tls Twisted extras)
2017-04-07 02:49:30,516 INFO     Using busy-loop synchronous mode on channel layer
2017-04-07 02:49:30,516 INFO     Listening on endpoint unix:/var/www/next/community/daphne.sock
2017-04-07 02:49:30,533 ERROR    Error trying to receive messages: __init__() got an unexpected keyword argument 'socket_connect_timeout'
2017-04-07 02:49:35,534 ERROR    Error trying to receive messages: __init__() got an unexpected keyword argument 'socket_connect_timeout'
2017-04-07 02:49:40,535 ERROR    Error trying to receive messages: __init__() got an unexpected keyword argument 'socket_connect_timeout'
2017-04-07 02:49:45,536 ERROR    Error trying to receive messages: __init__() got an unexpected keyword argument 'socket_connect_timeout'
2017-04-07 02:49:50,537 ERROR    Error trying to receive messages: __init__() got an unexpected keyword argument 'socket_connect_timeout'
2017-04-07 02:49:55,538 ERROR    Error trying to receive messages: __init__() got an unexpected keyword argument 'socket_connect_timeout'

Daphne Worker log:

2017-04-07 02:50:23,334 - INFO - runworker - Using single-threaded worker.
2017-04-07 02:50:23,334 - INFO - runworker - Running worker against channel layer default (asgi_redis.core.RedisChannelLayer)
2017-04-07 02:50:23,335 - INFO - worker - Listening on channels websocket.connect, websocket.disconnect, websocket.receive
Traceback (most recent call last):
  File "/var/www/next/venv/lib/python3.4/site-packages/redis/connection.py", line 895, in get_connection
    connection = self._available_connections.pop()
IndexError: pop from empty list

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/var/www/next/community/manage.py", line 22, in <module>
    execute_from_command_line(sys.argv)
  File "/var/www/next/venv/lib/python3.4/site-packages/django/core/management/__init__.py", line 363, in execute_from_command_line
    utility.execute()
  File "/var/www/next/venv/lib/python3.4/site-packages/django/core/management/__init__.py", line 355, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/var/www/next/venv/lib/python3.4/site-packages/django/core/management/base.py", line 283, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/var/www/next/venv/lib/python3.4/site-packages/django/core/management/base.py", line 330, in execute
    output = self.handle(*args, **options)
  File "/var/www/next/venv/lib/python3.4/site-packages/channels/management/commands/runworker.py", line 83, in handle
    worker.run()
  File "/var/www/next/venv/lib/python3.4/site-packages/channels/worker.py", line 87, in run
    channel, content = self.channel_layer.receive_many(channels, block=True)
  File "/var/www/next/venv/lib/python3.4/site-packages/asgiref/base_layer.py", line 43, in receive_many
    return self.receive(channels, block)
  File "/var/www/next/venv/lib/python3.4/site-packages/asgi_redis/core.py", line 211, in receive
    result = connection.blpop(list_names, timeout=self.blpop_timeout)
  File "/var/www/next/venv/lib/python3.4/site-packages/redis/client.py", line 1163, in blpop
    return self.execute_command('BLPOP', *keys)
  File "/var/www/next/venv/lib/python3.4/site-packages/redis/client.py", line 570, in execute_command
    connection = pool.get_connection(command_name, **options)
  File "/var/www/next/venv/lib/python3.4/site-packages/redis/connection.py", line 897, in get_connection
    connection = self.make_connection()
  File "/var/www/next/venv/lib/python3.4/site-packages/redis/connection.py", line 906, in make_connection
    return self.connection_class(**self.connection_kwargs)
TypeError: __init__() got an unexpected keyword argument 'socket_connect_timeout'
2017-04-07 02:50:28,350 - INFO - runworker - Using single-threaded worker.
2017-04-07 02:50:28,350 - INFO - runworker - Running worker against channel layer default (asgi_redis.core.RedisChannelLayer)
2017-04-07 02:50:28,351 - INFO - worker - Listening on channels websocket.connect, websocket.disconnect, websocket.receive
Traceback (most recent call last):
  File "/var/www/next/venv/lib/python3.4/site-packages/redis/connection.py", line 895, in get_connection
    connection = self._available_connections.pop()
IndexError: pop from empty list

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/var/www/next/community/manage.py", line 22, in <module>
    execute_from_command_line(sys.argv)
  File "/var/www/next/venv/lib/python3.4/site-packages/django/core/management/__init__.py", line 363, in execute_from_command_line
    utility.execute()
  File "/var/www/next/venv/lib/python3.4/site-packages/django/core/management/__init__.py", line 355, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/var/www/next/venv/lib/python3.4/site-packages/django/core/management/base.py", line 283, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/var/www/next/venv/lib/python3.4/site-packages/django/core/management/base.py", line 330, in execute
    output = self.handle(*args, **options)
  File "/var/www/next/venv/lib/python3.4/site-packages/channels/management/commands/runworker.py", line 83, in handle
    worker.run()
  File "/var/www/next/venv/lib/python3.4/site-packages/channels/worker.py", line 87, in run
    channel, content = self.channel_layer.receive_many(channels, block=True)
  File "/var/www/next/venv/lib/python3.4/site-packages/asgiref/base_layer.py", line 43, in receive_many
    return self.receive(channels, block)
  File "/var/www/next/venv/lib/python3.4/site-packages/asgi_redis/core.py", line 211, in receive
    result = connection.blpop(list_names, timeout=self.blpop_timeout)
  File "/var/www/next/venv/lib/python3.4/site-packages/redis/client.py", line 1163, in blpop
    return self.execute_command('BLPOP', *keys)
  File "/var/www/next/venv/lib/python3.4/site-packages/redis/client.py", line 570, in execute_command
    connection = pool.get_connection(command_name, **options)
  File "/var/www/next/venv/lib/python3.4/site-packages/redis/connection.py", line 897, in get_connection
    connection = self.make_connection()
  File "/var/www/next/venv/lib/python3.4/site-packages/redis/connection.py", line 906, in make_connection
    return self.connection_class(**self.connection_kwargs)
TypeError: __init__() got an unexpected keyword argument 'socket_keepalive_options'
2017-04-07 02:50:33,408 - INFO - runworker - Using single-threaded worker.
2017-04-07 02:50:33,408 - INFO - runworker - Running worker against channel layer default (asgi_redis.core.RedisChannelLayer)
2017-04-07 02:50:33,409 - INFO - worker - Listening on channels websocket.connect, websocket.disconnect, websocket.receive
Traceback (most recent call last):
  File "/var/www/next/venv/lib/python3.4/site-packages/redis/connection.py", line 895, in get_connection
    connection = self._available_connections.pop()
IndexError: pop from empty list

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/var/www/next/community/manage.py", line 22, in <module>
    execute_from_command_line(sys.argv)
  File "/var/www/next/venv/lib/python3.4/site-packages/django/core/management/__init__.py", line 363, in execute_from_command_line
    utility.execute()
  File "/var/www/next/venv/lib/python3.4/site-packages/django/core/management/__init__.py", line 355, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/var/www/next/venv/lib/python3.4/site-packages/django/core/management/base.py", line 283, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/var/www/next/venv/lib/python3.4/site-packages/django/core/management/base.py", line 330, in execute
    output = self.handle(*args, **options)
  File "/var/www/next/venv/lib/python3.4/site-packages/channels/management/commands/runworker.py", line 83, in handle
    worker.run()
  File "/var/www/next/venv/lib/python3.4/site-packages/channels/worker.py", line 87, in run
    channel, content = self.channel_layer.receive_many(channels, block=True)
  File "/var/www/next/venv/lib/python3.4/site-packages/asgiref/base_layer.py", line 43, in receive_many
    return self.receive(channels, block)
  File "/var/www/next/venv/lib/python3.4/site-packages/asgi_redis/core.py", line 211, in receive
    result = connection.blpop(list_names, timeout=self.blpop_timeout)
  File "/var/www/next/venv/lib/python3.4/site-packages/redis/client.py", line 1163, in blpop
    return self.execute_command('BLPOP', *keys)
  File "/var/www/next/venv/lib/python3.4/site-packages/redis/client.py", line 570, in execute_command
    connection = pool.get_connection(command_name, **options)
  File "/var/www/next/venv/lib/python3.4/site-packages/redis/connection.py", line 897, in get_connection
    connection = self.make_connection()
  File "/var/www/next/venv/lib/python3.4/site-packages/redis/connection.py", line 906, in make_connection
    return self.connection_class(**self.connection_kwargs)
TypeError: __init__() got an unexpected keyword argument 'socket_keepalive'

Multiple workers with Redis don't invalidate cache

Hello,

After deploying Django with Daphne and Redis (asgi_redis) as in documentation, I made a Circus config to run 4 workers, Redis and Daphne. The problem is that using multiple workers, the cache is not invalidated at some times. For example I make a change in the app and start refreshing. Sometimes the change will appear, sometimes not. Also, the frontend part of the app is separate (a React app) and not using Django templates. I found no way to specify exactly when to invalidate the cache (after an action, not a number of seconds). And when I use only one worker I don't have this issue. Is this a bug or am I doing something wrong?

Versions:
asgi-redis==1.4.3
channels==1.1.8
daphne==1.4.2
Django==1.11.9

The performance of version 1.4.x

When I upgrade to 1.4.x(1.4.0 or 1.4.1), and visit a url(use ajax)very quickly, then no response for a period of time(more 10 seconds) and no abnormal output found.
When downgrade to 1.3.0 version, the problem disappeared.
I test with different version of channels and daphne, the porblem just about asgi_redis 1.4.x.
My CHANNEL_LAYERS setting like this:

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'asgi_redis.RedisChannelLayer',
        'CONFIG': {'hosts': ['redis://:pwd@redis1', 'redis://:pwd@redis2']},
        'ROUTING': 'MyProject.routing.channel_routing'
    }
}

pipenv installation dependency error

Running pipenv install django channels channels_redis in a new project:

Adding channels_redis to Pipfile's [packages]…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Warning: Your dependencies could not be resolved. You likely have a mismatch in your sub-dependencies.
  You can use $ pipenv install --skip-lock to bypass this mechanism, then run $ pipenv graph to inspect the situation.
Could not find a version that matches asgiref~=2.0.1,~=2.1
Tried: 0.8, 0.9, 0.9.1, 0.10.0, 0.11.0, 0.11.0, 0.11.0, 0.11.1, 0.11.1, 0.11.2, 0.11.2, 0.12.0, 0.12.0, 0.12.1, 0.12.1, 0.13.0, 0.13.0, 0.13.2, 0.13.2, 0.13.3, 0.14.0, 0.14.0, 1.0.0, 1.0.0, 1.0.1, 1.0.1, 1.1.0, 1.1.0, 1.1.1, 1.1.1, 1.1.2, 1.1.2, 2.0.0, 2.0.0, 2.0.1, 2.0.1, 2.1.0, 2.1.0
Warning: Your dependencies could not be resolved. You likely have a mismatch in your sub-dependencies.
  You can use $ pipenv install --skip-lock to bypass this mechanism, then run $ pipenv graph to inspect the situation.
Could not find a version that matches asgiref~=2.0.1,~=2.1
Tried: 0.8, 0.9, 0.9.1, 0.10.0, 0.11.0, 0.11.0, 0.11.0, 0.11.1, 0.11.1, 0.11.2, 0.11.2, 0.12.0, 0.12.0, 0.12.1, 0.12.1, 0.13.0, 0.13.0, 0.13.2, 0.13.2, 0.13.3, 0.14.0, 0.14.0, 1.0.0, 1.0.0, 1.0.1, 1.0.1, 1.1.0, 1.1.0, 1.1.1, 1.1.1, 1.1.2, 1.1.2, 2.0.0, 2.0.0, 2.0.1, 2.0.1, 2.1.0, 2.1.0

Got the same warning when running pipenv install django channels asgi_redis. Is channels_redis the new name for the asgi_redis package? Couldn't find anything about it, but assumed so since 2 was released 15 hours ago, and https://github.com/django/asgi_redis redirects to this repo. (Update: found this blog post which confirms that it was renamed)

I don't know much about dependency management, but is asgiref~=2.0.1,~=2.1 the proper format for this?

Implement tests for sharded mode

Right now, the tests only cover single-host mode; it would be nice to have proper tests for sharded mode as it's the easiest one to get wrong.

"Task was destroyed but it is pending" warning on exit

Any use of the channels_redis backend inside of an async_to_sync wrapper (or some other situations) causes this warning:

Task was destroyed but it is pending!
task: <Task pending coro=<RedisConnection._read_data() done, defined at /home/serg/work/multisend/venv/lib/python3.6/site-packages/aioredis/connection.py:175> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x7fe51d946d98>()]> cb=[Future.set_result()]>

We need to find out what needs to be cleaned up inside channels_redis and... clean it up.

redis reconnect

Django can not work even recoverd the redis after redis down

msgpack-python is renamed to msgpack

Hi,

I ran into an issue Daphne not starting due to a missing msgpack module. The msgpack-python module was installed, but it was missing the msgpack module. I took a look at https://pypi.python.org/pypi/msgpack-python and found this:

msgpack-python is renamed to just msgpack.

It appears to have been done very recently, though. Would it be better to update the dependencies in setup.py to include msgpack instead of msgpack-python?

Happy to add a PR, btw

Twisted Test / FailTest: None != u'sr_test'

More of a question than anything; just upgrading to v1.3.0 and get a failure on just the twisted test (Python v2.7.5, Twisted v17.1.0).

=============================================== FAILURES ===============================================
__________________________________ TwistedTests.test_receive_twisted ___________________________________

result = (None, None), g = <generator object test_receive_twisted at 0x2fefd20>
deferred = <Deferred at 0x2ff4200 current result: None>

    def _inlineCallbacks(result, g, deferred):
        """
        See L{inlineCallbacks}.
        """
        # This function is complicated by the need to prevent unbounded recursion
        # arising from repeatedly yielding immediately ready deferreds.  This while
        # loop and the waiting variable solve that by manually unfolding the
        # recursion.
    
        waiting = [True, # waiting for result?
                   None] # result
    
        while 1:
            try:
                # Send the last result back as the result of the yield expression.
                isFailure = isinstance(result, failure.Failure)
                if isFailure:
                    result = result.throwExceptionIntoGenerator(g)
                else:
>                   result = g.send(result)

/usr/lib64/python2.7/site-packages/twisted/internet/defer.py:1301: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
asgi_redis/tests/test_twisted.py:35: in test_receive_twisted
    self.assertEqual(channel, "sr_test")
/usr/lib64/python2.7/site-packages/twisted/trial/_synctest.py:432: in assertEqual
    super(_Assertions, self).assertEqual(first, second, msg)
E   FailTest: None != u'sr_test'
===================== 1 failed, 52 passed, 87 skipped, 1 xfailed in 24.11 seconds ======================

Should i be concerned? The previous version i was using (1.1.0 worked without any issues which is why I ask).

How to use CHANNEL_LAYERS setting in Django?

models.py

CHANNEL_LAYERS = {
    "default": {
        "ROUTING": "models.routing.channel_routing",
        "BACKEND": "asgi_redis.RedisChannelLayer",
        "CONFIG": {
            "capacity": 100,
            "channel_capacity": {
                "http.request": 200,
                "http.response*": 10,
                "websocket.send*": 110,
            },
        }
    },
}

test.html

<script type="text/javascript">
    function WebSocketBulletLaunch()
    {
            setInterval(function(){
            str = '{"action":"test"}'
            socket.send(str);
        },100);		
    }
</script>

I use test.html to testing,it will 10 request 1s then ChanelFull.
I see capacity default 100 in asgi_redis/core.py and channel_capacity in your answers to other people's questions.I want to know capacity relationship with channel_capacity.When I mass request 1s,it will raise ChanelFull,how to set and testing the relationship.
I also not see the detail description in Channels readme,and I see the following in asgi_redis the following.

Support for configuring the socket_connect_timeout, socket_timeout, socket_keepalive and socket_keepalive_options

How to use them?

Support redis password

Pasword from CHANNEL_LAYERS is not respected in txredisapi.ConnectionPool.

For example:

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'asgi_redis.RedisChannelLayer',
        'CONFIG': {
            'hosts': [
                'redis://:pass@host:port/2'
            ],
         },
        'ROUTING': 'foo.routing.channel_routing', 
    },
}

With this config daphne returns exception like:
Error trying to receive messages: Redis error: could not set dbid=2: NOAUTH Authentication required.

asgi_redis silently fails to send with redis version < 2.6

If someone is running a redis version less than 2.6 then asgi_redis will fail silently in the send() call.

In the exception catch starting here https://github.com/django/asgi_redis/blob/master/asgi_redis/core.py#L107
There is no case for if a different error other than 'full' occurs. Namely if "unknown command 'EVALSHA'" occurs which will happen for redis versions < 2.6.

This can cause users applications to fail to respond for unknown reasons as both the workers and daphne will connect to redis just fine but no information will be passed between them due to this failure.

Considering the default version of redis in EPEL is 2.4 this could cause many people to tear their hair out wondering what is going on.

Address inefficiencies of large receive calls

Doing large receive calls means sending huge BLPOP requests to Redis every time a message is received, which is inefficient in terms of bandwidth. It would be nice to fix this.

Possible options:

  • Lua scripts doing some sort of repeat encoding or compression
  • Rotating through smaller subsets of channels with BLPOP and a timeout
  • Process-specific message lists for process-specific channels, collapsing all channels for one process into a single list (using a process-local part after the !)

Ruled out:

  • Client queues for non-client-specific channels, as this would cause a lot more message loss

Statistics for all available channels?

Having global_statistics() and channel_statistics() is actually the only way to figure out what's going on with channels performance with asgi_redis. The problem with channels_statistics() - it's hard to get statistics about response channels, that can be full too.

Playing with performance tuning and a little bigger scale (~200 websocket connections, 6 daphnes, 12 workers) is it very hard to measure lack of daphnes or lack of workers.

Is there any way to get statistics about all available channels?

Connection <RedisConnection [db:0]> has pending commands, closing it.

While trying to understand what's happening on channels issue 858 I found this message:

[2018-02-09 21:21:04,819: WARNING/ForkPoolWorker-2] Connection <RedisConnection [db:0]> has pending commands, closing it.

I scanned through the getting started guide at https://github.com/jonathanslenders/asyncio-redis and found that each connection was closed, in the examples. I did the same thing on my install and noticed that the message was gone, while it still appeared to work.

Question about redis being full

I'm getting this error after a while when there is like 40 users connected to the server. I'm running 10 workers as separated processes and I'm using django, channels, daphne.

What could I do wrong? Is there some kind of leak or why is there so many messages in queue? Every user sends hearthbeat every 2 seconds and then there are some random messages, for example chat messages and I find it weird. Why is there 2500-4200 keys in redis-cli?

It isn't even lagging. It just becomes full and then every user has to reconnect.

Traceback (most recent call last):
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/channels/worker.py", line 119, in run
consumer(message, **kwargs)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/channels/sessions.py", line 64, in inner
return func(message, *args, **kwargs)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/channels/sessions.py", line 127, in inner
"full wait channel for socket %s" % message.reply_channel.name
asgiref.base_layer.BaseChannelLayer.ChannelFull: Cannot add unordered message to already full wait channel for socket websocket.send!XAVTijfEWuAm
2017-03-13 16:57:18,574 - ERROR - worker - Error processing message with consumer chat.consumers.ws_message:
Traceback (most recent call last):
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/asgi_redis/core.py", line 121, in send
client=connection,
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/redis/client.py", line 2694, in call
return client.evalsha(self.sha, len(keys), *args)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/redis/client.py", line 1944, in evalsha
return self.execute_command('EVALSHA', sha, numkeys, *keys_and_args)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/redis/client.py", line 573, in execute_command
return self.parse_response(connection, command_name, **options)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/redis/client.py", line 585, in parse_response
response = connection.read_response()
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/redis/connection.py", line 582, in read_response
raise response
redis.exceptions.ResponseError: full

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/channels/sessions.py", line 123, in inner
message.channel_layer.send(wait_channel, message.content)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/asgi_redis/core.py", line 126, in send
raise self.ChannelFull
asgiref.base_layer.BaseChannelLayer.ChannelFull

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/channels/worker.py", line 119, in run
consumer(message, **kwargs)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/channels/sessions.py", line 64, in inner
return func(message, *args, **kwargs)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/channels/sessions.py", line 127, in inner
"full wait channel for socket %s" % message.reply_channel.name
asgiref.base_layer.BaseChannelLayer.ChannelFull: Cannot add unordered message to already full wait channel for socket websocket.send!XAVTijfEWuAm
2017-03-13 16:57:32,573 - ERROR - worker - Error processing message with consumer chat.consumers.ws_message:
Traceback (most recent call last):
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/asgi_redis/core.py", line 121, in send
client=connection,
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/redis/client.py", line 2694, in call
return client.evalsha(self.sha, len(keys), *args)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/redis/client.py", line 1944, in evalsha
return self.execute_command('EVALSHA', sha, numkeys, *keys_and_args)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/redis/client.py", line 573, in execute_command
return self.parse_response(connection, command_name, **options)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/redis/client.py", line 585, in parse_response
response = connection.read_response()
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/redis/connection.py", line 582, in read_response
raise response
redis.exceptions.ResponseError: full

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/channels/sessions.py", line 123, in inner
message.channel_layer.send(wait_channel, message.content)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/asgi_redis/core.py", line 126, in send
raise self.ChannelFull
asgiref.base_layer.BaseChannelLayer.ChannelFull

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/channels/worker.py", line 119, in run
consumer(message, **kwargs)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/channels/sessions.py", line 64, in inner
return func(message, *args, **kwargs)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/channels/sessions.py", line 127, in inner
"full wait channel for socket %s" % message.reply_channel.name
asgiref.base_layer.BaseChannelLayer.ChannelFull: Cannot add unordered message to already full wait channel for socket websocket.send!XAVTijfEWuAm

Traceback (most recent call last):
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/channels/worker.py", line 119, in run
consumer(message, **kwargs)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/channels/sessions.py", line 64, in inner
return func(message, *args, **kwargs)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/channels/sessions.py", line 127, in inner
"full wait channel for socket %s" % message.reply_channel.name
asgiref.base_layer.BaseChannelLayer.ChannelFull: Cannot add unordered message to already full wait channel for socket websocket.send!XAVTijfEWuAm
2017-03-13 16:57:18,574 - ERROR - worker - Error processing message with consumer chat.consumers.ws_message:
Traceback (most recent call last):
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/asgi_redis/core.py", line 121, in send
client=connection,
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/redis/client.py", line 2694, in call
return client.evalsha(self.sha, len(keys), *args)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/redis/client.py", line 1944, in evalsha
return self.execute_command('EVALSHA', sha, numkeys, *keys_and_args)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/redis/client.py", line 573, in execute_command
return self.parse_response(connection, command_name, **options)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/redis/client.py", line 585, in parse_response
response = connection.read_response()
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/redis/connection.py", line 582, in read_response
raise response
redis.exceptions.ResponseError: full

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/channels/sessions.py", line 123, in inner
message.channel_layer.send(wait_channel, message.content)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/asgi_redis/core.py", line 126, in send
raise self.ChannelFull
asgiref.base_layer.BaseChannelLayer.ChannelFull

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/channels/worker.py", line 119, in run
consumer(message, **kwargs)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/channels/sessions.py", line 64, in inner
return func(message, *args, **kwargs)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/channels/sessions.py", line 127, in inner
"full wait channel for socket %s" % message.reply_channel.name
asgiref.base_layer.BaseChannelLayer.ChannelFull: Cannot add unordered message to already full wait channel for socket websocket.send!XAVTijfEWuAm
2017-03-13 16:57:32,573 - ERROR - worker - Error processing message with consumer chat.consumers.ws_message:
Traceback (most recent call last):
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/asgi_redis/core.py", line 121, in send
client=connection,
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/redis/client.py", line 2694, in call
return client.evalsha(self.sha, len(keys), *args)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/redis/client.py", line 1944, in evalsha
return self.execute_command('EVALSHA', sha, numkeys, *keys_and_args)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/redis/client.py", line 573, in execute_command
return self.parse_response(connection, command_name, **options)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/redis/client.py", line 585, in parse_response
response = connection.read_response()
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/redis/connection.py", line 582, in read_response
raise response
redis.exceptions.ResponseError: full

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/channels/sessions.py", line 123, in inner
message.channel_layer.send(wait_channel, message.content)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/asgi_redis/core.py", line 126, in send
raise self.ChannelFull
asgiref.base_layer.BaseChannelLayer.ChannelFull

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/channels/worker.py", line 119, in run
consumer(message, **kwargs)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/channels/sessions.py", line 64, in inner
return func(message, *args, **kwargs)
File "/var/www/django/dotaleague.cz/env/lib/python3.5/site-packages/channels/sessions.py", line 127, in inner
"full wait channel for socket %s" % message.reply_channel.name
asgiref.base_layer.BaseChannelLayer.ChannelFull: Cannot add unordered message to already full wait channel for socket websocket.send!XAVTijfEWuAm

Redis does not auto-reconnect after restart

1.versions
python 2.7.6
Django==1.10.1
channels==0.17.3
asgi-redis==1.0.0
2.configuration
CHANNEL_LAYERS = {
"default": {
"BACKEND": "asgi_redis.RedisChannelLayer",
"CONFIG": {
"hosts": [("10.1.10.75", 6379)],
},
"ROUTING": "v1.websocket_routing.channel_routing",
},
}
2.run project
python manage.py runserver 0.0.0.0:8002

2017-01-05 07:51:05,973 - INFO - worker - Listening on channels http.request, websocket.connect, websocket.disconnect, websocket.receive
2017-01-05 07:51:05,973 - INFO - worker - Listening on channels http.request, websocket.connect, websocket.disconnect, websocket.receive
2017-01-05 07:51:05,973 - INFO - worker - Listening on channels http.request, websocket.connect, websocket.disconnect, websocket.receive
2017-01-05 07:51:05,975 - INFO - worker - Listening on channels http.request, websocket.connect, websocket.disconnect, websocket.receive
2017-01-05 07:51:05,976 - INFO - server - Using busy-loop synchronous mode on channel layer
2017-01-05 07:51:05,976 - INFO - server.run - Using busy-loop synchronous mode on channel layer

it is perfect and I can use websocket.

3. stop redis
Exception in thread Thread-3:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/usr/local/lib/python2.7/dist-packages/channels/management/commands/runserver.py", line 155, in run
worker.run()
File "/usr/local/lib/python2.7/dist-packages/channels/worker.py", line 88, in run
channel, content = self.channel_layer.receive_many(channels, block=True)
File "/usr/local/lib/python2.7/dist-packages/asgiref/base_layer.py", line 43, in receive_many
return self.receive(channels, block)
File "/usr/local/lib/python2.7/dist-packages/asgi_redis/core.py", line 152, in receive
result = connection.blpop(list_names, timeout=self.blpop_timeout)
File "/usr/local/lib/python2.7/dist-packages/redis/client.py", line 1163, in blpop
return self.execute_command('BLPOP', *keys)
File "/usr/local/lib/python2.7/dist-packages/redis/client.py", line 579, in execute_command
return self.parse_response(connection, command_name, **options)
File "/usr/local/lib/python2.7/dist-packages/redis/client.py", line 585, in parse_response
response = connection.read_response()
File "/usr/local/lib/python2.7/dist-packages/redis/connection.py", line 577, in read_response
response = self._parser.read_response()
File "/usr/local/lib/python2.7/dist-packages/redis/connection.py", line 238, in read_response
response = self._buffer.readline()
File "/usr/local/lib/python2.7/dist-packages/redis/connection.py", line 168, in readline
self._read_from_socket()
File "/usr/local/lib/python2.7/dist-packages/redis/connection.py", line 143, in _read_from_socket
(e.args,))
ConnectionError: Error while reading from socket: (104, 'Connection reset by peer')

Exception in thread Thread-4:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/usr/local/lib/python2.7/dist-packages/channels/management/commands/runserver.py", line 155, in run
worker.run()
File "/usr/local/lib/python2.7/dist-packages/channels/worker.py", line 88, in run
channel, content = self.channel_layer.receive_many(channels, block=True)
File "/usr/local/lib/python2.7/dist-packages/asgiref/base_layer.py", line 43, in receive_many
return self.receive(channels, block)
File "/usr/local/lib/python2.7/dist-packages/asgi_redis/core.py", line 152, in receive
result = connection.blpop(list_names, timeout=self.blpop_timeout)
File "/usr/local/lib/python2.7/dist-packages/redis/client.py", line 1163, in blpop
return self.execute_command('BLPOP', *keys)
File "/usr/local/lib/python2.7/dist-packages/redis/client.py", line 579, in execute_command
return self.parse_response(connection, command_name, **options)
File "/usr/local/lib/python2.7/dist-packages/redis/client.py", line 585, in parse_response
response = connection.read_response()
File "/usr/local/lib/python2.7/dist-packages/redis/connection.py", line 577, in read_response
response = self._parser.read_response()
File "/usr/local/lib/python2.7/dist-packages/redis/connection.py", line 238, in read_response
response = self._buffer.readline()
File "/usr/local/lib/python2.7/dist-packages/redis/connection.py", line 168, in readline
self._read_from_socket()
File "/usr/local/lib/python2.7/dist-packages/redis/connection.py", line 143, in _read_from_socket
(e.args,))
ConnectionError: Error while reading from socket: (104, 'Connection reset by peer')

Exception in thread Thread-5:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/usr/local/lib/python2.7/dist-packages/channels/management/commands/runserver.py", line 155, in run
worker.run()
File "/usr/local/lib/python2.7/dist-packages/channels/worker.py", line 88, in run
channel, content = self.channel_layer.receive_many(channels, block=True)
File "/usr/local/lib/python2.7/dist-packages/asgiref/base_layer.py", line 43, in receive_many
return self.receive(channels, block)
File "/usr/local/lib/python2.7/dist-packages/asgi_redis/core.py", line 152, in receive
result = connection.blpop(list_names, timeout=self.blpop_timeout)
File "/usr/local/lib/python2.7/dist-packages/redis/client.py", line 1163, in blpop
return self.execute_command('BLPOP', *keys)
File "/usr/local/lib/python2.7/dist-packages/redis/client.py", line 579, in execute_command
return self.parse_response(connection, command_name, **options)
File "/usr/local/lib/python2.7/dist-packages/redis/client.py", line 585, in parse_response
response = connection.read_response()
File "/usr/local/lib/python2.7/dist-packages/redis/connection.py", line 577, in read_response
response = self._parser.read_response()
File "/usr/local/lib/python2.7/dist-packages/redis/connection.py", line 238, in read_response
response = self._buffer.readline()
File "/usr/local/lib/python2.7/dist-packages/redis/connection.py", line 168, in readline
self._read_from_socket()
File "/usr/local/lib/python2.7/dist-packages/redis/connection.py", line 143, in _read_from_socket
(e.args,))
ConnectionError: Error while reading from socket: (104, 'Connection reset by peer')

Exception in thread Thread-2:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/usr/local/lib/python2.7/dist-packages/channels/management/commands/runserver.py", line 155, in run
worker.run()
File "/usr/local/lib/python2.7/dist-packages/channels/worker.py", line 88, in run
channel, content = self.channel_layer.receive_many(channels, block=True)
File "/usr/local/lib/python2.7/dist-packages/asgiref/base_layer.py", line 43, in receive_many
return self.receive(channels, block)
File "/usr/local/lib/python2.7/dist-packages/asgi_redis/core.py", line 152, in receive
result = connection.blpop(list_names, timeout=self.blpop_timeout)
File "/usr/local/lib/python2.7/dist-packages/redis/client.py", line 1163, in blpop
return self.execute_command('BLPOP', *keys)
File "/usr/local/lib/python2.7/dist-packages/redis/client.py", line 579, in execute_command
return self.parse_response(connection, command_name, **options)
File "/usr/local/lib/python2.7/dist-packages/redis/client.py", line 585, in parse_response
response = connection.read_response()
File "/usr/local/lib/python2.7/dist-packages/redis/connection.py", line 577, in read_response
response = self._parser.read_response()
File "/usr/local/lib/python2.7/dist-packages/redis/connection.py", line 238, in read_response
response = self._buffer.readline()
File "/usr/local/lib/python2.7/dist-packages/redis/connection.py", line 168, in readline
self._read_from_socket()
File "/usr/local/lib/python2.7/dist-packages/redis/connection.py", line 143, in _read_from_socket
(e.args,))
ConnectionError: Error while reading from socket: (104, 'Connection reset by peer')

4. recover redis
Django still can not work after I recovered redis except I restart the django

So it is there any options i can config ? just like CONN_MAX_AGE
MySQL can be auto-reconnected after I recovered mysql and no restart django when set CONN_MAX_AGE by None.
Thanks.

RedisChannelLayer.receive runs forever

RedisChannelLayer.receive, that was reworked in #43, now hangs forever if called with block. That was not the case in the previous version (it returned (None, None). This prevents channels Worker from exiting if termed is set to true (e.g. in the signal handler).

Configurable tcp socket keepalive on Redis connection - improved resiliency

Current PaaS solutions have very aggressive pruning of idle TCP connections, which affects ASGI workers since they maintain open connections to Redis and are left waiting for messages indefinitely, not sending anything. I see two solutions for this problem:

  1. A hearbeat protocol that would send "PING" commands periodically to the Redis server.
  2. Ability to configure the socket_keepalive_options of the redis-py connection. It is not possible to provide a value for this via a connection URL.

asgi_redis & asgi-redis

Hi,

Sorry if this is trivial, but I don't understand why after a pip install asgi_redis, pip freeze says that I have asgi-redis. I don't see that asgi-redis anywhere in this repo or on pypi.

TypeError: __init__() got an unexpected keyword argument 'socket_connect_timeout'

Runworker fails to start with asgi_redis >= 1.1:

2017-04-03 15:08:39,237 - INFO - runworker - Using single-threaded worker.
2017-04-03 15:08:39,237 - INFO - runworker - Running worker against channel layer default (asgi_redis.core.RedisChannelLayer)
2017-04-03 15:08:39,238 - INFO - worker - Listening on channels event, http.request, post-account-delete, post-stat-create, websocket.connect, websocket.disconnect, websocket.receive
Traceback (most recent call last):
  File "venv/bin/awesome", line 11, in <module>
    load_entry_point('awesome', 'console_scripts', 'awesome')() 
  File "src/awesome/manage.py", line 8, in main
    execute_from_command_line(sys.argv)
  File "venv/lib/python2.7/site-packages/django/core/management/__init__.py", line 367, in execute_from_command_line
    utility.execute()
  File "venv/lib/python2.7/site-packages/django/core/management/__init__.py", line 359, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "venv/lib/python2.7/site-packages/django/core/management/base.py", line 294, in run_from_argv
    self.execute(*args, **cmd_options)
  File "venv/lib/python2.7/site-packages/django/core/management/base.py", line 345, in execute
    output = self.handle(*args, **options)
  File "venv/lib/python2.7/site-packages/channels/management/commands/runworker.py", line 83, in handle
    worker.run()
  File "venv/lib/python2.7/site-packages/channels/worker.py", line 87, in run
    channel, content = self.channel_layer.receive_many(channels, block=True)
  File "venv/lib/python2.7/site-packages/asgiref/base_layer.py", line 43, in receive_many
    return self.receive(channels, block)
  File "venv/lib/python2.7/site-packages/asgi_redis/core.py", line 188, in receive
    result = connection.blpop(list_names, timeout=self.blpop_timeout)
  File "venv/lib/python2.7/site-packages/redis/client.py", line 1163, in blpop
    return self.execute_command('BLPOP', *keys)
  File "venv/lib/python2.7/site-packages/redis/client.py", line 570, in execute_command
    connection = pool.get_connection(command_name, **options)
  File "venv/lib/python2.7/site-packages/redis/connection.py", line 897, in get_connection
    connection = self.make_connection()
  File "venv/lib/python2.7/site-packages/redis/connection.py", line 906, in make_connection
    return self.connection_class(**self.connection_kwargs)
TypeError: __init__() got an unexpected keyword argument 'socket_connect_timeout'

Os: ubuntu xenial or arch linux
Python: 2.7
Django: 1.10.6
Channels: 1.1
Daphne: 1.2.0
Asgi_redis: 1.1.0 or 1.2.1

This seems to be because UnixDomainSocketConnection does not support socket_connect_timeout.

With asgi_redis 1.0 it works fine, because it doesn't expect every different redis backend to have the same constructor signature.

Perhaps we could replace RedisChannelLayer's constructor to support a connection kwargs dict instead of specific socket_* kwargs ?

Document unix:///path format for redis config

Redis supports unix domain sockets, which are slightly faster than a loopback tcp connection. The redis python bindings have direct support for this. So it should be very easy to add.

I propose the following syntax in order to keep the current syntax untouched.

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "asgi_redis.RedisChannelLayer",
        "CONFIG": {
            "unix": ["/path/to/redis.sock"],
        },
        "ROUTING": "my_project.routing.channel_routing",
    },
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.