Ruby on Rails: как запускать вещи в фоновом режиме? - PullRequest
29 голосов
/ 22 мая 2009

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

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

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

Ответы [ 7 ]

39 голосов
/ 22 мая 2009

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

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

7 голосов
/ 22 мая 2009

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

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

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

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

Действительно, процесс, который вы запускаете, должен быть «деамонизирован», см. Класс Daemonize .

6 голосов
/ 11 марта 2011

Я только что экспериментировал с драгоценным камнем '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

2 голосов
/ 22 мая 2009

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

1 голос
/ 29 марта 2010

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

1 голос
/ 22 мая 2009

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

0 голосов
/ 22 мая 2009

А как же:

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, имея возможность доступа к базе данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...