moneypools-delayed_job 1.8.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,21 @@
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
+ module M
16
+ class ModuleJob
17
+ cattr_accessor :runs; self.runs = 0
18
+ def perform; @@runs += 1; end
19
+ end
20
+
21
+ end
@@ -0,0 +1,33 @@
1
+ require 'active_record'
2
+
3
+ ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
4
+ ActiveRecord::Base.logger = DELAYED_JOB_LOGGER
5
+ ActiveRecord::Migration.verbose = false
6
+
7
+ ActiveRecord::Schema.define do
8
+
9
+ create_table :delayed_jobs, :force => true do |table|
10
+ table.integer :priority, :default => 0
11
+ table.integer :attempts, :default => 0
12
+ table.text :handler
13
+ table.string :last_error
14
+ table.datetime :run_at
15
+ table.datetime :locked_at
16
+ table.string :locked_by
17
+ table.datetime :failed_at
18
+ table.timestamps
19
+ end
20
+
21
+ create_table :stories, :force => true do |table|
22
+ table.string :text
23
+ end
24
+
25
+ end
26
+
27
+ # Purely useful for test cases...
28
+ class Story < ActiveRecord::Base
29
+ def tell; text; end
30
+ def whatever(n, _); tell*n; end
31
+
32
+ handle_asynchronously :whatever
33
+ end
@@ -0,0 +1,13 @@
1
+ MongoMapper.connection = Mongo::Connection.new nil, nil, :logger => DELAYED_JOB_LOGGER
2
+ MongoMapper.database = 'delayed_job'
3
+
4
+ unless defined?(Story)
5
+ class Story
6
+ include ::MongoMapper::Document
7
+ def tell; text; end
8
+ def whatever(n, _); tell*n; end
9
+ def self.count; end
10
+
11
+ handle_asynchronously :whatever
12
+ end
13
+ end
@@ -0,0 +1,33 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'rubygems'
4
+ require 'spec'
5
+ require 'logger'
6
+
7
+ backends_available = []
8
+ %w(active_record mongo_mapper).each do |backend|
9
+ begin
10
+ require backend
11
+ backends_available << backend
12
+ rescue LoadError => e
13
+ $stderr.puts "The backend '#{backend}' is not available. Skipping tests"
14
+ end
15
+ end
16
+
17
+ if backends_available.empty?
18
+ raise LoadError, "Cannot run delayed_job specs. No backends available"
19
+ end
20
+
21
+ require 'delayed_job'
22
+ require 'sample_jobs'
23
+ require 'backend/shared_backend_spec'
24
+
25
+ DELAYED_JOB_LOGGER = Logger.new('/tmp/dj.log')
26
+ Delayed::Worker.logger = DELAYED_JOB_LOGGER
27
+
28
+ DEFAULT_BACKEND = backends_available.first.to_sym
29
+
30
+ backends_available.each do |backend|
31
+ require "setup/#{backend}"
32
+ require "backend/#{backend}_job_spec"
33
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe "A story" do
4
+
5
+ before(:all) do
6
+ @story = Story.create :text => "Once upon a time..."
7
+ end
8
+
9
+ it "should be shared" do
10
+ @story.tell.should == 'Once upon a time...'
11
+ end
12
+
13
+ it "should not return its result if it storytelling is delayed" do
14
+ @story.send_later(:tell).should_not == 'Once upon a time...'
15
+ end
16
+
17
+ end
@@ -0,0 +1,178 @@
1
+ require 'spec_helper'
2
+
3
+ describe Delayed::Worker do
4
+ def job_create(opts = {})
5
+ Delayed::Job.create(opts.merge(:payload_object => SimpleJob.new))
6
+ end
7
+
8
+ before(:all) do
9
+ Delayed::Worker.send :public, :work_off
10
+ end
11
+
12
+ before(:each) do
13
+ # Make sure backend is set to active record
14
+ Delayed::Worker.backend = DEFAULT_BACKEND
15
+
16
+ @worker = Delayed::Worker.new(:max_priority => nil, :min_priority => nil, :quiet => true)
17
+
18
+ Delayed::Job.delete_all
19
+
20
+ SimpleJob.runs = 0
21
+ end
22
+
23
+ describe "backend=" do
24
+ it "should set the Delayed::Job constant to the backend" do
25
+ @clazz = Class.new
26
+ Delayed::Worker.backend = @clazz
27
+ Delayed::Job.should == @clazz
28
+ end
29
+
30
+ it "should set backend with a symbol" do
31
+ Delayed::Worker.backend = Class.new
32
+ Delayed::Worker.backend = :active_record
33
+ Delayed::Worker.backend.should == Delayed::Backend::ActiveRecord::Job
34
+ end
35
+ end
36
+
37
+ describe "running a job" do
38
+ it "should fail after Worker.max_run_time" do
39
+ begin
40
+ old_max_run_time = Delayed::Worker.max_run_time
41
+ Delayed::Worker.max_run_time = 1.second
42
+ @job = Delayed::Job.create :payload_object => LongRunningJob.new
43
+ @worker.run(@job)
44
+ @job.reload.last_error.should =~ /expired/
45
+ @job.attempts.should == 1
46
+ ensure
47
+ Delayed::Worker.max_run_time = old_max_run_time
48
+ end
49
+ end
50
+ end
51
+
52
+ context "worker prioritization" do
53
+ before(:each) do
54
+ @worker = Delayed::Worker.new(:max_priority => 5, :min_priority => -5, :quiet => true)
55
+ end
56
+
57
+ it "should only work_off jobs that are >= min_priority" do
58
+ SimpleJob.runs.should == 0
59
+
60
+ job_create(:priority => -10)
61
+ job_create(:priority => 0)
62
+ @worker.work_off
63
+
64
+ SimpleJob.runs.should == 1
65
+ end
66
+
67
+ it "should only work_off jobs that are <= max_priority" do
68
+ SimpleJob.runs.should == 0
69
+
70
+ job_create(:priority => 10)
71
+ job_create(:priority => 0)
72
+
73
+ @worker.work_off
74
+
75
+ SimpleJob.runs.should == 1
76
+ end
77
+ end
78
+
79
+ context "while running with locked and expired jobs" do
80
+ before(:each) do
81
+ @worker.name = 'worker1'
82
+ end
83
+
84
+ it "should not run jobs locked by another worker" do
85
+ job_create(:locked_by => 'other_worker', :locked_at => (Delayed::Job.db_time_now - 1.minutes))
86
+ lambda { @worker.work_off }.should_not change { SimpleJob.runs }
87
+ end
88
+
89
+ it "should run open jobs" do
90
+ job_create
91
+ lambda { @worker.work_off }.should change { SimpleJob.runs }.from(0).to(1)
92
+ end
93
+
94
+ it "should run expired jobs" do
95
+ expired_time = Delayed::Job.db_time_now - (1.minutes + Delayed::Worker.max_run_time)
96
+ job_create(:locked_by => 'other_worker', :locked_at => expired_time)
97
+ lambda { @worker.work_off }.should change { SimpleJob.runs }.from(0).to(1)
98
+ end
99
+
100
+ it "should run own jobs" do
101
+ job_create(:locked_by => @worker.name, :locked_at => (Delayed::Job.db_time_now - 1.minutes))
102
+ lambda { @worker.work_off }.should change { SimpleJob.runs }.from(0).to(1)
103
+ end
104
+ end
105
+
106
+ describe "failed jobs" do
107
+ before do
108
+ # reset defaults
109
+ Delayed::Worker.destroy_failed_jobs = true
110
+ Delayed::Worker.max_attempts = 25
111
+
112
+ @job = Delayed::Job.enqueue ErrorJob.new
113
+ end
114
+
115
+ it "should record last_error when destroy_failed_jobs = false, max_attempts = 1" do
116
+ Delayed::Worker.destroy_failed_jobs = false
117
+ Delayed::Worker.max_attempts = 1
118
+ @worker.run(@job)
119
+ @job.reload
120
+ @job.last_error.should =~ /did not work/
121
+ @job.last_error.should =~ /worker_spec.rb/
122
+ @job.attempts.should == 1
123
+ @job.failed_at.should_not be_nil
124
+ end
125
+
126
+ it "should re-schedule jobs after failing" do
127
+ @worker.run(@job)
128
+ @job.reload
129
+ @job.last_error.should =~ /did not work/
130
+ @job.last_error.should =~ /sample_jobs.rb:8:in `perform'/
131
+ @job.attempts.should == 1
132
+ @job.run_at.should > Delayed::Job.db_time_now - 10.minutes
133
+ @job.run_at.should < Delayed::Job.db_time_now + 10.minutes
134
+ end
135
+ end
136
+
137
+ context "reschedule" do
138
+ before do
139
+ @job = Delayed::Job.create :payload_object => SimpleJob.new
140
+ end
141
+
142
+ context "and we want to destroy jobs" do
143
+ before do
144
+ Delayed::Worker.destroy_failed_jobs = true
145
+ end
146
+
147
+ it "should be destroyed if it failed more than Worker.max_attempts times" do
148
+ @job.should_receive(:destroy)
149
+ Delayed::Worker.max_attempts.times { @worker.reschedule(@job) }
150
+ end
151
+
152
+ it "should not be destroyed if failed fewer than Worker.max_attempts times" do
153
+ @job.should_not_receive(:destroy)
154
+ (Delayed::Worker.max_attempts - 1).times { @worker.reschedule(@job) }
155
+ end
156
+ end
157
+
158
+ context "and we don't want to destroy jobs" do
159
+ before do
160
+ Delayed::Worker.destroy_failed_jobs = false
161
+ end
162
+
163
+ it "should be failed if it failed more than Worker.max_attempts times" do
164
+ @job.reload.failed_at.should == nil
165
+ Delayed::Worker.max_attempts.times { @worker.reschedule(@job) }
166
+ @job.reload.failed_at.should_not == nil
167
+ end
168
+
169
+ it "should not be failed if it failed fewer than Worker.max_attempts times" do
170
+ (Delayed::Worker.max_attempts - 1).times { @worker.reschedule(@job) }
171
+ @job.reload.failed_at.should == nil
172
+ end
173
+
174
+ end
175
+ end
176
+
177
+
178
+ end
@@ -0,0 +1 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'delayed', 'tasks'))
metadata ADDED
@@ -0,0 +1,144 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: moneypools-delayed_job
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 8
8
+ - 4
9
+ version: 1.8.4
10
+ platform: ruby
11
+ authors:
12
+ - Brandon Keepers
13
+ - "Tobias L\xC3\xBCtke"
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-02-23 00:00:00 -06:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: daemons
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: rspec
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ segments:
41
+ - 0
42
+ version: "0"
43
+ type: :development
44
+ version_requirements: *id002
45
+ - !ruby/object:Gem::Dependency
46
+ name: sqlite3-ruby
47
+ prerelease: false
48
+ requirement: &id003 !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ segments:
53
+ - 0
54
+ version: "0"
55
+ type: :development
56
+ version_requirements: *id003
57
+ description: Delayed_job (or DJ) encapsulates the common pattern of asynchronously executing longer tasks in the background. It is a direct extraction from Shopify where the job table is responsible for a multitude of core tasks.
58
+ email: tobi@leetsoft.com
59
+ executables: []
60
+
61
+ extensions: []
62
+
63
+ extra_rdoc_files:
64
+ - README.textile
65
+ files:
66
+ - .gitignore
67
+ - MIT-LICENSE
68
+ - README.textile
69
+ - Rakefile
70
+ - VERSION
71
+ - contrib/delayed_job.monitrc
72
+ - delayed_job.gemspec
73
+ - generators/delayed_job/delayed_job_generator.rb
74
+ - generators/delayed_job/templates/migration.rb
75
+ - generators/delayed_job/templates/script
76
+ - init.rb
77
+ - lib/delayed/backend/active_record.rb
78
+ - lib/delayed/backend/base.rb
79
+ - lib/delayed/backend/mongo_mapper.rb
80
+ - lib/delayed/command.rb
81
+ - lib/delayed/message_sending.rb
82
+ - lib/delayed/performable_method.rb
83
+ - lib/delayed/recipes.rb
84
+ - lib/delayed/tasks.rb
85
+ - lib/delayed/worker.rb
86
+ - lib/delayed_job.rb
87
+ - recipes/delayed_job.rb
88
+ - spec/backend/active_record_job_spec.rb
89
+ - spec/backend/mongo_mapper_job_spec.rb
90
+ - spec/backend/shared_backend_spec.rb
91
+ - spec/delayed_method_spec.rb
92
+ - spec/performable_method_spec.rb
93
+ - spec/sample_jobs.rb
94
+ - spec/setup/active_record.rb
95
+ - spec/setup/mongo_mapper.rb
96
+ - spec/spec_helper.rb
97
+ - spec/story_spec.rb
98
+ - spec/worker_spec.rb
99
+ - tasks/jobs.rake
100
+ has_rdoc: true
101
+ homepage: http://github.com/collectiveidea/delayed_job
102
+ licenses: []
103
+
104
+ post_install_message:
105
+ rdoc_options:
106
+ - --main
107
+ - README.textile
108
+ - --inline-source
109
+ - --line-numbers
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ segments:
117
+ - 0
118
+ version: "0"
119
+ required_rubygems_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ segments:
124
+ - 0
125
+ version: "0"
126
+ requirements: []
127
+
128
+ rubyforge_project:
129
+ rubygems_version: 1.3.6
130
+ signing_key:
131
+ specification_version: 3
132
+ summary: Database-backed asynchronous priority queue system -- Extracted from Shopify
133
+ test_files:
134
+ - spec/backend/active_record_job_spec.rb
135
+ - spec/backend/mongo_mapper_job_spec.rb
136
+ - spec/backend/shared_backend_spec.rb
137
+ - spec/delayed_method_spec.rb
138
+ - spec/performable_method_spec.rb
139
+ - spec/sample_jobs.rb
140
+ - spec/setup/active_record.rb
141
+ - spec/setup/mongo_mapper.rb
142
+ - spec/spec_helper.rb
143
+ - spec/story_spec.rb
144
+ - spec/worker_spec.rb