Redis pub/sub на рельсах
Следуя Redis Pub/Sub
это прекрасно работает, и я могу публиковать сообщения в любом классе, используя
$redis.publish 'channel', { object: @object.id }
используя redis-cli > MONITOR
, я могу проверить правильность публикации этого запроса
[0 127.0.0.1:64192] "publish" "channel" "{:object=>\"5331d541f4eec77185000003\" }"
проблема начинается, когда я добавляю подписчик блок к этому каналу в другом классе (классе слушателя), как показано ниже
class OtherClass
$redis.subscribe('channel') do |payload|
p payload
end
end
в redis-cli > MONITOR
, также показывает, что слушатель правильно подписан
[0 127.0.0.1:52930] "subscribe" "channel"
проблема в том, что когда я добавляю класс слушателя-слушателя к тому же рельсовому приложению... он перестает работать, потому что OtherClass
слушает сервер redis и останавливает выполнение любого другого кода... он просто сидит там слушать.
так есть способ сделать шину обмена сообщениями с redis на одном и том же приложении rails... так что события публикуются из некоторых классов или служебных объектов, и есть слушатели для определенных каналов, чтобы воздействовать на получение событий в фона.
Я знаю, что я мог бы использовать sidekiq или любого другого фонового работника для выполнения этой работы... но через некоторое время фоновые работники стали беспорядочными и недостижимыми.
Ответы
Ответ 1
Реализация Redis#subscribe
цикл, который будет контролировать текущий поток, чтобы прослушивать события. Это означает, что процесс загрузки останавливается при отбрасывании подписки в контексте класса Rails так, как вы показали.
Вы можете попробовать обернуть вызов в потоке, но этот подход будет буквально создавать новую подписку каждый раз, когда этот класс загружается в новый процесс, например, консоль рельсов или несколько единорогов. Кроме того, вы должны быть осторожны в отношении общих состояний и других проблем с потоками. Вероятно, это не то, что вы хотите.
Лучше всего начать другой процесс, который загружает среду рельсов и подписывается на redis отдельно от процесса (ов), обслуживающего веб-запросы. Это может быть такая задача, как:
namespace :subscribe do
task :redis => :environment do
$redis.subscribe("bravo") do |on|
on.message do |channel, message|
Rails.logger.info("Broadcast on channel #{channel}: #{message}")
OtherClass.some_method # yada yada
end
end
end
end