leporo / tornado-redis

Asynchronous Redis client that works within Tornado IO loop.
666 stars 162 forks source link

Do not subscribe all time #76

Closed faisalp4p closed 10 years ago

faisalp4p commented 10 years ago

Hi, I building a new application with tornado websocket and tornado-redis, a chat like application. It is very great to work with both of them. Thanks for that.

when a user connect to websocket he will subscribe to channel with his user id. so every message some one sent to him can be listen. a user may connect and disconnect websocket frequent times.

Problem is when user establish a successful socket connection, it cannot subscribe to respected channel all the time. Most of the time it works, but some times it making problem

If anyone have any idea, please help me to solve this issue. and i wonder if any one else experiencing same problem?

Thanks in advance!

hagsteel commented 10 years ago

Could you provide a stack trace with the error you are getting? If it's not an error, do you have some code to show.

I use tornado-redis and I have no problems with it.

faisalp4p commented 10 years ago

@jonashagstedt Thank you for response

My custom subscriber class inherited from BaseSubscriber is below

class PubSub(tornadoredis.pubsub.BaseSubscriber):

def __init__(self, client):
    super(PubSub, self).__init__(client)

def on_message(self, msg):
    if msg.kind == "message":
        for handler in self.subscribers[msg.channel].keys():
            handler.real_time_message(msg.body)

and i created custom RedisClient inheriting usual redis client(not tornado-redis). Inside that class i added two functions subscribe and unsubscribe. i use tornado-redis only for pubsub and redis for other redis uses. you can see the code below

class RedisClient(redis.Redis):

def __init__(self, *args, **kwargs):
    self.async = kwargs['async']
    del kwargs['async']
    super(RedisClient, self).__init__(*args, **kwargs)
    if self.async:
        host = self.connection_pool.connection_kwargs['host']
        port = self.connection_pool.connection_kwargs['port']
        db = self.connection_pool.connection_kwargs['db']

        self.tornadoredis_client = tornadoredis.Client(host, port, db)
        self.tornadoredis_client.connect()
        self.subscriber = PubSub(self.tornadoredis_client)

def subscribe(self, channel, handler):
    self.subscriber.subscribe(channel, handler)

def unsubscribe(self, channel, handler):
    self.subscriber.unsubscribe(channel, handler)

i create an object of this client only one time and keep it globally and reuse it for every socket conection. when a new socket connection is created, in "open" function i call

self.redis_client.subscribe(self.username, self)

It works most of the time, some times it showing problem..but its bad. I doubt whether it because i keep only one client for the socket connection (actually i run 4 clients which is reverse peroxided by nginx)

See if you have any idea bout this

Thanks

leporo commented 10 years ago

Thank you for report.

PubSub helper classes do not handle disconnects properly at the moment. There is a bug filled for this: #74. May the issue be caused with it?

Please try to add a special "disconnect" message handler. I suggest removing all active subscriptions in it or/and scheduling an reconnect-and-then-subscribe attempt.

In fact it's the next thing I'm going to add to BaseSubscriber class after completing #71.

faisalp4p commented 10 years ago

Thanks

This issue is not about restarting redis server.

This issue is not producing any error

when i connect a user through websocket(example: user1) it subscribe to the corresponding channel using "self.redis_client.subscribe(self.username, self)"

and when i run the command "redis-cli pubsub channels", list contains "user1" it is OK when i disconnect and connect multiple times. but some times after a successful websocket connection when i run command "redis-cli pubsub channels" user1 will not be there in the list. when i repeat same process it may work well. The problem is tornado-redis not subscribe to channel even if i call "self.redis_client.subscribe(self.username, self)". so the corresponding user not getting realtime messages.

Sorry, i didn't get that "disconnect" handler part.

leporo commented 10 years ago

Thank you.

I'll look for for possible race condition cases happening when user subscribes to the channel.

On Thu, Sep 25, 2014 at 9:44 AM, faisalp4p notifications@github.com wrote:

Thanks

This issue is not about restarting redis server.

This issue is not producing any error

when i connect a user through websocket(example: user1) it subscribe to the corresponding channel using "self.redis_client.subscribe(self.username, self)"

and when i run the command "redis-cli pubsub channels", list contains "user1" it is OK when i disconnect and connect multiple times. but some times after a successful websocket connection when i run command "redis-cli pubsub channels" user1 will not be there in the list. when i repeat same process it may work well. The problem is tornado-redis not subscribe to channel even if i call "self.redis_client.subscribe(self.username, self)". so the corresponding user not getting realtime messages.

Sorry, i didn't get that "disconnect" handler part.

— Reply to this email directly or view it on GitHub https://github.com/leporo/tornado-redis/issues/76#issuecomment-56784994.

faisalp4p commented 10 years ago

Thank you @leporo

faisalp4p commented 10 years ago

I am really sorry for posting this issue. It was not an issue. This problem was occur because of a terrible bug in my code. tornado-redis is awesome.