Ruby и Redis: установите тайм-аут для подписок
Я хотел бы подождать сообщения в канале Redis не более 2 секунд, затем я хочу, чтобы срок действия подписки истек / истекло, и я прекратил блокировать мой код.
redis = Redis.new
redis.subscribe(channel) do |on|
on.message do |channel, message|
# ...
end
end
# This line is never reached if no message is sent to channel :(
Я использую https://github.com/redis/redis-rb. Я искал в источнике, но не нашел вариант тайм-аута для подписок.
3 ответа
Решение
Вы можете добавить блок тайм-аута следующим образом:
require 'timeout'
begin
Timeout.timeout(2) do
redis.subscribe(channel) do |on|
on.message do |channel, message|
# ...
end
end
end
rescue Timeout::Error
# handle error: show user a message?
end
Теперь вы можете подписаться с таймаутом за один шаг:
redis.subscribe_with_timeout(5, channel) do |on|
on.message do |channel, message|
# ...
end
end
В реализации redis-rb pubsub нет опции тайм-аута. Однако это может быть довольно легко с помощью инструментов, которые у вас уже есть:
require 'redis'
channel = 'test'
timeout_channel = 'test_timeout'
timeout = 3
redis = Redis.new
redis.subscribe(channel, time_channel) do |on|
timeout_at = Time.now + timeout
on.message do |channel, message|
redis.unsubscribe if channel == timeout_channel && Time.now >= timeout_at
end
# not the best way to do it, but we need something publishing to timeout_channel
Thread.new {
sleep timeout
Redis.new.publish timeout_channel, 'ping'
}
end
#This line is never reached if no message is sent to channel :(
puts "here we are!"
Основная идея здесь состоит в том, чтобы время от времени публиковать сообщения на отдельном канале. Клиент подписки также подписывается на этот специальный канал и проверяет текущее время, чтобы решить, истек ли он уже.