Оповещение после выполнения «тяжелой» фоновой задачи с помощью faye и PrivatePub

Допустим нам необоходимо после выполнения большой задачи в фоновом режиме сообщить об этом пользователю и совершить что-нибудь, например, показать ему какой-нибудь 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, выглядеть это будет примерно так
def clone
  Resque.enqueue(CloneProfileWorker, params[:id])
end

Теперь тяжелая задача будет добавляться в очередь всякий раз, когда мы пройдем по ссылке /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 в данном проекте)
= subscribe_to "/profile_cloning_#{ params[:id] }"

:javascript
  PrivatePub.subscribe('/profile_cloning_#{ params[:id] }', function(data, channel) {
    location.href = data.url;
  });

Первая строчка это метод из гема, который инициализует объект необходимыми параметрами из файла /config/private_pub.yml, а после мы «подписываемся на событие ‘/profile_cloning_#{ params[:id] }’, где в params[:id] содержится текущий id профиля. При наступлении данного события, мы перенаправляем пользователя на страницу ‘/profile/#{ new_id }/edit», полный урл мы получим после того, как resque job отработает.

app/workers/clone_profile_worker.rb
require 'resque'

class CloneProfileWorker
  @queue = :default

  def self.perform(profile_id)
    c = Profile.find profile_id
    new_profile = c.clone_self

    if new_profile.is_a? Profile
      PrivatePub.publish_to "/profile_cloning_#{ profile_id }", :url => "/profiles/#{ new_profile.id }/edit"
    end
  end 
end

В данном воркере нет ничего магического: сначала мы клонируем наш профиль и если все прошло успешно, то оповещаем нашего клиента и передаем туда 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 и мы перенаправляемся на редактирование уже склонированного профиля, если все отработало без ошибок. Если же возникли ошибки, то они отобразятся в терминале, если произойдет что-то невообразимое и непредвиденное, пишите в комментариях, я попробую помочь вам.
Теги:
Оповещение, faye, PrivatePub
Добавлено: 21 Сентября 2013 09:06:28 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...