简体   繁体   中英

Schedule a one-time Resque job on heroku on application start in Rails

I am using Resque and Resque Schedule to start a job that has to be run immediately on the application start. Other scheduled jobs are loaded every 30 seconds.

This is the code for my 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'))

When the application is started up, the AllMessageRetriever gets run 2-3 times rather than only once. Do the initializers get called more than once? This happens both on Heroku and my local environment?

Is it possible to set a delayed job in Resque-Scheduler which will only get executed once and immediately on runtime?

The code for AllMessageRetriever. Basically it loops over a table and calls an external API to get data and then updates it to the table. This entire task happens 2-3 times if I add the enqueue method in initializer file

 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

Rake

Firstly, why are you trying to queue on init?

You'd be much better delegating to a rake task which is called from an initializer.

This will remove dependency on the initialize process, which should clear things up a lot. I wouldn't put this in an initializer itself, as it will be better handled elsewhere ( modularity )


Problem

I think this line is causing the issue:

Resque.enqueue(AllMessageRetriever)

Without seeing the contents of AllMessageRetriever , I'd surmise that you're AllMessageRetriever (module / class?) will be returning the results 2/3 times, causing Resque to add the (2 / 3 times) data-set to the queue

Could be wrong, but it would make sense, and mean your issue is not with Resque / Initializers , but your AllMessageRetriever class

Would be a big help if you showed it!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM