Rake задачи и рельсы инициализаторы - PullRequest
2 голосов
/ 24 июля 2011

Вроде новичок в 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, я ссылаюсь на: среду.Если я поставлю хотя бы 1 рабочий динам в фоновом режиме на героку, мой 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 ]

5 голосов
/ 24 июля 2011

Вы не должны загружать планировщик в инициализаторе, у вас должен быть процесс-демон, запускающий планировщик и заполняющий вашу очередь. Это было бы что-то вроде этого («скрипт / планировщик»):

#!/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

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

3 голосов
/ 24 июля 2011

Прежде всего, если вы не работаете на 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"

Пара заметок:

  1. Это будет несовершенным, если вы используете более одного рабочего dyno, потому что планировщик будет работать более чем в одном месте. Вы можете решить это, сохранив состояние где-нибудь, но оно не так чисто, как хотелось бы.
  2. Я нашел первоначальную причину зависания процесса. Это была эта строка кода:

    scheduler.in '5s' do
     autoprocessor_method
    end
    

    Я не уверен, почему, но когда я это убрал, он больше никогда не зависал.

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