From e55979407a152df3280a95f8725e6e492502e0f8 Mon Sep 17 00:00:00 2001 From: Mike Perham Date: Thu, 16 Aug 2012 16:43:01 -0700 Subject: [PATCH] Add extension to delay any arbitrary class method to Sidekiq. --- Changes.md | 7 ++++++ lib/sidekiq.rb | 1 + lib/sidekiq/extensions/active_record.rb | 7 ++++-- lib/sidekiq/extensions/class_methods.rb | 33 +++++++++++++++++++++++++ lib/sidekiq/rails.rb | 1 - test/test_extensions.rb | 9 +++++++ test/test_testing.rb | 11 ++++++--- 7 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 lib/sidekiq/extensions/class_methods.rb diff --git a/Changes.md b/Changes.md index 1cf32aa1..7f8355fd 100644 --- a/Changes.md +++ b/Changes.md @@ -1,6 +1,13 @@ HEAD ----------- +- Add extension to delay any arbitrary class method to Sidekiq. + Previously this was limited to ActiveRecord classes. + +```ruby +SomeClass.delay.class_method(1, 'mike', Date.today) +``` + - Sidekiq::Client now generates and returns a random, 128-bit Job ID 'jid' which can be used to track the processing of a Job, e.g. for calling back to a webhook when a job is finished. diff --git a/lib/sidekiq.rb b/lib/sidekiq.rb index c1f886f5..855f4e92 100644 --- a/lib/sidekiq.rb +++ b/lib/sidekiq.rb @@ -5,6 +5,7 @@ require 'sidekiq/worker' require 'sidekiq/redis_connection' require 'sidekiq/util' +require 'sidekiq/extensions/class_methods' require 'sidekiq/extensions/action_mailer' require 'sidekiq/extensions/active_record' require 'sidekiq/rails' if defined?(::Rails::Engine) diff --git a/lib/sidekiq/extensions/active_record.rb b/lib/sidekiq/extensions/active_record.rb index ee1859fa..4358d828 100644 --- a/lib/sidekiq/extensions/active_record.rb +++ b/lib/sidekiq/extensions/active_record.rb @@ -3,11 +3,14 @@ require 'sidekiq/extensions/generic_proxy' module Sidekiq module Extensions ## - # Adds a 'delay' method to ActiveRecord to offload arbitrary method + # Adds a 'delay' method to ActiveRecords to offload instance method # execution to Sidekiq. Examples: # - # User.delay.delete_inactive # User.recent_signups.each { |user| user.delay.mark_as_awesome } + # + # Please note, this is not recommended as this will serialize the entire + # object to Redis. Your Sidekiq jobs should pass IDs, not entire instances. + # This is here for backwards compatibility with Delayed::Job only. class DelayedModel include Sidekiq::Worker diff --git a/lib/sidekiq/extensions/class_methods.rb b/lib/sidekiq/extensions/class_methods.rb new file mode 100644 index 00000000..67dd04d7 --- /dev/null +++ b/lib/sidekiq/extensions/class_methods.rb @@ -0,0 +1,33 @@ +require 'sidekiq/extensions/generic_proxy' + +module Sidekiq + module Extensions + ## + # Adds a 'delay' method to all Classes to offload class method + # execution to Sidekiq. Examples: + # + # User.delay.delete_inactive + # Wikipedia.delay.download_changes_for(Date.today) + # + class DelayedClass + include Sidekiq::Worker + + def perform(yml) + (target, method_name, args) = YAML.load(yml) + target.send(method_name, *args) + end + end + + module Klass + def delay + Proxy.new(DelayedClass, self) + end + def delay_for(interval) + Proxy.new(DelayedClass, self, Time.now.to_f + interval.to_f) + end + end + + end +end + +Class.send(:include, Sidekiq::Extensions::Klass) diff --git a/lib/sidekiq/rails.rb b/lib/sidekiq/rails.rb index cf4e07c8..8d2563fd 100644 --- a/lib/sidekiq/rails.rb +++ b/lib/sidekiq/rails.rb @@ -2,7 +2,6 @@ module Sidekiq def self.hook_rails! return unless Sidekiq.options[:enable_rails_extensions] if defined?(ActiveRecord) - ActiveRecord::Base.extend(Sidekiq::Extensions::ActiveRecord) ActiveRecord::Base.send(:include, Sidekiq::Extensions::ActiveRecord) end diff --git a/test/test_extensions.rb b/test/test_extensions.rb index 0e455fb2..ff0206ff 100644 --- a/test/test_extensions.rb +++ b/test/test_extensions.rb @@ -54,6 +54,15 @@ class TestExtensions < MiniTest::Unit::TestCase UserMailer.delay_for(5.days).greetings(1, 2) assert_equal 1, Sidekiq.redis {|c| c.zcard('schedule') } end + + class SomeClass + def self.doit(arg) + end + end + + it 'allows delay of any ole class method' do + SomeClass.delay.doit(Date.today) + end end describe 'sidekiq rails extensions configuration' do diff --git a/test/test_testing.rb b/test/test_testing.rb index 0d1c2c49..7bab5241 100644 --- a/test/test_testing.rb +++ b/test/test_testing.rb @@ -76,10 +76,15 @@ class TestTesting < MiniTest::Unit::TestCase assert_equal 1, Sidekiq::Extensions::DelayedMailer.jobs.size end + class Something + def self.foo(x) + end + end + it 'stubs the delay call on models' do - assert_equal 0, Sidekiq::Extensions::DelayedModel.jobs.size - FooModel.delay.bar('hello!') - assert_equal 1, Sidekiq::Extensions::DelayedModel.jobs.size + assert_equal 0, Sidekiq::Extensions::DelayedClass.jobs.size + Something.delay.foo(Date.today) + assert_equal 1, Sidekiq::Extensions::DelayedClass.jobs.size end it 'stubs the enqueue call' do