如何实现redis的pubsub超时功能?

时间:2011-10-24 11:36:34

标签: python redis comet flask

我想使用Redis的pubsub功能来实现comet,但pubsub没有超时,所以如果我ps.listen(),即使客户端关闭了浏览器,它也会阻塞。

生成进程时,

greenlet具有超时功能。但我不知道如何将它们组合在一起。

flask的伪

@app.route('/')
def comet():
    rc = redis.Redis()
    ps = rc.pubsub()
    ps.subscribe('foo')
    for item in ps.listen():
        if item['type'] == 'message':
            return item['data']
    # ps.listen() will block, so how to make it timeout after 30 s?

2 个答案:

答案 0 :(得分:1)

因为你没有线程(我假设这是故意的,在某些情况下是明智的)你必须使用一种中断。信号是Unix系统上的一种中断,允许您在可能阻塞的调用期间返回回调。

这个永不返回的文件打开示例符合您的要求。它来自http://docs.python.org/library/signal.html#module-signal

但警告。因为Python使用全局解释器锁来执行操作系统信号处理,所以它会遇到一些稳定性问题。但这些问题通常很少见。

import signal, os

def handler(signum, frame):
    print 'Signal handler called with signal', signum
    raise IOError("Couldn't open device!")

# Set the signal handler and a 5-second alarm
signal.signal(signal.SIGALRM, handler)
signal.alarm(5)

# This open() may hang indefinitely
fd = os.open('/dev/ttyS0', os.O_RDWR)

signal.alarm(0)          # Disable the alarm

答案 1 :(得分:0)

p = redis.pubsub(
     ignore_subscribe_messages=True
)

p.subscribe(
    DB_PREFIX + CHANEL_KEY
)

message = None
timeout = 20
stop_time = time.time() + timeout

# little hack for setting get_message polling timeout
# because redis-py have bug and first call this method processed
# without timeout
while time.time() < stop_time:
    message = p.get_message(timeout=stop_time - time.time())
    if message:
        break

if message:
    data = json.loads(message["data"])
else:
    raise HTTPRequestTimeout