knotito
knotito

Reputation: 1392

conflict delayed_job / sidekiq

I have an app with both sidekiq and delayed job gems installed. When I trigger handle_asynchronously in active record models it appear to be handled by sidekiq while I would like to trigger delayed_job.

Is there a way to desactivate sidekiq for a specific model?

Upvotes: 2

Views: 1180

Answers (2)

lulalala
lulalala

Reputation: 17981

UPDATE:

Sidekiq now provides ways to either disable its delay module completely or alias it as sidekiq_delay. Please check this to see how to do it. https://github.com/mperham/sidekiq/wiki/Delayed-Extensions#disabling-extensions


For older version of sidekiq:

I use this monkey patch to make it so that calling .sidekiq_delay() goes to sidekiq and .delay() is goes to DelayedJob. According the answer by Viren, I think this may also solve your problem.

The patch is less complex (just a bunch of aliases), and gives you the power to consciously decide which delay you are actually calling.

Upvotes: 3

Viren
Viren

Reputation: 5962

As I mention in the comment In order to get it working you have to redefine/basically monkey patch the handle_asynchronously method something like this

Anywhere you like (but make sure it loaded )

in your config/initializers/patch.rb the code look like this

module Patch
  def handle_asynchronously(method, opts = {})
    aliased_method, punctuation = method.to_s.sub(/([?!=])$/, ''), $1
    with_method, without_method = "#{aliased_method}_with_delay#{punctuation}", "#{aliased_method}_without_delay#{punctuation}"
    define_method(with_method) do |*args|
      curr_opts = opts.clone
      curr_opts.each_key do |key|
        if (val = curr_opts[key]).is_a?(Proc)
          curr_opts[key] = if val.arity == 1
            val.call(self)
          else
            val.call
          end
        end
      end
      ## Replace this with other syntax
      # delay(curr_opts).__send__(without_method, *args)
      __delay__(curr_opts).__send__(without_method, *args)
    end
    alias_method_chain method, :delay
  end
end

Module.send(:include,Patch)

And I believe rest all will follow then they way it should :)

Reason:

Delayed::Job include delay method on Object and Sidekiq include it delay method over ActiveRecord Hence when the class try to invoke delay it look up it ancestors class (including the Eigen Class) and it find the method define or included in ActiveRecord::Base class (which is sidekiq delay)

why does __delay__ work because alias define the copy of the existing method which is delay method of DelayedJob , hence when you invoke the __delay__ method it invoke delay method define DelayedJob include to Object

Note:

Although the solution is bit patch but the it works . Keeping in mind that every direct .delay methid invocation is invoking delay method of the SideKiq and not DelayedJob to invoke the DelayedJob delay method you always has call it this way __delay__

Suggestion :

Monkey Patching is just a bad practice on my personal note I would rather not use 2 entirely different background processing library for a single application to achieve the same task. If the task is process thing in background why cant it be done with a single library either delayed_job or sidekiq (why it is that you required both of them )

So the point and to simply thing make your background processing an ease with respect to future I sincerely advice you take any one of the two library for background processing and I feel that would the valid answer for your question instead of monkey patching an doing other crazy stuff

Hope this help

Upvotes: 2

Related Questions