delayed_job 2.1.2 → 2.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -206,6 +206,8 @@ Delayed::Worker.destroy_failed_jobs = false. The failed jobs will be marked with
206
206
 
207
207
  By default all jobs are scheduled with priority = 0, which is top priority. You can change this by setting Delayed::Worker.default_priority to something else. Lower numbers have higher priority.
208
208
 
209
+ It is possible to disable delayed jobs for testing purposes. Set Delayed::Worker.delay_jobs = false to execute all jobs realtime.
210
+
209
211
  Here is an example of changing job parameters in Rails:
210
212
 
211
213
  <pre>
@@ -214,6 +216,7 @@ Delayed::Worker.destroy_failed_jobs = false
214
216
  Delayed::Worker.sleep_delay = 60
215
217
  Delayed::Worker.max_attempts = 3
216
218
  Delayed::Worker.max_run_time = 5.minutes
219
+ Delayed::Worker.delay_jobs = !Rails.env.test?
217
220
  </pre>
218
221
 
219
222
  h3. Cleaning up
@@ -16,10 +16,6 @@ module Delayed
16
16
  }
17
17
  scope :by_priority, order('priority ASC, run_at ASC')
18
18
 
19
- scope :locked_by_worker, lambda{|worker_name, max_run_time|
20
- where(['locked_by = ? AND locked_at > ?', worker_name, db_time_now - max_run_time])
21
- }
22
-
23
19
  def self.before_fork
24
20
  ::ActiveRecord::Base.clear_all_connections!
25
21
  end
@@ -33,25 +29,37 @@ module Delayed
33
29
  update_all("locked_by = null, locked_at = null", ["locked_by = ?", worker_name])
34
30
  end
35
31
 
36
- def self.jobs_available_to_worker(worker_name, max_run_time)
32
+ # Find a few candidate jobs to run (in case some immediately get locked by others).
33
+ def self.find_available(worker_name, limit = 5, max_run_time = Worker.max_run_time)
37
34
  scope = self.ready_to_run(worker_name, max_run_time)
38
35
  scope = scope.scoped(:conditions => ['priority >= ?', Worker.min_priority]) if Worker.min_priority
39
36
  scope = scope.scoped(:conditions => ['priority <= ?', Worker.max_priority]) if Worker.max_priority
40
- scope.by_priority
41
- end
42
37
 
43
- # Reserve a single job in a single update query. This causes workers to serialize on the
44
- # database and avoids contention.
45
- def self.reserve(worker, max_run_time = Worker.max_run_time)
46
- affected_rows = 0
47
38
  ::ActiveRecord::Base.silence do
48
- affected_rows = jobs_available_to_worker(worker.name, max_run_time).limit(1).update_all(["locked_at = ?, locked_by = ?", db_time_now, worker.name])
39
+ scope.by_priority.all(:limit => limit)
49
40
  end
41
+ end
50
42
 
43
+ # Lock this job for this worker.
44
+ # Returns true if we have the lock, false otherwise.
45
+ def lock_exclusively!(max_run_time, worker)
46
+ now = self.class.db_time_now
47
+ affected_rows = if locked_by != worker
48
+ # We don't own this job so we will update the locked_by name and the locked_at
49
+ self.class.update_all(["locked_at = ?, locked_by = ?", now, worker], ["id = ? and (locked_at is null or locked_at < ?) and (run_at <= ?)", id, (now - max_run_time.to_i), now])
50
+ else
51
+ # We already own this job, this may happen if the job queue crashes.
52
+ # Simply resume and update the locked_at
53
+ self.class.update_all(["locked_at = ?", now], ["id = ? and locked_by = ?", id, worker])
54
+ end
51
55
  if affected_rows == 1
52
- locked_by_worker(worker.name, max_run_time).first
56
+ self.locked_at = now
57
+ self.locked_by = worker
58
+ self.locked_at_will_change!
59
+ self.locked_by_will_change!
60
+ return true
53
61
  else
54
- nil
62
+ return false
55
63
  end
56
64
  end
57
65
 
@@ -23,9 +23,13 @@ module Delayed
23
23
  unless options[:payload_object].respond_to?(:perform)
24
24
  raise ArgumentError, 'Cannot enqueue items which do not respond to perform'
25
25
  end
26
-
27
- self.create(options).tap do |job|
28
- job.hook(:enqueue)
26
+
27
+ if Delayed::Worker.delay_jobs
28
+ self.create(options).tap do |job|
29
+ job.hook(:enqueue)
30
+ end
31
+ else
32
+ options[:payload_object].perform
29
33
  end
30
34
  end
31
35
 
@@ -11,6 +11,7 @@ shared_examples_for 'a delayed_job backend' do
11
11
  Delayed::Worker.max_priority = nil
12
12
  Delayed::Worker.min_priority = nil
13
13
  Delayed::Worker.default_priority = 99
14
+ Delayed::Worker.delay_jobs = true
14
15
  SimpleJob.runs = 0
15
16
  described_class.delete_all
16
17
  end
@@ -57,6 +58,12 @@ shared_examples_for 'a delayed_job backend' do
57
58
  described_class.enqueue SimpleJob.new
58
59
  described_class.count.should == 1
59
60
  end
61
+
62
+ it "should not increase count after enqueuing items when delay_jobs is false" do
63
+ Delayed::Worker.delay_jobs = false
64
+ described_class.enqueue SimpleJob.new
65
+ described_class.count.should == 0
66
+ end
60
67
 
61
68
  it "should be able to set priority [DEPRECATED]" do
62
69
  silence_warnings do
@@ -155,6 +162,17 @@ shared_examples_for 'a delayed_job backend' do
155
162
  described_class.reserve(worker).should be_nil
156
163
  end
157
164
 
165
+ it "should reserve jobs scheduled for the past" do
166
+ job = create_job :run_at => described_class.db_time_now - 1.minute
167
+ described_class.reserve(worker).should == job
168
+ end
169
+
170
+ it "should reserve jobs scheduled for the past when time zones are involved" do
171
+ Time.zone = 'US/Eastern'
172
+ job = create_job :run_at => described_class.db_time_now - 1.minute.ago.in_time_zone
173
+ described_class.reserve(worker).should == job
174
+ end
175
+
158
176
  it "should not reserve jobs locked by other workers" do
159
177
  job = create_job
160
178
  other_worker = Delayed::Worker.new
@@ -10,7 +10,7 @@
10
10
  # If you want to use command line options, for example to start multiple workers,
11
11
  # define a Capistrano variable delayed_job_args:
12
12
  #
13
- # set :delayed_jobs_args, "-n 2"
13
+ # set :delayed_job_args, "-n 2"
14
14
  #
15
15
  # If you've got delayed_job workers running on a servers, you can also specify
16
16
  # which servers have delayed_job running and should be restarted after deploy.
@@ -6,11 +6,12 @@ require 'logger'
6
6
 
7
7
  module Delayed
8
8
  class Worker
9
- cattr_accessor :min_priority, :max_priority, :max_attempts, :max_run_time, :default_priority, :sleep_delay, :logger
9
+ cattr_accessor :min_priority, :max_priority, :max_attempts, :max_run_time, :default_priority, :sleep_delay, :logger, :delay_jobs
10
10
  self.sleep_delay = 5
11
11
  self.max_attempts = 25
12
12
  self.max_run_time = 4.hours
13
13
  self.default_priority = 0
14
+ self.delay_jobs = true
14
15
 
15
16
  # By default failed jobs are destroyed after too many attempts. If you want to keep them around
16
17
  # (perhaps to inspect the reason for the failure), set this to false.
@@ -13,7 +13,6 @@ class CreateDelayedJobs < ActiveRecord::Migration
13
13
  end
14
14
 
15
15
  add_index :delayed_jobs, [:priority, :run_at], :name => 'delayed_jobs_priority'
16
- add_index :delayed_jobs, :locked_by, :name => 'delayed_jobs_locked_by'
17
16
  end
18
17
 
19
18
  def self.down
@@ -85,5 +85,32 @@ describe Delayed::MessageSending do
85
85
  job.run_at.should == run_at
86
86
  job.priority.should == 20
87
87
  end
88
+
89
+ class FairyTail
90
+ attr_accessor :happy_ending
91
+ def tell
92
+ @happy_ending = true
93
+ end
94
+ end
95
+
96
+ it "should not delay the job when delay_jobs is false" do
97
+ Delayed::Worker.delay_jobs = false
98
+ fairy_tail = FairyTail.new
99
+ lambda {
100
+ lambda {
101
+ fairy_tail.delay.tell
102
+ }.should change(fairy_tail, :happy_ending).from(nil).to(true)
103
+ }.should_not change { Delayed::Job.count }
104
+ end
105
+
106
+ it "should delay the job when delay_jobs is true" do
107
+ Delayed::Worker.delay_jobs = true
108
+ fairy_tail = FairyTail.new
109
+ lambda {
110
+ lambda {
111
+ fairy_tail.delay.tell
112
+ }.should_not change(fairy_tail, :happy_ending)
113
+ }.should change { Delayed::Job.count }.by(1)
114
+ end
88
115
  end
89
116
  end
metadata CHANGED
@@ -1,130 +1,125 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: delayed_job
3
3
  version: !ruby/object:Gem::Version
4
- hash: 15
5
4
  prerelease: false
6
5
  segments:
7
6
  - 2
8
7
  - 1
9
- - 2
10
- version: 2.1.2
8
+ - 3
9
+ version: 2.1.3
11
10
  platform: ruby
12
11
  authors:
12
+ - Chris Gaffney
13
13
  - Brandon Keepers
14
14
  - "Tobias L\xC3\xBCtke"
15
15
  autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2010-12-01 00:00:00 -05:00
19
+ date: 2011-01-20 00:00:00 -07:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
23
23
  name: daemons
24
- prerelease: false
25
24
  requirement: &id001 !ruby/object:Gem::Requirement
26
25
  none: false
27
26
  requirements:
28
27
  - - ">="
29
28
  - !ruby/object:Gem::Version
30
- hash: 3
31
29
  segments:
32
30
  - 0
33
31
  version: "0"
34
32
  type: :runtime
33
+ prerelease: false
35
34
  version_requirements: *id001
36
35
  - !ruby/object:Gem::Dependency
37
36
  name: activesupport
38
- prerelease: false
39
37
  requirement: &id002 !ruby/object:Gem::Requirement
40
38
  none: false
41
39
  requirements:
42
40
  - - ~>
43
41
  - !ruby/object:Gem::Version
44
- hash: 7
45
42
  segments:
46
43
  - 3
47
44
  - 0
48
45
  version: "3.0"
49
46
  type: :runtime
47
+ prerelease: false
50
48
  version_requirements: *id002
51
49
  - !ruby/object:Gem::Dependency
52
50
  name: rspec
53
- prerelease: false
54
51
  requirement: &id003 !ruby/object:Gem::Requirement
55
52
  none: false
56
53
  requirements:
57
54
  - - ~>
58
55
  - !ruby/object:Gem::Version
59
- hash: 3
60
56
  segments:
61
57
  - 2
62
58
  - 0
63
59
  version: "2.0"
64
60
  type: :development
61
+ prerelease: false
65
62
  version_requirements: *id003
66
63
  - !ruby/object:Gem::Dependency
67
64
  name: rake
68
- prerelease: false
69
65
  requirement: &id004 !ruby/object:Gem::Requirement
70
66
  none: false
71
67
  requirements:
72
68
  - - ">="
73
69
  - !ruby/object:Gem::Version
74
- hash: 3
75
70
  segments:
76
71
  - 0
77
72
  version: "0"
78
73
  type: :development
74
+ prerelease: false
79
75
  version_requirements: *id004
80
76
  - !ruby/object:Gem::Dependency
81
77
  name: rails
82
- prerelease: false
83
78
  requirement: &id005 !ruby/object:Gem::Requirement
84
79
  none: false
85
80
  requirements:
86
81
  - - ~>
87
82
  - !ruby/object:Gem::Version
88
- hash: 7
89
83
  segments:
90
84
  - 3
91
85
  - 0
92
86
  version: "3.0"
93
87
  type: :development
88
+ prerelease: false
94
89
  version_requirements: *id005
95
90
  - !ruby/object:Gem::Dependency
96
- name: sqlite3-ruby
97
- prerelease: false
91
+ name: sqlite3
98
92
  requirement: &id006 !ruby/object:Gem::Requirement
99
93
  none: false
100
94
  requirements:
101
95
  - - ">="
102
96
  - !ruby/object:Gem::Version
103
- hash: 3
104
97
  segments:
105
98
  - 0
106
99
  version: "0"
107
100
  type: :development
101
+ prerelease: false
108
102
  version_requirements: *id006
109
103
  - !ruby/object:Gem::Dependency
110
104
  name: mysql
111
- prerelease: false
112
105
  requirement: &id007 !ruby/object:Gem::Requirement
113
106
  none: false
114
107
  requirements:
115
108
  - - ">="
116
109
  - !ruby/object:Gem::Version
117
- hash: 3
118
110
  segments:
119
111
  - 0
120
112
  version: "0"
121
113
  type: :development
114
+ prerelease: false
122
115
  version_requirements: *id007
123
116
  description: |-
124
117
  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.
125
118
 
126
119
  This gem is collectiveidea's fork (http://github.com/collectiveidea/delayed_job).
127
- email: brandon@collectiveidea.com
120
+ email:
121
+ - chris@collectiveidea.com
122
+ - brandon@opensoul.org
128
123
  executables: []
129
124
 
130
125
  extensions: []
@@ -183,7 +178,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
183
178
  requirements:
184
179
  - - ">="
185
180
  - !ruby/object:Gem::Version
186
- hash: 3
181
+ hash: -1896469102761102405
187
182
  segments:
188
183
  - 0
189
184
  version: "0"
@@ -192,7 +187,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
192
187
  requirements:
193
188
  - - ">="
194
189
  - !ruby/object:Gem::Version
195
- hash: 3
190
+ hash: -1896469102761102405
196
191
  segments:
197
192
  - 0
198
193
  version: "0"