donald
donald

Reputation: 23747

Using Heroku and Resque in Different Apps

My goal is to have a main app adding jobs to a Resque queue on Heroku. However, I want the workers to be run in different apps.

Can I enqueue a job in an app to be performed by other app(worker)? Is there any tutorial explaining how to do it?

Thanks

Upvotes: 0

Views: 661

Answers (2)

kain
kain

Reputation: 5570

This takes care of the environment, usually on Heroku you run with RedisToGo:

# config/initializers/resque.rb
uri = if ENV['REDISTOGO_URL']
  URI.parse(ENV['REDISTOGO_URL'])
else
  Settings.redis.uri
end

Resque.redis = Redis.new(host: uri.host, port: uri.port, password: uri.password)

Remember that if you are using the Cedar stack you must write in your Procfile:

worker: bundle exec rake environment resque:work

As a added bonus, in your Gemfile gem 'heroku' and put this in lib/heroku_resque_auto_scale.rb and require the file from your resque initializer:

require 'heroku'

module HerokuResqueAutoScale
  module Scaler
    class << self
      @@heroku = Heroku::Client.new(ENV['HEROKU_USER'], ENV['HEROKU_PASS'])

      def workers
        @@heroku.info(ENV['HEROKU_APP'])[:workers].to_i
      end

      def workers=(qty)
        @@heroku.set_workers(ENV['HEROKU_APP'], qty)
      end

      def job_count
        Resque.info[:pending].to_i
      end
    end
  end

  def after_perform_scale_down(*args)
    # Nothing fancy, just shut everything down if we have no jobs
    Scaler.workers = 0 if Scaler.job_count.zero?
  end

  def after_enqueue_scale_up(*args)
    [
      {
        :workers => 1, # This many workers
        :job_count => 1 # For this many jobs or more, until the next level
      },
      {
        :workers => 2,
        :job_count => 15
      },
      {
        :workers => 3,
        :job_count => 25
      },
      {
        :workers => 4,
        :job_count => 40
      },
      {
        :workers => 5,
        :job_count => 60
      }
    ].reverse_each do |scale_info|
      # Run backwards so it gets set to the highest value first
      # Otherwise if there were 70 jobs, it would get set to 1, then 2, then 3, etc

      # If we have a job count greater than or equal to the job limit for this scale info
      if Scaler.job_count >= scale_info[:job_count]
        # Set the number of workers unless they are already set to a level we want. Don't scale down here!
        if Scaler.workers <= scale_info[:workers]
          Scaler.workers = scale_info[:workers]
        end
        break # We've set or ensured that the worker count is high enough
      end
    end
  end
end

Credit: https://gist.github.com/812430

Upvotes: 0

Yuri Gadow
Yuri Gadow

Reputation: 1813

Resque is going to use whatever Redis instance you point it at. In Heroku, that's probably going to be an instance from the separate service Redis To Go. You just need to write your Resque setup code to point to the common Redis instance.

From http://blog.redistogo.com/2010/07/26/resque-with-redis-to-go/

uri = URI.parse(ENV["REDISTOGO_URL"])
Resque.redis = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)

This will initialize Resque with the environment variable, which you can set in each deployed Heroku app using heroku config:add REDISTOGO=etc.

Upvotes: 1

Related Questions