Ruby на рельсах:Как запустить что-то в фоновом режиме?
-
23-08-2019 - |
Вопрос
Когда создается новый ресурс, и ему необходимо выполнить некоторые длительная обработка прежде чем ресурс будет готов, как мне отправить эту обработку на задний план где это не выдержит текущий запрос или другой трафик к моему веб-приложению?
в моей модели:
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
Решение
Вам обязательно стоит посмотреть следующие железнодорожные трансляции:
- http://railscasts.com/episodes/127-rake-in-background
- http://railscasts.com/episodes/128-starling-and-workling
- http://railscasts.com/episodes/129-custom-daemon
- http://railscasts.com/episodes/366-sidekiq
Они объясняют, как запускать фоновые процессы в Rails всеми возможными способами (с очередью или без нее ...)
Другие советы
Запустите отдельный процесс, который, вероятно, проще всего выполнить с помощью system
, добавляя 'nohup' и '&' в конце команды, которую вы передаете.(Убедитесь, что команда представляет собой только один строковый аргумент, а не список аргументов.)
Есть несколько причин, по которым вы хотите сделать это таким образом, а не, скажем, пытаться использовать потоки:
Потоки Ruby могут быть немного сложными, когда дело доходит до выполнения ввода-вывода;вы должны позаботиться о том, чтобы некоторые действия, которые вы делаете, не привели к блокировке всего процесса.
Если вы запускаете программу с другим именем, ее легко идентифицировать по '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, имея возможность доступа к базе данных.