2

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?

knotito
  • 1,382
  • 1
  • 12
  • 18
  • note that delayed_job is triggered on non activerecord inherited classes – knotito Sep 04 '13 at 18:12
  • what is the `self` getting stored in it (db) does it persist because if not delayed_job on work if the record persist – Viren Sep 05 '13 at 06:50
  • apparently it works as it, it saves the object and his state even with relationships – knotito Sep 10 '13 at 16:56
  • My friend your a victim of ruby meta-programming I believe check [this](https://github.com/mperham/sidekiq/blob/master/lib/sidekiq/extensions/active_record.rb#L24-L26) and [this](https://github.com/collectiveidea/delayed_job/blob/master/lib/delayed/message_sending.rb#L17-L19) The only resort I believe is that you perhaps use `__delay__` method instead of `delay` because that what `handle_asynchronously` do internally it invoke `delay` method which in your case is invoking the `SideKiq` because thanks to of ghost class or eigen class :) – Viren Sep 10 '13 at 17:19
  • As an approach I would suggest is to overwrite [this](https://github.com/collectiveidea/delayed_job/blob/master/lib/delayed/message_sending.rb#L33-L51) piece of code inside your `lib` or anywhere you like :) , and replace this [line](https://github.com/collectiveidea/delayed_job/blob/master/lib/delayed/message_sending.rb#L47) with something like this `__delay__(curr_opts).__send__(without_method, *args)` and see if it work – Viren Sep 10 '13 at 17:37

2 Answers2

3

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.

Community
  • 1
  • 1
lulalala
  • 17,572
  • 15
  • 110
  • 169
2

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

Community
  • 1
  • 1
Viren
  • 5,812
  • 6
  • 45
  • 98