Search code examples
ruby-on-railsherokusidekiq

Rails Sidekiq delay task


I'd like to do a for loop with a 5 minute delay between each in a sidekiq worker. But when I try to deploy it to Heroku it crashes my app

class DelayedCallWorker
    include Sidekiq::Worker
    include Sidekiq::Status::Worker

    def perform(survey_id)
        @twilio_sid = ENV['TWILIO_ACCOUNT_SID']
        @twilio_token = ENV['TWILIO_AUTH_TOKEN']
        @twilio_number = ENV['TWILIO_NUMBER']

        @survey = Survey.find(survey_id)
        phone_number = @survey.call_center_number

        @client = Twilio::REST::Client.new @twilio_sid, @twilio_token

        @leads = @survey.leads.where(call_needed: true)
        @leads.each do |lead|
            @call = @client.account.calls.create(
              :from => @twilio_number,
              :to => lead.phone, 
              :url => "http://example.com/connect?number=#{phone_number}"
              )
            sleep, 180
        end
    end
end

if I comment out the sleep, 180 everything works fine, but then there's no delay.

I also tried a variation where I looped through the leads in a controller and created the worker with a longer delay per worker using perform_in(5.minutes, survey_id) but that likewise crashed heroku.

Does anyone know what the best way is to do a delay from within a look within a sidekiq worker?


Solution

  • This is definitely not the kind of task you want to perform in Sidekiq. Or at least, not designed as you did.

    Sidekiq is a background worker. If you keep one worker running, it will saturate the queue and not free the space for other workers.

    You have two alternatives:

    • Use a cron-like process that is executed every 5 minutes, for example using Clockwork
    • Run a Sidekiq task, and the end of each task queue another job to be executed 5 minutes in the future (using the perform_at Sidekiq feature)