Ruby на рельсах:Как запустить что-то в фоновом режиме?

StackOverflow https://stackoverflow.com/questions/897605

Вопрос

Когда создается новый ресурс, и ему необходимо выполнить некоторые длительная обработка прежде чем ресурс будет готов, как мне отправить эту обработку на задний план где это не выдержит текущий запрос или другой трафик к моему веб-приложению?

в моей модели:

class User < ActiveRecord::Base
 after_save :background_check

 protected
 def background_check
  # check through a list of 10000000000001 mil different
  # databases that takes approx one hour :)
  if( check_for_record_in_www( self.username ) )
    # code that is run after the 1 hour process is finished.
    user.update_attribute( :has_record )
  end
 end
end
Это было полезно?

Решение

Вам обязательно стоит посмотреть следующие железнодорожные трансляции:

Они объясняют, как запускать фоновые процессы в Rails всеми возможными способами (с очередью или без нее ...)

Другие советы

Запустите отдельный процесс, который, вероятно, проще всего выполнить с помощью system, добавляя 'nohup' и '&' в конце команды, которую вы передаете.(Убедитесь, что команда представляет собой только один строковый аргумент, а не список аргументов.)

Есть несколько причин, по которым вы хотите сделать это таким образом, а не, скажем, пытаться использовать потоки:

  1. Потоки Ruby могут быть немного сложными, когда дело доходит до выполнения ввода-вывода;вы должны позаботиться о том, чтобы некоторые действия, которые вы делаете, не привели к блокировке всего процесса.

  2. Если вы запускаете программу с другим именем, ее легко идентифицировать по 'ps', так что вы случайно не подумаете, что это сошедший с ума сервер FastCGI или что-то в этом роде, и не убьете ее.

Действительно, процесс, который вы запускаете, должен быть "деамонизирован", см. Демонизировать класс для помощи.

Я только что экспериментировал с драгоценным камнем 'delayed_job', потому что он работает с хостинговой платформой Heroku, и его было до смешного просто настроить!!

Добавить драгоценный камень в Gemfile, bundle install, rails g delayed_job, rake db:migrate Затем запустите обработчик очереди с помощью;

RAILS_ENV=production script/delayed_job start

Где у вас есть вызов метода, который является вашим длительным процессом, т.е.

company.send_mail_to_all_users

вы меняете его на;

company.delay.send_mail_to_all_users

Ознакомьтесь с полными документами на github: https://github.com/collectiveidea/delayed_job

в идеале вы хотите использовать существующий сервер фоновых заданий, а не писать свой собственный.обычно они позволяют вам отправить задание и присвоить ему уникальный ключ;затем вы можете использовать ключ для периодического запроса к серверу заданий статуса вашего задания, не блокируя свое веб-приложение. вот хороший обзор из существующих различных вариантов.

Мне нравится использовать backgroundrb, приятно, что он позволяет вам общаться с ним во время длительных процессов.Таким образом, вы можете получать обновления статуса в своем приложении rails

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

О чем:

def background_check
   exec("script/runner check_for_record_in_www.rb #{self.username}") if fork == nil
end

Программа "check_for_record_in_www.rb" затем будет запущен в другом процессе и будет иметь доступ к ActiveRecord, имея возможность доступа к базе данных.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top