topprospect-delayed_job 2.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.textile +210 -0
  3. data/contrib/delayed_job.monitrc +14 -0
  4. data/contrib/delayed_job_multiple.monitrc +23 -0
  5. data/lib/delayed/backend/active_record.rb +97 -0
  6. data/lib/delayed/backend/active_record.rb.orig +105 -0
  7. data/lib/delayed/backend/base.rb +85 -0
  8. data/lib/delayed/backend/couch_rest.rb +109 -0
  9. data/lib/delayed/backend/data_mapper.rb +121 -0
  10. data/lib/delayed/backend/mongo_mapper.rb +106 -0
  11. data/lib/delayed/command.rb +107 -0
  12. data/lib/delayed/message_sending.rb +45 -0
  13. data/lib/delayed/performable_method.rb +27 -0
  14. data/lib/delayed/railtie.rb +14 -0
  15. data/lib/delayed/recipes.rb +31 -0
  16. data/lib/delayed/tasks.rb +20 -0
  17. data/lib/delayed/tasks.rb.orig +26 -0
  18. data/lib/delayed/worker.rb +213 -0
  19. data/lib/delayed/worker.rb.orig +202 -0
  20. data/lib/delayed/yaml_ext.rb +40 -0
  21. data/lib/delayed_job.rb +15 -0
  22. data/lib/generators/delayed_job/delayed_job_generator.rb +34 -0
  23. data/lib/generators/delayed_job/templates/migration.rb +21 -0
  24. data/lib/generators/delayed_job/templates/script +5 -0
  25. data/recipes/delayed_job.rb +1 -0
  26. data/spec/autoloaded/clazz.rb +7 -0
  27. data/spec/autoloaded/struct.rb +7 -0
  28. data/spec/backend/active_record_job_spec.rb +54 -0
  29. data/spec/backend/couch_rest_job_spec.rb +15 -0
  30. data/spec/backend/data_mapper_job_spec.rb +16 -0
  31. data/spec/backend/mongo_mapper_job_spec.rb +94 -0
  32. data/spec/backend/shared_backend_spec.rb +280 -0
  33. data/spec/message_sending_spec.rb +51 -0
  34. data/spec/performable_method_spec.rb +48 -0
  35. data/spec/sample_jobs.rb +25 -0
  36. data/spec/setup/active_record.rb +54 -0
  37. data/spec/setup/couch_rest.rb +7 -0
  38. data/spec/setup/data_mapper.rb +8 -0
  39. data/spec/setup/mongo_mapper.rb +17 -0
  40. data/spec/spec_helper.rb +31 -0
  41. data/spec/worker_spec.rb +214 -0
  42. metadata +300 -0
@@ -0,0 +1,94 @@
1
+ require 'spec_helper'
2
+ require 'backend/shared_backend_spec'
3
+ require 'delayed/backend/mongo_mapper'
4
+
5
+ describe Delayed::Backend::MongoMapper::Job do
6
+ before(:all) do
7
+ @backend = Delayed::Backend::MongoMapper::Job
8
+ end
9
+
10
+ before(:each) do
11
+ MongoMapper.database.collections.each(&:remove)
12
+ end
13
+
14
+ it_should_behave_like 'a backend'
15
+
16
+ describe "indexes" do
17
+ it "should have combo index on priority and run_at" do
18
+ @backend.collection.index_information.detect { |index| index[0] == 'priority_1_run_at_1' }.should_not be_nil
19
+ end
20
+
21
+ it "should have index on locked_by" do
22
+ @backend.collection.index_information.detect { |index| index[0] == 'locked_by_1' }.should_not be_nil
23
+ end
24
+ end
25
+
26
+ describe "delayed method" do
27
+ class MongoStoryReader
28
+ def read(story)
29
+ "Epilog: #{story.tell}"
30
+ end
31
+ end
32
+
33
+ class MongoStory
34
+ include ::MongoMapper::Document
35
+ key :text, String
36
+
37
+ def tell
38
+ text
39
+ end
40
+ end
41
+
42
+ it "should ignore not found errors because they are permanent" do
43
+ story = MongoStory.create :text => 'Once upon a time...'
44
+ job = story.delay.tell
45
+ story.destroy
46
+ lambda { job.invoke_job }.should_not raise_error
47
+ end
48
+
49
+ it "should store the object as string" do
50
+ story = MongoStory.create :text => 'Once upon a time...'
51
+ job = story.delay.tell
52
+
53
+ job.payload_object.class.should == Delayed::PerformableMethod
54
+ job.payload_object.object.should == story
55
+ job.payload_object.method.should == :tell
56
+ job.payload_object.args.should == []
57
+ job.payload_object.perform.should == 'Once upon a time...'
58
+ end
59
+
60
+ it "should store arguments as string" do
61
+ story = MongoStory.create :text => 'Once upon a time...'
62
+ job = MongoStoryReader.new.delay.read(story)
63
+ job.payload_object.class.should == Delayed::PerformableMethod
64
+ job.payload_object.method.should == :read
65
+ job.payload_object.args.should == [story]
66
+ job.payload_object.perform.should == 'Epilog: Once upon a time...'
67
+ end
68
+ end
69
+
70
+ describe "before_fork" do
71
+ after do
72
+ MongoMapper.connection.connect_to_master
73
+ end
74
+
75
+ it "should disconnect" do
76
+ lambda do
77
+ Delayed::Backend::MongoMapper::Job.before_fork
78
+ end.should change { !!MongoMapper.connection.connected? }.from(true).to(false)
79
+ end
80
+ end
81
+
82
+ describe "after_fork" do
83
+ before do
84
+ MongoMapper.connection.close
85
+ end
86
+
87
+ it "should call reconnect" do
88
+ lambda do
89
+ Delayed::Backend::MongoMapper::Job.after_fork
90
+ end.should change { !!MongoMapper.connection.connected? }.from(false).to(true)
91
+ end
92
+ end
93
+
94
+ end
@@ -0,0 +1,280 @@
1
+ class NamedJob < Struct.new(:perform)
2
+ def display_name
3
+ 'named_job'
4
+ end
5
+ end
6
+
7
+ shared_examples_for 'a backend' do
8
+ def create_job(opts = {})
9
+ @backend.create(opts.merge(:payload_object => SimpleJob.new, :queue => Delayed::Worker.queue))
10
+ end
11
+
12
+ before do
13
+ # Delayed::Worker.queue must be defined
14
+ Delayed::Worker.max_priority = nil
15
+ Delayed::Worker.min_priority = nil
16
+ Delayed::Worker.default_priority = 99
17
+ SimpleJob.runs = 0
18
+ end
19
+
20
+ it "should set run_at automatically if not set" do
21
+ @backend.create(:payload_object => ErrorJob.new ).run_at.should_not be_nil
22
+ end
23
+
24
+ it "should not set run_at automatically if already set" do
25
+ later = @backend.db_time_now + 5.minutes
26
+ @backend.create(:payload_object => ErrorJob.new, :run_at => later).run_at.should be_close(later, 1)
27
+ end
28
+
29
+ it "should raise ArgumentError when handler doesn't respond_to :perform" do
30
+ lambda { @backend.enqueue(Object.new) }.should raise_error(ArgumentError)
31
+ end
32
+
33
+ it "should increase count after enqueuing items" do
34
+ @backend.enqueue SimpleJob.new
35
+ @backend.count.should == 1
36
+ end
37
+
38
+ it "should be able to set priority when enqueuing items" do
39
+ @job = @backend.enqueue SimpleJob.new, 5
40
+ @job.priority.should == 5
41
+ end
42
+
43
+ it "should use default priority when it is not set" do
44
+ @job = @backend.enqueue SimpleJob.new
45
+ @job.priority.should == 99
46
+ end
47
+
48
+ it "should be able to set run_at when enqueuing items" do
49
+ later = @backend.db_time_now + 5.minutes
50
+ @job = @backend.enqueue SimpleJob.new, 5, later
51
+ @job.run_at.should be_close(later, 1)
52
+ end
53
+
54
+ it "should work with jobs in modules" do
55
+ M::ModuleJob.runs = 0
56
+ job = @backend.enqueue M::ModuleJob.new
57
+ lambda { job.invoke_job }.should change { M::ModuleJob.runs }.from(0).to(1)
58
+ end
59
+
60
+ describe "payload_object" do
61
+ it "should raise a DeserializationError when the job class is totally unknown" do
62
+ job = @backend.new :handler => "--- !ruby/object:JobThatDoesNotExist {}"
63
+ lambda { job.payload_object }.should raise_error(Delayed::Backend::DeserializationError)
64
+ end
65
+
66
+ it "should raise a DeserializationError when the job struct is totally unknown" do
67
+ job = @backend.new :handler => "--- !ruby/struct:StructThatDoesNotExist {}"
68
+ lambda { job.payload_object }.should raise_error(Delayed::Backend::DeserializationError)
69
+ end
70
+
71
+ it "should autoload classes that are unknown at runtime" do
72
+ job = @backend.new :handler => "--- !ruby/object:Autoloaded::Clazz {}"
73
+ lambda { job.payload_object }.should_not raise_error(Delayed::Backend::DeserializationError)
74
+ end
75
+
76
+ it "should autoload structs that are unknown at runtime" do
77
+ job = @backend.new :handler => "--- !ruby/struct:Autoloaded::Struct {}"
78
+ lambda { job.payload_object }.should_not raise_error(Delayed::Backend::DeserializationError)
79
+ end
80
+ end
81
+
82
+ describe "find_available" do
83
+ it "should not find failed jobs" do
84
+ @job = create_job :attempts => 50, :failed_at => @backend.db_time_now
85
+ @backend.find_available('worker', 5, 1.second).should_not include(@job)
86
+ end
87
+
88
+ it "should not find jobs scheduled for the future" do
89
+ @job = create_job :run_at => (@backend.db_time_now + 1.minute)
90
+ @backend.find_available('worker', 5, 4.hours).should_not include(@job)
91
+ end
92
+
93
+ it "should not find jobs locked by another worker" do
94
+ @job = create_job(:locked_by => 'other_worker', :locked_at => @backend.db_time_now - 1.minute)
95
+ @backend.find_available('worker', 5, 4.hours).should_not include(@job)
96
+ end
97
+
98
+ it "should find open jobs" do
99
+ @job = create_job
100
+ @backend.find_available('worker', 5, 4.hours).should include(@job)
101
+ end
102
+
103
+ it "should find expired jobs" do
104
+ @job = create_job(:locked_by => 'worker', :locked_at => @backend.db_time_now - 2.minutes)
105
+ @backend.find_available('worker', 5, 1.minute).should include(@job)
106
+ end
107
+
108
+ it "should find own jobs" do
109
+ @job = create_job(:locked_by => 'worker', :locked_at => (@backend.db_time_now - 1.minutes))
110
+ @backend.find_available('worker', 5, 4.hours).should include(@job)
111
+ end
112
+
113
+ it "should find only the right amount of jobs" do
114
+ 10.times { create_job }
115
+ @backend.find_available('worker', 7, 4.hours).should have(7).jobs
116
+ end
117
+ end
118
+
119
+ context "when another worker is already performing an task, it" do
120
+
121
+ before :each do
122
+ @job = @backend.create :payload_object => SimpleJob.new, :locked_by => 'worker1', :locked_at => @backend.db_time_now - 5.minutes, :queue => Delayed::Worker.queue
123
+ end
124
+
125
+ it "should not allow a second worker to get exclusive access" do
126
+ @job.lock_exclusively!(4.hours, 'worker2').should == false
127
+ end
128
+
129
+ it "should allow a second worker to get exclusive access if the timeout has passed" do
130
+ @job.lock_exclusively!(1.minute, 'worker2').should == true
131
+ end
132
+
133
+ it "should be able to get access to the task if it was started more then max_age ago" do
134
+ @job.locked_at = 5.hours.ago
135
+ @job.save
136
+
137
+ @job.lock_exclusively! 4.hours, 'worker2'
138
+ @job.reload
139
+ @job.locked_by.should == 'worker2'
140
+ @job.locked_at.should > 1.minute.ago
141
+ end
142
+
143
+ it "should not be found by another worker" do
144
+ @backend.find_available('worker2', 1, 6.minutes).length.should == 0
145
+ end
146
+
147
+ it "should be found by another worker if the time has expired" do
148
+ @backend.find_available('worker2', 1, 4.minutes).length.should == 1
149
+ end
150
+
151
+ it "should be able to get exclusive access again when the worker name is the same" do
152
+ @job.lock_exclusively!(5.minutes, 'worker1').should be_true
153
+ @job.lock_exclusively!(5.minutes, 'worker1').should be_true
154
+ @job.lock_exclusively!(5.minutes, 'worker1').should be_true
155
+ end
156
+ end
157
+
158
+ context "when another worker has worked on a task since the job was found to be available, it" do
159
+
160
+ before :each do
161
+ @job = @backend.create :payload_object => SimpleJob.new
162
+ @job_copy_for_worker_2 = @backend.find(@job.id)
163
+ end
164
+
165
+ it "should not allow a second worker to get exclusive access if already successfully processed by worker1" do
166
+ @job.destroy
167
+ @job_copy_for_worker_2.lock_exclusively!(4.hours, 'worker2').should == false
168
+ end
169
+
170
+ it "should not allow a second worker to get exclusive access if failed to be processed by worker1 and run_at time is now in future (due to backing off behaviour)" do
171
+ @job.update_attributes(:attempts => 1, :run_at => 1.day.from_now)
172
+ @job_copy_for_worker_2.lock_exclusively!(4.hours, 'worker2').should == false
173
+ end
174
+ end
175
+
176
+ context "#name" do
177
+ it "should be the class name of the job that was enqueued" do
178
+ @backend.create(:payload_object => ErrorJob.new ).name.should == 'ErrorJob'
179
+ end
180
+
181
+ it "should be the method that will be called if its a performable method object" do
182
+ job = @backend.new(:payload_object => NamedJob.new)
183
+ job.name.should == 'named_job'
184
+ end
185
+
186
+ it "should be the instance method that will be called if its a performable method object" do
187
+ @job = Story.create(:text => "...").delay.save
188
+ @job.name.should == 'Story#save'
189
+ end
190
+ end
191
+
192
+ context "worker prioritization" do
193
+ before(:each) do
194
+ Delayed::Worker.max_priority = nil
195
+ Delayed::Worker.min_priority = nil
196
+ end
197
+
198
+ it "should fetch jobs ordered by priority" do
199
+ 10.times { @backend.enqueue SimpleJob.new, rand(10), Delayed::Worker.queue }
200
+ jobs = @backend.find_available('worker', 10)
201
+ jobs.size.should == 10
202
+ jobs.each_cons(2) do |a, b|
203
+ a.priority.should <= b.priority
204
+ end
205
+ end
206
+
207
+ it "should only find jobs greater than or equal to min priority" do
208
+ min = 5
209
+ Delayed::Worker.min_priority = min
210
+ 10.times {|i| @backend.enqueue SimpleJob.new, i }
211
+ jobs = @backend.find_available('worker', 10)
212
+ jobs.each {|job| job.priority.should >= min}
213
+ end
214
+
215
+ it "should only find jobs less than or equal to max priority" do
216
+ max = 5
217
+ Delayed::Worker.max_priority = max
218
+ 10.times {|i| @backend.enqueue SimpleJob.new, i }
219
+ jobs = @backend.find_available('worker', 10)
220
+ jobs.each {|job| job.priority.should <= max}
221
+ end
222
+ end
223
+
224
+ context "clear_locks!" do
225
+ before do
226
+ @job = create_job(:locked_by => 'worker', :locked_at => @backend.db_time_now)
227
+ end
228
+
229
+ it "should clear locks for the given worker" do
230
+ @backend.clear_locks!('worker')
231
+ @backend.find_available('worker2', 5, 1.minute).should include(@job)
232
+ end
233
+
234
+ it "should not clear locks for other workers" do
235
+ @backend.clear_locks!('worker1')
236
+ @backend.find_available('worker1', 5, 1.minute).should_not include(@job)
237
+ end
238
+ end
239
+
240
+ context "unlock" do
241
+ before do
242
+ @job = create_job(:locked_by => 'worker', :locked_at => @backend.db_time_now)
243
+ end
244
+
245
+ it "should clear locks" do
246
+ @job.unlock
247
+ @job.locked_by.should be_nil
248
+ @job.locked_at.should be_nil
249
+ end
250
+ end
251
+
252
+ context "large handler" do
253
+ before do
254
+ text = "Lorem ipsum dolor sit amet. " * 1000
255
+ @job = @backend.enqueue Delayed::PerformableMethod.new(text, :length, {})
256
+ end
257
+
258
+ it "should have an id" do
259
+ @job.id.should_not be_nil
260
+ end
261
+ end
262
+
263
+ describe "yaml serialization" do
264
+ it "should reload changed attributes" do
265
+ job = @backend.enqueue SimpleJob.new
266
+ yaml = job.to_yaml
267
+ job.priority = 99
268
+ job.save
269
+ YAML.load(yaml).priority.should == 99
270
+ end
271
+
272
+ it "should ignore destroyed records" do
273
+ job = @backend.enqueue SimpleJob.new
274
+ yaml = job.to_yaml
275
+ job.destroy
276
+ lambda { YAML.load(yaml).should be_nil }.should_not raise_error
277
+ end
278
+ end
279
+
280
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe Delayed::MessageSending do
4
+ describe "handle_asynchronously" do
5
+ class Story < ActiveRecord::Base
6
+ def tell!(arg)
7
+ end
8
+ handle_asynchronously :tell!
9
+ end
10
+
11
+ it "should alias original method" do
12
+ Story.new.should respond_to(:tell_without_delay!)
13
+ Story.new.should respond_to(:tell_with_delay!)
14
+ end
15
+
16
+ it "should create a PerformableMethod" do
17
+ story = Story.create!
18
+ lambda {
19
+ job = story.tell!(1)
20
+ job.payload_object.class.should == Delayed::PerformableMethod
21
+ job.payload_object.method.should == :tell_without_delay!
22
+ job.payload_object.args.should == [1]
23
+ }.should change { Delayed::Job.count }
24
+ end
25
+ end
26
+
27
+ context "delay" do
28
+ it "should create a new PerformableMethod job" do
29
+ lambda {
30
+ job = "hello".delay.count('l')
31
+ job.payload_object.class.should == Delayed::PerformableMethod
32
+ job.payload_object.method.should == :count
33
+ job.payload_object.args.should == ['l']
34
+ }.should change { Delayed::Job.count }.by(1)
35
+ end
36
+
37
+ it "should set default priority" do
38
+ Delayed::Worker.default_priority = 99
39
+ job = Object.delay.to_s
40
+ job.priority.should == 99
41
+ Delayed::Worker.default_priority = 0
42
+ end
43
+
44
+ it "should set job options" do
45
+ run_at = Time.parse('2010-05-03 12:55 AM')
46
+ job = Object.delay(:priority => 20, :run_at => run_at).to_s
47
+ job.run_at.should == run_at
48
+ job.priority.should == 20
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe Delayed::PerformableMethod do
4
+ describe "perform" do
5
+ before do
6
+ @method = Delayed::PerformableMethod.new("foo", :count, ['o'])
7
+ end
8
+
9
+ context "with the persisted record cannot be found" do
10
+ before do
11
+ @method.object = nil
12
+ end
13
+
14
+ it "should be a no-op if object is nil" do
15
+ lambda { @method.perform }.should_not raise_error
16
+ end
17
+ end
18
+
19
+ it "should call the method on the object" do
20
+ @method.object.should_receive(:count).with('o')
21
+ @method.perform
22
+ end
23
+
24
+ it "should respond to on_permanent_failure when implemented and target object is called via object.delay.do_something" do
25
+ @method = Delayed::PerformableMethod.new(OnPermanentFailureJob.new, :perform, [])
26
+ @method.respond_to?(:on_permanent_failure).should be_true
27
+ @method.object.should_receive(:on_permanent_failure)
28
+ @method.on_permanent_failure
29
+ end
30
+ end
31
+
32
+ it "should raise a NoMethodError if target method doesn't exist" do
33
+ lambda {
34
+ Delayed::PerformableMethod.new(Object, :method_that_does_not_exist, [])
35
+ }.should raise_error(NoMethodError)
36
+ end
37
+
38
+ it "should not raise NoMethodError if target method is private" do
39
+ clazz = Class.new do
40
+ def private_method
41
+ end
42
+ private :private_method
43
+ end
44
+ lambda {
45
+ Delayed::PerformableMethod.new(clazz.new, :private_method, [])
46
+ }.should_not raise_error(NoMethodError)
47
+ end
48
+ end
@@ -0,0 +1,25 @@
1
+ class SimpleJob
2
+ cattr_accessor :runs; self.runs = 0
3
+ def perform; @@runs += 1; end
4
+ end
5
+
6
+ class ErrorJob
7
+ cattr_accessor :runs; self.runs = 0
8
+ def perform; raise 'did not work'; end
9
+ end
10
+
11
+ class LongRunningJob
12
+ def perform; sleep 250; end
13
+ end
14
+
15
+ class OnPermanentFailureJob < SimpleJob
16
+ def on_permanent_failure
17
+ end
18
+ end
19
+
20
+ module M
21
+ class ModuleJob
22
+ cattr_accessor :runs; self.runs = 0
23
+ def perform; @@runs += 1; end
24
+ end
25
+ end
@@ -0,0 +1,54 @@
1
+ require 'active_record'
2
+
3
+ #ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
4
+ ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => 'test.sql3')
5
+ ActiveRecord::Base.logger = Delayed::Worker.logger
6
+ ActiveRecord::Migration.verbose = false
7
+
8
+ ActiveRecord::Schema.define do
9
+ create_table :delayed_jobs, :force => true do |table|
10
+ table.integer :priority, :default => 0
11
+ table.integer :attempts, :default => 0
12
+ table.column :handler, :mediumtext
13
+ table.text :last_error
14
+ table.datetime :run_at
15
+ table.datetime :locked_at
16
+ table.datetime :failed_at
17
+ table.string :locked_by
18
+ table.string :queue, :limit => 255, :null => false, :default => Delayed::DEFAULT_QUEUE
19
+ table.timestamps
20
+ end
21
+
22
+ =begin
23
+ CREATE TABLE `delayed_jobs` (
24
+ `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
25
+ `priority` int(11) DEFAULT '0',
26
+ `attempts` int(11) DEFAULT '0',
27
+ `handler` mediumtext COLLATE utf8_unicode_ci,
28
+ `last_error` text COLLATE utf8_unicode_ci,
29
+ `run_at` datetime DEFAULT NULL,
30
+ `locked_at` datetime DEFAULT NULL,
31
+ `failed_at` datetime DEFAULT NULL,
32
+ `locked_by` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL,
33
+ `queue` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
34
+ `created_at` datetime DEFAULT NULL,
35
+ `updated_at` datetime DEFAULT NULL,
36
+ PRIMARY KEY (`id`),
37
+ KEY `index_delayed_jobs_on_queue_and_locked_by` (`queue`,`locked_by`)
38
+ ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
39
+ =end
40
+
41
+ add_index :delayed_jobs, [:priority, :run_at], :name => 'delayed_jobs_priority'
42
+
43
+ create_table :stories, :force => true do |table|
44
+ table.string :text
45
+ end
46
+ end
47
+
48
+ # Purely useful for test cases...
49
+ class Story < ActiveRecord::Base
50
+ def tell; text; end
51
+ def whatever(n, _); tell*n; end
52
+
53
+ handle_asynchronously :whatever
54
+ end
@@ -0,0 +1,7 @@
1
+ require 'couchrest'
2
+ require 'delayed/backend/couch_rest'
3
+
4
+ Delayed::Backend::CouchRest::Job.use_database CouchRest::Server.new.database!('delayed_job_spec')
5
+
6
+ # try to perform a query to check that we can connect
7
+ Delayed::Backend::CouchRest::Job.all
@@ -0,0 +1,8 @@
1
+ require 'dm-core'
2
+ require 'dm-validations'
3
+
4
+ require 'delayed/backend/data_mapper'
5
+
6
+ DataMapper.logger = Delayed::Worker.logger
7
+ DataMapper.setup(:default, "sqlite3::memory:")
8
+ DataMapper.auto_migrate!
@@ -0,0 +1,17 @@
1
+ require 'mongo_mapper'
2
+
3
+ MongoMapper.config = {
4
+ RAILS_ENV => {'database' => 'delayed_job'}
5
+ }
6
+ MongoMapper.connect RAILS_ENV
7
+
8
+ unless defined?(Story)
9
+ class Story
10
+ include ::MongoMapper::Document
11
+ def tell; text; end
12
+ def whatever(n, _); tell*n; end
13
+ def self.count; end
14
+
15
+ handle_asynchronously :whatever
16
+ end
17
+ end
@@ -0,0 +1,31 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'rubygems'
4
+ require 'spec'
5
+ require 'logger'
6
+
7
+ gem 'rails', '~>2.3.5'
8
+
9
+ require 'delayed_job'
10
+ require 'sample_jobs'
11
+
12
+ Delayed::Worker.logger = Logger.new('/tmp/dj.log')
13
+ RAILS_ENV = 'test'
14
+
15
+ # determine the available backends
16
+ BACKENDS = []
17
+ Dir.glob("#{File.dirname(__FILE__)}/setup/*.rb") do |backend|
18
+ begin
19
+ backend = File.basename(backend, '.rb')
20
+ require "setup/#{backend}"
21
+ require "backend/#{backend}_job_spec"
22
+ BACKENDS << backend.to_sym
23
+ rescue Exception
24
+ puts "Unable to load #{backend} backend: #{$!}"
25
+ end
26
+ end
27
+
28
+ Delayed::Worker.backend = BACKENDS.first
29
+
30
+ # Add this directory so the ActiveSupport autoloading works
31
+ ActiveSupport::Dependencies.load_paths << File.dirname(__FILE__)