Ruby on Rails: как работать в фоновом режиме?
Когда создается новый ресурс и ему нужно сделать некоторую длительную обработку до того, как ресурс будет готов, как отправить эту обработку в фоновом режиме, где она выиграла Не задерживайте текущий запрос или другой трафик на моем веб-приложении?
в моей модели:
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
Ответы
Ответ 1
Вы должны обязательно проверить следующие Railscasts:
Они объясняют, как запускать фоновые процессы в Rails всеми возможными способами (с или без очереди...)
Ответ 2
Начните отдельный процесс, который, вероятно, легче всего сделать с помощью system
, добавив "nohup" и добавив "&" до конца команды, которую вы передаете. (Убедитесь, что команда представляет собой только один строковый аргумент, а не список аргументов.)
Есть несколько причин, по которым вы хотите сделать это таким образом, а не, скажем, пытаться использовать потоки:
-
Рубиновые потоки могут быть немного сложными, когда дело доходит до ввода-вывода; вы должны позаботиться о том, чтобы некоторые вещи, которые вы делаете, не приводили к блокированию всего процесса.
-
Если вы запускаете программу с другим именем, она легко идентифицируется в "ps", поэтому вы не ошибаетесь, полагая, что FastCGI back-end удалился или что-то еще, и убейте его.
Действительно, процесс, который вы начинаете, должен быть "деамонизирован", обратитесь за помощью к Daemonize.
Ответ 3
Я только что экспериментировал с камнем "delayed_job", потому что он работает с хоринговой платформой Heroku, и это было смешно легко настроить!
Добавьте gem в Gemfile, bundle install
, rails g delayed_job
, rake db:migrate
Затем запустите обработчик очереди;
RAILS_ENV=production script/delayed_job start
Если у вас есть вызов метода, который является вашим длительным процессом, i.e
company.send_mail_to_all_users
вы меняете его на;
company.delay.send_mail_to_all_users
Проверьте полные документы в github: https://github.com/collectiveidea/delayed_job
Ответ 4
вы в идеале хотите использовать существующий фоновый сервер заданий, а не писать свои собственные. они обычно позволят вам отправить задание и дать ему уникальный ключ; вы можете затем использовать ключ для периодического запроса сервера заданий для статуса вашей работы без блокировки вашего веб-приложения. вот хороший обзор различных вариантов.
Ответ 5
Мне нравится использовать backgroundrb, его приятный способ позволяет вам общаться с ним во время длительных процессов. Таким образом, вы можете иметь обновления статуса в своем приложении rails
Ответ 6
Я думаю, spawn - отличный способ развернуть ваш процесс, сделать некоторую обработку в фоновом режиме и показать пользователю только некоторое подтверждение, что эта обработка была начата.
Ответ 7
Как насчет:
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, имея возможность доступа к базе данных.