Тайм-аут Heroku при отправке писем

Я нахожусь на Heroku с пользовательским доменом, и у меня есть дополнение Redis. Мне нужна помощь, чтобы понять, как создать фоновый рабочий для уведомлений по электронной почте. Пользователи могут отправлять сообщения "Входящие" друг другу, и я хотел бы отправить уведомление по электронной почте пользователю для каждого полученного нового сообщения. У меня есть уведомления, работающие в разработке, но мне нехорошо создавать фоновые задания, которые требуются для Heroku, иначе сервер будет тайм-аут.

Контроллер сообщений:

  def create
    @recipient = User.find(params[:user])
    current_user.send_message(@recipient, params[:body], params[:subject])
    flash[:notice] = "Message has been sent!"
    if request.xhr?
        render :json => {:notice => flash[:notice]}
    else
        redirect_to :conversations
    end
  end

Модель пользователя:

def mailboxer_email(object)
    if self.no_email
      email
    else
        nil
    end
end

Mailboxer.rb:

Mailboxer.setup do |config|

  #Configures if you applications uses or no the email sending for Notifications and Messages
  config.uses_emails = false

  #Configures the default from for the email sent for Messages and Notifications of Mailboxer
  config.default_from = "[email protected]"

  #Configures the methods needed by mailboxer
  config.email_method = :mailboxer_email
  config.name_method = :name

  #Configures if you use or not a search engine and wich one are you using
  #Supported enignes: [:solr,:sphinx]
  config.search_enabled = false
  config.search_engine = :sphinx
end

Ответ 1

Sidekiq - это определенно способ пойти с Heroku. Я не думаю, что почтовый ящик поддерживает конфигурацию фона из коробки. К счастью, это все еще очень легко с процессом очереди sidekiq.

  • Добавьте gem 'sidekiq' в свой gemfile и запустите bundle.
  • Создайте рабочий файл app/workers/message_worker.rb.
class MessageWorker
  include Sidekiq::Worker

  def perform(sender_id, recipient_id, body, subject)
    sender = User.find(sender_id)
    recipient = User.find(recipient_id)
    sender.send_message(recipient, body, subject) 
  end
end
  1. Обновите свой контроллер до очереди до рабочего.

Удалить: current_user.send_message(@recipient, params[:body], params[:subject])

Добавить: MessageWorker.perform_async(current_user.id, @recipient.id, params[:body], params[:subject])

Примечание. Вы не должны пропускать рабочие объекты ActiveRecord. Поэтому я устанавливаю этот метод для передачи идентификаторов пользователей и просматриваю их в рабочем perform методе, а не всего объекта.

  1. Наконец, перезагрузите сервер и запустите bundle exec sidekiq. Теперь ваше приложение должно отправлять фон электронной почты.

  2. При развертывании вам понадобится отдельный динамик для рабочего, который должен выглядеть следующим образом: worker: bundle exec sidekiq. Вам также понадобится дополнение Heroku redis.

Ответ 2

Звучит как время ожидания запроса H21:

HTTP-запрос занял более 30 секунд.

Чтобы создать фоновый рабочий для этого в RoR, вы должны захватить Resque, библиотеку очередного фона для резервного копирования для RoR. Вот демонстрация. Еще одна демонстрация. И еще одно демо.

Чтобы узнать больше об использовании Resque в Heroku, вы также можете прочитать статью о героике здесь. Или этот урок (он старый, хотя). Еще один отличный учебник.

Существует также драгоценный камень resque_mailer, который ускорит процесс для вас.

gem install resque_mailer #or add it to your Gemfile & use bundler 

Это довольно просто. Вот фрагмент из рабочей демонстрации автора:

class Notifier < ActionMailer::Base
  include Resque::Mailer

  default :from => "[email protected]"

  def test(data={})
    data.symbolize_keys!

    Rails.logger.info "sending test mail"
    Rails.logger.info "params: #{data.keys.join(',')}"
    Rails.logger.info ""

    @subject = data[:subject] || "Testing mail"
    mail(:to => "[email protected]",
         :subject => @subject)
  end
end

Выполнение Notifier.test.deliver будет доставлять почту.

Вы также можете использовать службы доставки почты, такие как SES.

Ответ 3

Sidekiq - это вариант, который вы могли бы рассмотреть. Чтобы заставить его работать, вы можете добавить что-то вроде RedisToGo, а затем настроить инициализатор для Redis. Затем на Heroku вы можете добавить что-то вроде worker: bundle exec sidekiq ... в свой файл Procfile.

https://github.com/mperham/sidekiq/wiki/Getting-Started

Он также имеет панель мониторинга для мониторинга.

https://github.com/mperham/sidekiq/wiki/Monitoring