Permalink
Browse files

Refactor PerformableMethod so it's easier to extend with multiple bac…

…kends
  • Loading branch information...
1 parent c9e9775 commit 35a28085cb54f82562a7b869c3cdd85fae7b4b44 @bkeepers bkeepers committed Jan 19, 2010
@@ -1,5 +1,15 @@
require 'timeout'
+class ActiveRecord::Base
+ def self.load_for_delayed_job(id)
+ find(id)
+ end
+
+ def dump_for_delayed_job
+ "#{self.class};#{id}"
+ end
+end
+
module Delayed
module Backend
module ActiveRecord
@@ -1,5 +1,21 @@
require 'mongo_mapper'
+module MongoMapper
+ module Document
+ module ClassMethods
+ def load_for_delayed_job(id)
+ find!(id)
+ end
+ end
+
+ module InstanceMethods
+ def dump_for_delayed_job
+ "#{self.class};#{id}"
+ end
+ end
+ end
+end
+
module Delayed
module Backend
module Mongo
@@ -1,8 +1,16 @@
+class Class
+ def load_for_delayed_job(arg)
+ self
+ end
+
+ def dump_for_delayed_job
+ name
+ end
+end
+
module Delayed
class PerformableMethod < Struct.new(:object, :method, :args)
- CLASS_STRING_FORMAT = /^CLASS\:([A-Z][\w\:]+)$/
- AR_STRING_FORMAT = /^AR\:([A-Z][\w\:]+)\:(\d+)$/
- MM_STRING_FORMAT = /^MM\:([A-Z][\w\:]+)\:(\w+)$/
+ STRING_FORMAT = /^LOAD\;([A-Z][\w\:]+)(?:\;(\w+))?$/
class LoadError < StandardError
end
@@ -15,42 +23,39 @@ def initialize(object, method, args)
self.method = method.to_sym
end
- def display_name
- case self.object
- when CLASS_STRING_FORMAT then "#{$1}.#{method}"
- when AR_STRING_FORMAT then "#{$1}##{method}"
- when MM_STRING_FORMAT then "#{$1}##{method}"
- else "Unknown##{method}"
- end
- end
-
+ def display_name
+ if STRING_FORMAT === object
+ "#{$1}#{$2 ? '#' : '.'}#{method}"
+ else
+ "#{object.class}##{method}"
+ end
+ end
+
def perform
load(object).send(method, *args.map{|a| load(a)})
rescue PerformableMethod::LoadError
- # We cannot do anything about objects which were deleted in the meantime
+ # We cannot do anything about objects that can't be loaded
true
end
private
def load(obj)
- case obj
- when CLASS_STRING_FORMAT then $1.constantize
- when AR_STRING_FORMAT then $1.constantize.find($2)
- when MM_STRING_FORMAT then $1.constantize.find!($2)
- else obj
+ if STRING_FORMAT === obj
+ $1.constantize.load_for_delayed_job($2)
+ else
+ obj
end
rescue => e
Delayed::Worker.logger.warn "Could not load object for job: #{e.message}"
raise PerformableMethod::LoadError
end
def dump(obj)
- case obj
- when Class then "CLASS:#{obj.name}"
- when ActiveRecord::Base then "AR:#{obj.class}:#{obj.id}"
- when MongoMapper::Document then "MM:#{obj.class}:#{obj.id}"
- else obj
+ if obj.respond_to?(:dump_for_delayed_job)
+ "LOAD;#{obj.dump_for_delayed_job}"
+ else
+ obj
end
end
end
@@ -11,15 +11,6 @@ def say_hello
end
end
-class ErrorObject
-
- def throw
- raise ActiveRecord::RecordNotFound, '...'
- false
- end
-
-end
-
class StoryReader
def read(story)
@@ -65,7 +56,9 @@ def read(story)
end
it "should ignore ActiveRecord::RecordNotFound errors because they are permanent" do
- job = ErrorObject.new.send_later(:throw)
+ story = Story.create :text => 'Once upon...'
+ job = story.send_later(:tell)
+ story.destroy
lambda { job.invoke_job }.should_not raise_error
end
@@ -75,7 +68,7 @@ def read(story)
job = Delayed::Job.find(:first)
job.payload_object.class.should == Delayed::PerformableMethod
- job.payload_object.object.should == "AR:Story:#{story.id}"
+ job.payload_object.object.should == "LOAD;Story;#{story.id}"
job.payload_object.method.should == :tell
job.payload_object.args.should == []
job.payload_object.perform.should == 'Once upon...'
@@ -91,7 +84,7 @@ def read(story)
job = Delayed::Job.find(:first)
job.payload_object.class.should == Delayed::PerformableMethod
job.payload_object.method.should == :read
- job.payload_object.args.should == ["AR:Story:#{story.id}"]
+ job.payload_object.args.should == ["LOAD;Story;#{story.id}"]
job.payload_object.perform.should == 'Epilog: Once upon...'
end
View
@@ -44,7 +44,7 @@ def tell
job = story.send_later(:tell)
job.payload_object.class.should == Delayed::PerformableMethod
- job.payload_object.object.should == "MM:MongoStory:#{story.id}"
+ job.payload_object.object.should == "LOAD;MongoStory;#{story.id}"
job.payload_object.method.should == :tell
job.payload_object.args.should == []
job.payload_object.perform.should == 'Once upon a time…'
@@ -55,7 +55,7 @@ def tell
job = MongoStoryReader.new.send_later(:read, story)
job.payload_object.class.should == Delayed::PerformableMethod
job.payload_object.method.should == :read
- job.payload_object.args.should == ["MM:MongoStory:#{story.id}"]
+ job.payload_object.args.should == ["LOAD;MongoStory;#{story.id}"]
job.payload_object.perform.should == 'Epilog: Once upon a time…'
end
end

0 comments on commit 35a2808

Please sign in to comment.