Permalink
Browse files

Make performable method work with Mongo

  • Loading branch information...
1 parent 661f0f3 commit da4b5d0453fe7ea03ba59bdd44fe02fb49d366d9 @bkeepers bkeepers committed Jan 19, 2010
Showing with 63 additions and 17 deletions.
  1. +19 −17 lib/delayed/performable_method.rb
  2. +44 −0 spec/mongo_job_spec.rb
@@ -2,6 +2,10 @@ 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+)$/
+
+ class LoadError < StandardError
+ end
def initialize(object, method, args)
raise NoMethodError, "undefined method `#{method}' for #{self.inspect}" unless object.respond_to?(method)
@@ -15,41 +19,39 @@ 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 perform
load(object).send(method, *args.map{|a| load(a)})
- rescue ActiveRecord::RecordNotFound
+ rescue PerformableMethod::LoadError
# We cannot do anything about objects which were deleted in the meantime
true
end
private
- def load(arg)
- case arg
+ def load(obj)
+ case obj
when CLASS_STRING_FORMAT then $1.constantize
when AR_STRING_FORMAT then $1.constantize.find($2)
- else arg
+ when MM_STRING_FORMAT then $1.constantize.find!($2)
+ else obj
end
+ rescue => e
+ Delayed::Worker.logger.warn "Could not load object for job: #{e.message}"
+ raise PerformableMethod::LoadError
end
- def dump(arg)
- case arg
- when Class then class_to_string(arg)
- when ActiveRecord::Base then ar_to_string(arg)
- else arg
+ 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
end
end
-
- def ar_to_string(obj)
- "AR:#{obj.class}:#{obj.id}"
- end
-
- def class_to_string(obj)
- "CLASS:#{obj.name}"
- end
end
end
View
@@ -15,4 +15,48 @@
end
it_should_behave_like 'a backend'
+
+ describe "delayed method" do
+ class MongoStoryReader
+ def read(story)
+ "Epilog: #{story.tell}"
+ end
+ end
+
+ class MongoStory
+ include MongoMapper::Document
+ key :text, String
+
+ def tell
+ text
+ end
+ end
+
+ it "should ignore not found errors because they are permanent" do
+ story = MongoStory.create :text => 'Once upon a time…'
+ job = story.send_later(:tell)
+ story.destroy
+ lambda { job.invoke_job }.should_not raise_error
+ end
+
+ it "should store the object as string" do
+ story = MongoStory.create :text => 'Once upon a time…'
+ job = story.send_later(:tell)
+
+ job.payload_object.class.should == Delayed::PerformableMethod
+ job.payload_object.object.should == "MM:MongoStory:#{story.id}"
+ job.payload_object.method.should == :tell
+ job.payload_object.args.should == []
+ job.payload_object.perform.should == 'Once upon a time…'
+ end
+
+ it "should store arguments as string" do
+ story = MongoStory.create :text => 'Once upon a time…'
+ 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.perform.should == 'Epilog: Once upon a time…'
+ end
+ end
end

0 comments on commit da4b5d0

Please sign in to comment.