Rake задачи и рельсы инициализаторы
Вроде новичок в Rails, так что, пожалуйста, справляйтесь со мной. То, что я делаю сейчас, это фоновая обработка некоторого кода на Ruby с использованием Resque. Чтобы запустить задачу Rescque rake, я использую (на heroku), у меня есть файл resque.rake с рекомендованным кодом, который нужно присоединить к магической (или странной) архитектуре потоков heroku:
require "resque/tasks"
require 'resque_scheduler/tasks'
task "resque:setup" => :environment do
ENV['QUEUE'] = '*'
end
desc "Alias for resque:work (To run workers on Heroku)"
task "jobs:work" => "resque:work"
Поскольку мне нужен доступ к коду Rails, я ссылаюсь на: среду. Если я поставлю хотя бы одного рабочего динамо в фоновом режиме на героку, мой Resque отлично справится, очистится, все будет хорошо. Пока я не попытаюсь автоматизировать вещи...
Поэтому я хотел развить код и автоматически заполнять очередь соответствующими задачами каждую минуту или около того. Сделав это (без использования cron, потому что heroku не подходит для cron), я объявляю инициализатор с именем task_scheduler.rb, который использует планировщик Rufus для запуска задач:
scheduler = Rufus::Scheduler.start_new
scheduler.in '5s' do
autoprocessor_method
end
scheduler.every '1m' do
autoprocessor_method
end
Некоторое время кажется, что все работает потрясающе... тогда процесс граблей просто перестает подниматься из очереди необъяснимым образом. Очередь становится все больше и больше. Даже если у меня работает несколько рабочих динамов, все они со временем устают и перестают обрабатывать очередь. Я не уверен, что я делаю неправильно, но я подозреваю, что ссылка на среду Rails в моей задаче rake вызывает повторный запуск кода task_scheduler.rb, что приводит к дублированию расписаний. Мне интересно, как решить эту проблему, если кто-то знает, и мне также любопытно, не является ли это причиной прекращения работы граблей.
Спасибо
2 ответа
Вы не должны загружать планировщик в инициализаторе, у вас должен быть процесс-демон, запускающий планировщик и заполняющий вашу очередь. Это было бы что-то вроде этого ("скрипт / планировщик"):
#!/usr/bin/env ruby
root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
Dir.chdir(root)
require 'rubygems'
gem 'daemons'
require 'daemons'
options = {
:dir_mode => :normal,
:dir => File.join(root, 'log'),
:log_output => true,
:backtrace => true,
:multiple => false
}
Daemons.run_proc("scheduler", options) do
Dir.chdir(root)
require(File.join(root, 'config', 'environment'))
scheduler = Rufus::Scheduler.start_new
scheduler.in '5s' do
autoprocessor_method
end
scheduler.every '1m' do
autoprocessor_method
end
end
И вы можете вызвать этот скрипт как обычный демон из вашего приложения:
script/scheduler start
Это позволит убедиться, что у вас есть только один процесс, отправляющий работу работникам resque, а не по одному на каждого монгрела, который вы запускаете.
Прежде всего, если вы не работаете на Heroku, я бы не рекомендовал такой подход. Я бы посмотрел на ответ Маурисио или подумал бы о том, чтобы использовать классическую работу cron или использовать Whenever для планирования работы cron.
Но если вам больно бегать на героку и пытаться сделать это, вот как я заставил это работать.
Я сохранил тот же оригинальный код Resque.rake, который вставил в исходный вопрос. Кроме того, я создал еще одну задачу rake, которую я прикрепил к заданию: процесс work rake, как в первом случае:
desc "Scheduler processor"
task :scheduler => :environment do
autoprocess_method
scheduler = Rufus::Scheduler.start_new
scheduler.every '1m' do
twitter_autoprocess
end
end
desc "Alias for resque:work (To run workers on Heroku)"
task "jobs:work" => "scheduler"
Пара заметок:
- Это будет несовершенным, если вы используете более одного рабочего динамо, потому что планировщик будет работать более чем в одном месте. Вы можете решить это, сохранив состояние где-нибудь, но это не так чисто, как хотелось бы.
Я нашел оригинальную причину, по которой процесс зависал. Это была эта строка кода:
scheduler.in '5s' do autoprocessor_method end
Я не уверен, почему, но когда я это убрал, он больше никогда не зависал.