График одноразового задания Resque на героку при запуске приложения в Rails

Я использую Resque и Resque Schedule для запуска задания, которое должно быть запущено сразу при запуске приложения. Другие запланированные задания загружаются каждые 30 секунд.

Это код для моего config/initializers/redis.rb

require 'rake'
require 'resque'
require 'resque/server'
require 'resque_scheduler/tasks'
# This will make the tabs show up.
require 'resque_scheduler'
require 'resque_scheduler/server'

uri = URI.parse(ENV["REDISTOGO_URL"])
REDIS = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
Resque.redis = REDIS
Dir["#{Rails.root}/app/workers/*.rb"].each { |file| require file }
Resque.enqueue(AllMessageRetriever)
Resque.schedule = YAML.load_file(Rails.root.join('config', 'schedule.yml'))

Когда приложение запускается, AllMessageRetriever запускается 2-3 раза, а не только один раз. Инициализаторы вызывались более одного раза? Это происходит как на Heroku, так и в моей местной среде?

Можно ли установить отложенное задание в Resque-Scheduler, которое будет выполняться только один раз и сразу во время выполнения?

Код для AllMessageRetriever. По сути, он проходит по таблице и вызывает внешний API для получения данных, а затем обновляет их в таблице. Вся эта задача происходит 2-3 раза, если я добавляю метод enqueue в файл инициализатора

 require 'socialcast'
module AllMessageRetriever
    @queue = :message_queue
    def self.perform()
        Watchedgroup.all.each do |group|    
            puts "Running group #{group.name}"
            continueLoading=true
            page=1
            per_page=500
            while(continueLoading == true)
                User.first.refresh_token_if_expired
                token = User.first.token
                puts "ContinueLoading: #{continueLoading}"
                @test = Socialcast.get_all_messages(group.name,token,page,per_page)

                messagesArray =  ActiveSupport::JSON.decode(@test)["messages"]
                puts "Message Count: #{messagesArray.count}"
                if messagesArray.count == 0
                    puts 'count is zero now'
                    continueLoading = false
                else
                    messagesArray.each do |message|
                        if not Message.exists?(message["id"])   
                            Message.create_with_socialcast(message, group.id)
                        else
                            Message.update_with_socialcast(message)
                        end
                    end
                end
                page += 1
            end
            Resqueaudit.create({:watchedgroup_id => group.id,:timecompleted => DateTime.now})
        end
        # Do anything here, like access models, etc
        puts "Doing my job"
    end
end

1 ответ

Грабли

Во-первых, почему вы пытаетесь поставить в очередь на init?

Вы были бы намного лучше делегировать на грабли задачу, которая вызывается из инициализатора.

Это удалит зависимость от процесса инициализации, что должно многое прояснить. Я бы не стал помещать это в сам инициализатор, так как это будет лучше обрабатываться в другом месте ( модульность)


проблема

Я думаю, что эта строка вызывает проблему:

Resque.enqueue(AllMessageRetriever)

Не видя содержимого AllMessageRetrieverЯ бы предположил что ты AllMessageRetriever (модуль / класс?) будет возвращать результаты 2/3 раза, в результате чего Resque добавит (2 / 3 раза) набор данных в очередь

Может быть неправильно, но это имеет смысл, и означает, что ваша проблема не с Resque / Initializers, но твой AllMessageRetriever учебный класс

Была бы большая помощь, если бы вы показали это!

Другие вопросы по тегам