topprospect-delayed_job 2.0.6 → 2.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -25,6 +25,8 @@ module Delayed
25
25
 
26
26
  before_save :set_default_run_at
27
27
 
28
+
29
+ # TODO Rails 3 scope is not queue-aware as the mainstream delayed_job does it
28
30
  if ::ActiveRecord::VERSION::MAJOR >= 3
29
31
  scope :ready_to_run, lambda {|worker_name, max_run_time|
30
32
  where(['(run_at <= ? AND (locked_at IS NULL OR locked_at < ?) OR locked_by = ?) AND failed_at IS NULL', db_time_now, db_time_now - max_run_time, worker_name])
@@ -32,7 +34,16 @@ module Delayed
32
34
  scope :by_priority, order('priority ASC, run_at ASC')
33
35
  else
34
36
  named_scope :ready_to_run, lambda {|worker_name, max_run_time|
35
- {:conditions => ['queue = ? AND (run_at <= ? AND (locked_at IS NULL OR locked_at < ?) OR locked_by = ?) AND failed_at IS NULL', Worker.queue, db_time_now, db_time_now - max_run_time, worker_name]}
37
+
38
+ if Worker.queue == Delayed::ALL_QUEUES
39
+ conditions = ['(run_at <= ? AND (locked_at IS NULL OR locked_at < ?) OR locked_by = ?) AND failed_at IS NULL',
40
+ db_time_now, db_time_now - max_run_time, worker_name]
41
+ else
42
+ conditions = ['queue = ? AND (run_at <= ? AND (locked_at IS NULL OR locked_at < ?) OR locked_by = ?) AND failed_at IS NULL',
43
+ Worker.queue, db_time_now, db_time_now - max_run_time, worker_name]
44
+ end
45
+
46
+ {:conditions => conditions}
36
47
  }
37
48
  named_scope :by_priority, :order => 'priority ASC, run_at ASC'
38
49
  end
@@ -5,6 +5,7 @@ require 'active_support/core_ext/kernel'
5
5
 
6
6
  module Delayed
7
7
  DEFAULT_QUEUE = ''
8
+ ALL_QUEUES = 'ALL'
8
9
 
9
10
  class Worker
10
11
  cattr_accessor :min_priority, :max_priority, :max_attempts, :max_run_time, :default_priority, :sleep_delay, :logger, :queue
@@ -32,6 +33,7 @@ module Delayed
32
33
 
33
34
  # rename the default Rails logger file, if requested
34
35
  # TODO should we put it inside a Rails own class/module?
36
+ # TODO flush in any case, even if not renaming?
35
37
  #
36
38
  # http://stackoverflow.com/questions/3500200/getting-delayed-job-to-log
37
39
  # https://gist.github.com/833828
@@ -16,8 +16,7 @@ describe Delayed::Backend::ActiveRecord::Job do
16
16
  Time.zone = nil
17
17
  end
18
18
 
19
- it_should_behave_like 'a backend'
20
- [Delayed::DEFAULT_QUEUE, "foo"].each do |queue|
19
+ [Delayed::DEFAULT_QUEUE, Delayed::ALL_QUEUES, "foo"].each do |queue|
21
20
  context "when given a queue of #{queue}" do
22
21
  before do
23
22
  Delayed::Worker.queue = queue
@@ -26,6 +25,46 @@ describe Delayed::Backend::ActiveRecord::Job do
26
25
  end
27
26
  end
28
27
 
28
+ context "named queues" do
29
+ def create_job(opts = {})
30
+ @backend.create({:payload_object => SimpleJob.new, :queue => Delayed::Worker.queue}.merge(opts))
31
+ end
32
+
33
+ context "when worker has one queue set" do
34
+ before(:each) do
35
+ @worker = Delayed::Worker.new(:queue => "large")
36
+ end
37
+
38
+ it "should only work off jobs which are from its queue" do
39
+ SimpleJob.runs.should == 0
40
+
41
+ create_job(:queue => "large")
42
+ create_job(:queue => "small")
43
+ @worker.work_off
44
+
45
+ SimpleJob.runs.should == 1
46
+ end
47
+ end
48
+
49
+ context "when worker has all queues set" do
50
+ before(:each) do
51
+ @worker = Delayed::Worker.new(:queue => Delayed::ALL_QUEUES)
52
+ end
53
+
54
+ it "should work off all jobs for ALL queue designator" do
55
+ SimpleJob.runs.should == 0
56
+
57
+ create_job(:queue => "large")
58
+ create_job(:queue => "small")
59
+ create_job(:queue => "medium")
60
+ create_job(:queue => Delayed::DEFAULT_QUEUE)
61
+ @worker.work_off
62
+
63
+ SimpleJob.runs.should == 4
64
+ end
65
+ end
66
+ end
67
+
29
68
  context "db_time_now" do
30
69
  it "should return time in current time zone if set" do
31
70
  Time.zone = 'Eastern Time (US & Canada)'
@@ -6,7 +6,7 @@ end
6
6
 
7
7
  shared_examples_for 'a backend' do
8
8
  def create_job(opts = {})
9
- @backend.create(opts.merge(:payload_object => SimpleJob.new, :queue => Delayed::Worker.queue))
9
+ @backend.create({:payload_object => SimpleJob.new, :queue => Delayed::Worker.queue}.merge(opts))
10
10
  end
11
11
 
12
12
  before do
@@ -18,7 +18,7 @@ shared_examples_for 'a backend' do
18
18
  end
19
19
 
20
20
  it "should set run_at automatically if not set" do
21
- @backend.create(:payload_object => ErrorJob.new ).run_at.should_not be_nil
21
+ @backend.create(:payload_object => ErrorJob.new).run_at.should_not be_nil
22
22
  end
23
23
 
24
24
  it "should not set run_at automatically if already set" do
metadata CHANGED
@@ -1,23 +1,25 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: topprospect-delayed_job
3
3
  version: !ruby/object:Gem::Version
4
- hash: 3
4
+ hash: 1
5
5
  prerelease:
6
6
  segments:
7
7
  - 2
8
8
  - 0
9
- - 6
10
- version: 2.0.6
9
+ - 7
10
+ version: 2.0.7
11
11
  platform: ruby
12
12
  authors:
13
13
  - Chris Gaffney
14
14
  - Brandon Keepers
15
15
  - "Tobias L\xC3\xBCtke"
16
+ - Sujoy Gupta
17
+ - Alexy Khrabrov
16
18
  autorequire:
17
19
  bindir: bin
18
20
  cert_chain: []
19
21
 
20
- date: 2011-07-26 00:00:00 -07:00
22
+ date: 2011-09-01 00:00:00 -07:00
21
23
  default_executable:
22
24
  dependencies:
23
25
  - !ruby/object:Gem::Dependency
@@ -190,9 +192,10 @@ dependencies:
190
192
  type: :development
191
193
  version_requirements: *id012
192
194
  description: |-
193
- 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.
194
-
195
- This gem is collectiveidea's fork (http://github.com/collectiveidea/delayed_job).
195
+ Delayed_job (or DJ) encapsulates the common pattern of asynchronously executing longer tasks in the background.
196
+ It is a direct extraction from Shopify where the job table is responsible for a multitude of core tasks.
197
+ This gem isa topprospect fork (http://github.com/topprospect/delayed_job)
198
+ of the collectiveidea's fork (http://github.com/collectiveidea/delayed_job).
196
199
  email:
197
200
  - chris@collectiveidea.com
198
201
  - brandon@opensoul.org
@@ -206,7 +209,6 @@ files:
206
209
  - contrib/delayed_job.monitrc
207
210
  - contrib/delayed_job_multiple.monitrc
208
211
  - lib/delayed/backend/active_record.rb
209
- - lib/delayed/backend/active_record.rb.orig
210
212
  - lib/delayed/backend/base.rb
211
213
  - lib/delayed/backend/couch_rest.rb
212
214
  - lib/delayed/backend/data_mapper.rb
@@ -276,10 +278,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
276
278
  requirements: []
277
279
 
278
280
  rubyforge_project:
279
- rubygems_version: 1.5.2
281
+ rubygems_version: 1.6.2
280
282
  signing_key:
281
283
  specification_version: 3
282
- summary: Database-backed asynchronous priority queue system -- Extracted from Shopify. TopProspect improvements include named queues, bundler, and more
284
+ summary: Database-backed asynchronous priority queue system -- Extracted from Shopify
283
285
  test_files:
284
286
  - spec/autoloaded/clazz.rb
285
287
  - spec/autoloaded/struct.rb
@@ -1,105 +0,0 @@
1
- require 'active_record'
2
-
3
- class ActiveRecord::Base
4
- yaml_as "tag:ruby.yaml.org,2002:ActiveRecord"
5
-
6
- def self.yaml_new(klass, tag, val)
7
- klass.find(val['attributes']['id'])
8
- rescue ActiveRecord::RecordNotFound
9
- nil
10
- end
11
-
12
- def to_yaml_properties
13
- ['@attributes']
14
- end
15
- end
16
-
17
- module Delayed
18
- module Backend
19
- module ActiveRecord
20
- # A job object that is persisted to the database.
21
- # Contains the work object as a YAML field.
22
- class Job < ::ActiveRecord::Base
23
- include Delayed::Backend::Base
24
- set_table_name :delayed_jobs
25
-
26
- before_save :set_default_run_at
27
-
28
- <<<<<<< HEAD
29
- if ::ActiveRecord::VERSION::MAJOR >= 3
30
- scope :ready_to_run, lambda {|worker_name, max_run_time|
31
- where(['(run_at <= ? AND (locked_at IS NULL OR locked_at < ?) OR locked_by = ?) AND failed_at IS NULL', db_time_now, db_time_now - max_run_time, worker_name])
32
- }
33
- scope :by_priority, order('priority ASC, run_at ASC')
34
- else
35
- named_scope :ready_to_run, lambda {|worker_name, max_run_time|
36
- {:conditions => ['queue = ? AND (run_at <= ? AND (locked_at IS NULL OR locked_at < ?) OR locked_by = ?) AND failed_at IS NULL', Worker.queue, db_time_now, db_time_now - max_run_time, worker_name]}
37
- }
38
- named_scope :by_priority, :order => 'priority ASC, run_at ASC'
39
- end
40
-
41
- =======
42
- named_scope :ready_to_run, lambda {|worker_name, max_run_time|
43
- {:conditions => ['queue = ? AND (run_at <= ? AND (locked_at IS NULL OR locked_at < ?) OR locked_by = ?) AND failed_at IS NULL', Worker.queue, db_time_now, db_time_now - max_run_time, worker_name]}
44
- }
45
- named_scope :by_priority, :order => 'priority ASC, run_at ASC'
46
-
47
- >>>>>>> 75b6e0c... added queues from the original topprospect patch, added tests for queues
48
- def self.after_fork
49
- ::ActiveRecord::Base.connection.reconnect!
50
- end
51
-
52
- # When a worker is exiting, make sure we don't have any locked jobs.
53
- def self.clear_locks!(worker_name)
54
- update_all("locked_by = null, locked_at = null", ["locked_by = ?", worker_name])
55
- end
56
-
57
- # Find a few candidate jobs to run (in case some immediately get locked by others).
58
- def self.find_available(worker_name, limit = 5, max_run_time = Worker.max_run_time)
59
- scope = self.ready_to_run(worker_name, max_run_time)
60
- scope = scope.scoped(:conditions => ['priority >= ?', Worker.min_priority]) if Worker.min_priority
61
- scope = scope.scoped(:conditions => ['priority <= ?', Worker.max_priority]) if Worker.max_priority
62
-
63
- ::ActiveRecord::Base.silence do
64
- scope.by_priority.all(:limit => limit)
65
- end
66
- end
67
-
68
- # Lock this job for this worker.
69
- # Returns true if we have the lock, false otherwise.
70
- def lock_exclusively!(max_run_time, worker)
71
- now = self.class.db_time_now
72
- affected_rows = if locked_by != worker
73
- # We don't own this job so we will update the locked_by name and the locked_at
74
- 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])
75
- else
76
- # We already own this job, this may happen if the job queue crashes.
77
- # Simply resume and update the locked_at
78
- self.class.update_all(["locked_at = ?", now], ["id = ? and locked_by = ?", id, worker])
79
- end
80
- if affected_rows == 1
81
- self.locked_at = now
82
- self.locked_by = worker
83
- return true
84
- else
85
- return false
86
- end
87
- end
88
-
89
- # Get the current time (GMT or local depending on DB)
90
- # Note: This does not ping the DB to get the time, so all your clients
91
- # must have syncronized clocks.
92
- def self.db_time_now
93
- if Time.zone
94
- Time.zone.now
95
- elsif ::ActiveRecord::Base.default_timezone == :utc
96
- Time.now.utc
97
- else
98
- Time.now
99
- end
100
- end
101
-
102
- end
103
- end
104
- end
105
- end