Django / Gevent Socket.IO с Redis Pubsub. Где я могу положить вещи?

У меня есть изолированный скрипт на python, который просто собирает данные из потокового API Twitter, а затем при получении каждого сообщения, используя redis pubsub, который он публикует на канале «твиты». Вот этот скрипт:

def main():
    username = "username"
    password = "password"
    track_list = ["apple", "microsoft", "google"]

    with tweetstream.FilterStream(username, password, track=track_list) as stream:
        for tweet in stream:
            text = tweet["text"]
            user = tweet["user"]["screen_name"]
            message = {"text": text, "user": user}
            db.publish("tweets", message)

if __name__ == '__main__':
    try:
        print "Started..."
        main()
    except KeyboardInterrupt:
        print '\nGoodbye!'

Моя реализация socket.io на стороне сервера выполняется с использованием django-socketio (на основе gevent-socketio)https://github.com/stephenmcd/django-socketio который просто предоставляет несколько вспомогательных декораторов, а также метод broadcast_channel. Поскольку это сделано в django, я просто поместил этот код в views.py просто для того, чтобы он был импортирован. Мой код views.py:

def index(request):
    return render_to_response("twitter_app/index.html", {
    }, context_instance=RequestContext(request))

def _listen(socket):
    db = redis.Redis(host="localhost", port=6379, db=0)
    client = db.pubsub()
    client.subscribe("tweets")
    tweets = client.listen()

    while True:
        tweet = tweets.next()
        tweet_data = ast.literal_eval(tweet["data"])
        message = {"text": tweet_data["text"], "user": tweet_data["user"], "type": "tweet"}
        socket.broadcast_channel(message)

@on_subscribe(channel="livestream")
def subscribe(request, socket, context, channel):
    g = Greenlet.spawn(_listen, socket)

Клиентская сторона socket.io JavaScript просто подключается и подписывается на канал «прямой эфир» и фиксирует все полученные сообщения на этот канал:

var socket = new io.Socket();
socket.connect();
socket.on('connect', function() {
    socket.subscribe("livestream");
});
socket.on('message', function(data) {
    console.log(data);
});

Очевидная проблема с этим кодом заключается в том, что каждый раз, когда на странице открывается новое окно пользователя или браузера, создается новый метод _listen, а твиты подписываются и транслируются для каждого пользователя, что приводит к получению дубликатов сообщений на клиенте. Мой вопрос: где было бы правильное место для размещения метода _listen, чтобы он создавался только один раз, независимо от количества клиентов? Также следует помнить, что метод broadcast_channel является методом экземпляра сокета.

Ответы на вопрос(1)

Ваш ответ на вопрос