Domanda

I am trying to synchronize incoming connections using Redis lpush/blpop.

For example, one user attempts to load the page, and his connection blocks via blpop. As soon as a second user starts loading the page they lpush, releasing the first connection.

Instead the first blpop seems to block the entire server and the second connection never enters the view.

Here is a minimal example of what I'm trying:

views.py:

from django.http import HttpResponse
import redis

r = redis.StrictRedis()

def two_view(request):
    print('Starting request')
    if r.get('waiting') == '1':
        print('Someone is waiting')
        r.set('waiting', 0)
        print('Pushing key')
        r.lpush('waiting_key', 1)
        return HttpResponse('Released lock, we both go')
    else:
        print('Nobody is waiting.')
        r.set('waiting', 1)
        print('Begin waiting for other')
        r.blpop('waiting_key')
        return HttpResponse('set waiting higher, to: {}'.format(r.get('waiting')))

manage.py:

#!/usr/bin/env python
from gevent import monkey
monkey.patch_all()
import os
import sys

if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "basic.settings")

    from django.core.management import execute_from_command_line

    execute_from_command_line(sys.argv)

urls.py:

from django.conf.urls import patterns, include, url
from django.contrib import admin
from views import two_view

admin.autodiscover()

urlpatterns = patterns('',
    url(r'^admin/', include(admin.site.urls)),
    url(r'^$', two_view),
)

And the output when I point two tabs at it:

(env)Vincents-MacBook-Pro:basic vkhougaz$ python manage.py runserver
Validating models...

0 errors found
April 04, 2014 - 02:38:34
Django version 1.6.2, using settings 'basic.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Starting request
Nobody is waiting.
Begin waiting for other

And both tabs never finish loading.

Here is a working example of what I am trying to do:

import redis
from gevent import monkey
import gevent
monkey.patch_all(thread=False)
from time import sleep

conpol = redis.ConnectionPool()

def do_lock_thing_1():
    r = redis.StrictRedis(connection_pool=conpol)
    print('starting thing 1')
    r.blpop('k')
    print('finishing thing 1')

def do_lock_thing_2():
    r = redis.StrictRedis(connection_pool=conpol)

    print('starting thing 2')
    sleep(1)
    r.lpush('k', 1)
    print('finishing thing 2')

r2 = redis.StrictRedis(connection_pool=conpol)

r2.delete('k')

t1 = gevent.spawn(do_lock_thing_1)
t2 = gevent.spawn(do_lock_thing_2)

gevent.joinall([t1, t2])

And the output:

starting thing 1
starting thing 2
<1 second delay>
finishing thing 2
finishing thing 1

What am I missing?

È stato utile?

Soluzione

It turns out that the issue was not with django or gevent or redis, rather chrome was queueing the connections. If I use two different browsers the code works as expected.

Blocking calls with Gevent and WSGI

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top