Допустим нам необоходимо после выполнения большой задачи в фоновом режиме сообщить об этом пользователю и совершить что-нибудь, например, показать ему какой-нибудь popup. Для этого по-старинке, можно с интервалом, скажем в 1 секунду опрашивать сервер и смотреть не завершилась ли наша задача, но в пору HTML5 делать это, по крайней мере, не престижно. Будем использовать для этих целей инструмент по обмену сообщениями между сервером и клиентом Faye.
Инструменты
Нам понадобится Rails приложение, к которому мы и будем привязывать всю эту функциональность. Также будем использовать Resque для выполнений фоновых задач – инструмент, зарекомендовавший себя, как надежный и стабильный помощник, спасающий всегда, когда нужно выполнить тяжелые задачи в фоне. Вместе с faye воспользуемся оберткой для него от Ryan Bates Private Pub, который мне очень облегчил жизнь, надеюсь, и облегчит вам.
Реализация
Для начала установим redis и обновим наш Gemfile, дополнив его необходимыми гемами resque, faye, private_pub, thin.
Я буду рассказать все на примере Mac OS, установка подобного инструментарий, скажем, на Ubuntu, не должна вызвать вопросов, потому что инструменты очень распространенные.
Устанавливал redis я с помощью всем известного пакетного менеджера Homebrew, напечатав в терминале всего одну команду brew install redis
Допустим у нас имеется какой-нибудь тяжелый объект с несколькими картинками, которые лежат в Amazon S3 и, чтобы создать копию этого объекта нам понадобится скачать все эти картинки, чтобы вновь их туда загрузить, привязав в новому объекту. Не спрашивайте почему так сложно, так работает CarrierWave или я просто не нашел лучшего решения.
Если у нас раньше был метод в контролле, к примеру, clone, которй вызывал метод из модели, делающий всю грязную работу, то сейчас нам нужно лишь добавить новую задачу для resque, выглядеть это будет примерно так
1 2 3 |
|
Теперь тяжелая задача будет добавляться в очередь всякий раз, когда мы пройдем по ссылке /profiles/#{ id }/clone.
Давайте поставим и настроим PrivatePub, который будет со стороны клиента подписываться на определенные события, и со стороны сервера, после наступления определенного события (в нашем примере это, когда resque job отработает) делать нужные нам вещи.
Для этого в консоли нужно запустить rails g private_pub:install
и добавить в файл app/assets/javascripts/application.js[.cofeee] строчку
#= require private_pub
, если вы используете cofeeScript или же //= require private_pub
, если js
и дальше во вьюхе /profile/clone.html.haml (я использую haml в данном проекте)
1 2 3 4 5 6 |
|
Первая строчка это метод из гема, который инициализует объект необходимыми параметрами из файла /config/private_pub.yml, а после мы “подписываемся на событие ‘/profile_cloning_#{ params[:id] }’, где в params[:id] содержится текущий id профиля. При наступлении данного события, мы перенаправляем пользователя на страницу ‘/profile/#{ new_id }/edit”, полный урл мы получим после того, как resque job отработает.
app/workers/clone_profile_worker.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
В данном воркере нет ничего магического: сначала мы клонируем наш профиль и если все прошло успешно, то оповещаем нашего клиента и передаем туда url, на который он перенаправится.
Проверяем работоспособность
Запускаем в разных окнах терминала:
rails s
redis-server /usr/local/etc/redis.conf
(у меня MacOs, на других ОС должно быть нечто подобное)VERBOSE=1 rake resque:work QUEUE=*
(запускаем все очереди, устанвливаем verbose=1 для того, чтобы видеть что происходит внутри resque)rackup private_pub.ru -s thin -E production
(сервер для PrivatePub и Faye)
Проходим по ссылке наподобие /profiles/73/clone и смотрим в терминале как отрабатывает наш resque job и мы перенаправляемся на редактирование уже склонированного профиля, если все отработало без ошибок. Если же возникли ошибки, то они отобразятся в терминале, если произойдет что-то невообразимое и непредвиденное, пишите в комментариях, я попробую помочь вам.