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

发布于 2024-12-11 20:28:54 字数 436 浏览 0 评论 0原文

我想使用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?

I want to use Redis's pubsub feature to implement comet, but pubsub doesn't have timeout, so if I use ps.listen(), it will block, even if client closes browser.

Greenlet has a timeout feature when spawn process, but I don't know how to combine them.

Flask's pseudo code:

@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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

迷迭香的记忆 2024-12-18 20:28:54

因为你不是线程(我假设这是故意的,并且在某些情况下是明智的),所以你必须使用某种类型的中断。信号是 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

Because you're not threading (and I'm assuming this is intentional and in some cases wise) you must use a type of interrupt. Signals are a type of interrupt on Unix systems to allow you to return to a callback during a call that could block.

This example of a file open which will never return is in line with what you want to do. It's taken from http://docs.python.org/library/signal.html#module-signal

But a warning. Because Python uses a Global Interpreter Lock to perform OS signal handling it is subject to some stability problems. These problems should be rare normally though.

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
貪欢 2024-12-18 20:28:54
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
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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文