resque-concurrent-restriction 0.5.2 → 0.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,32 @@
1
+ # To configure resque concurrent restriction, add something like the
2
+ # following to an initializer (defaults shown):
3
+ #
4
+ # Resque::Plugins::ConcurrentRestriction.configure do |config|
5
+ # # The lock timeout for the restriction queue lock
6
+ # config.lock_timeout = 60
7
+ # # Try to pick jobs off of the restricted queue before normal queues
8
+ # config.restricted_before_queued = true
9
+ # end
10
+
1
11
  module Resque
2
12
  module Plugins
3
13
  module ConcurrentRestriction
4
14
 
15
+ # Allows configuring via class accessors
16
+ class << self
17
+ # optional
18
+ attr_accessor :lock_timeout, :restricted_before_queued
19
+ end
20
+
21
+ # default values
22
+ self.lock_timeout = 60
23
+ self.restricted_before_queued = false
24
+
25
+ # Allows configuring via class accessors
26
+ def self.configure
27
+ yield self
28
+ end
29
+
5
30
  # Redis Data Structures
6
31
  #
7
32
  # concurrent.lock.tracking_id => timestamp
@@ -317,7 +342,7 @@ module Resque
317
342
  exp_backoff = 1
318
343
 
319
344
  while trying do
320
- lock_expiration = Time.now.to_i + 10
345
+ lock_expiration = Time.now.to_i + ConcurrentRestriction.lock_timeout
321
346
  if acquire_lock(lock_key, lock_expiration)
322
347
  begin
323
348
  yield
@@ -14,7 +14,7 @@ module Resque
14
14
  end
15
15
  end
16
16
 
17
- # Wrap reserve so we can pass the job to done_working to release restriction if neccessary
17
+ # Wrap reserve so we can pass the job to done_working to release restriction if necessary
18
18
  def reserve_with_restriction
19
19
  @job_in_progress = reserve_without_restriction
20
20
  return @job_in_progress
@@ -47,6 +47,26 @@ module Resque
47
47
  # Wrap reserve so we can move a job to restriction queue if it is restricted
48
48
  # This needs to be a class method
49
49
  def reserve_with_restriction(queue)
50
+ order = [:get_queued_job, :get_restricted_job]
51
+ order.reverse! if ConcurrentRestriction.restricted_before_queued
52
+
53
+ resque_job = nil
54
+ order.each do |m|
55
+ resque_job ||= self.send(m, queue)
56
+ end
57
+
58
+ # Return job or nil to move on to next queue if we couldn't get a job
59
+ return resque_job
60
+ end
61
+
62
+ def get_restricted_job(queue)
63
+ # Try to find a runnable job from restriction queues
64
+ # This also acquires a restriction lock, which is released in done_working
65
+ resque_job = ConcurrentRestrictionJob.next_runnable_job(queue)
66
+ return resque_job
67
+ end
68
+
69
+ def get_queued_job(queue)
50
70
  resque_job = reserve_without_restriction(queue)
51
71
 
52
72
  if resque_job
@@ -60,21 +80,10 @@ module Resque
60
80
  # Move on to next if job is restricted
61
81
  # If job is runnable, we keep the lock until done_working
62
82
  resque_job = nil if job_class.stash_if_restricted(resque_job)
63
-
64
83
  end
65
-
66
- else
67
- # if no queues have a runnable job, then try to find a
68
- # runnable job from restriction queues
69
- # This also acquires a restriction lock, which is released in done_working
70
- resque_job = ConcurrentRestrictionJob.next_runnable_job(queue)
71
-
72
- return resque_job
73
84
  end
74
85
 
75
- # Return job or nil to move on to next queue if we couldn't get a job
76
86
  return resque_job
77
-
78
87
  end
79
88
 
80
89
  end
@@ -1,7 +1,7 @@
1
1
  module Resque
2
2
  module Plugins
3
3
  module ConcurrentRestriction
4
- VERSION = "0.5.2"
4
+ VERSION = "0.5.4"
5
5
  end
6
6
  end
7
7
  end
@@ -9,12 +9,36 @@ describe Resque::Plugins::ConcurrentRestriction do
9
9
 
10
10
  after(:each) do
11
11
  Resque.redis.lrange("failed", 0, -1).size.should == 0
12
+ Resque.redis.get("stat:failed").to_i.should == 0
12
13
  end
13
14
 
14
15
  it "should follow the convention" do
15
16
  Resque::Plugin.lint(Resque::Plugins::ConcurrentRestrictionJob)
16
17
  end
17
18
 
19
+ context "settings" do
20
+
21
+ it "should allow setting/getting global config for lock_timeout" do
22
+ Resque::Plugins::ConcurrentRestriction.lock_timeout.should == 60
23
+ Resque::Plugins::ConcurrentRestriction.configure do |config|
24
+ config.lock_timeout = 61
25
+ end
26
+ Resque::Plugins::ConcurrentRestriction.lock_timeout.should == 61
27
+ Resque::Plugins::ConcurrentRestriction.lock_timeout = 60
28
+ Resque::Plugins::ConcurrentRestriction.lock_timeout.should == 60
29
+ end
30
+
31
+ it "should allow setting/getting global config for restricted_before_queued" do
32
+ Resque::Plugins::ConcurrentRestriction.restricted_before_queued.should == false
33
+ Resque::Plugins::ConcurrentRestriction.configure do |config|
34
+ config.restricted_before_queued = true
35
+ end
36
+ Resque::Plugins::ConcurrentRestriction.restricted_before_queued.should == true
37
+ Resque::Plugins::ConcurrentRestriction.restricted_before_queued = false
38
+ Resque::Plugins::ConcurrentRestriction.restricted_before_queued.should == false
39
+ end
40
+
41
+ end
18
42
 
19
43
  context "keys" do
20
44
  it "should always contain the classname in tracking_key" do
@@ -180,7 +204,6 @@ describe Resque::Plugins::ConcurrentRestriction do
180
204
  ConcurrentRestrictionJob.restricted?(ConcurrentRestrictionJob.tracking_key).should == false
181
205
  ConcurrentRestrictionJob.set_running_count(ConcurrentRestrictionJob.tracking_key, 1)
182
206
  ConcurrentRestrictionJob.restricted?(ConcurrentRestrictionJob.tracking_key).should == true
183
-
184
207
  end
185
208
 
186
209
  end
@@ -9,6 +9,7 @@ describe Resque::Plugins::ConcurrentRestriction::Worker do
9
9
 
10
10
  after(:each) do
11
11
  Resque.redis.lrange("failed", 0, -1).size.should == 0
12
+ Resque.redis.get("stat:failed").to_i.should == 0
12
13
  end
13
14
 
14
15
  it "should do nothing for no jobs" do
@@ -58,6 +59,8 @@ describe Resque::Plugins::ConcurrentRestriction::Worker do
58
59
  end
59
60
 
60
61
  it "should prefer running a normal job over one on restriction queue" do
62
+ Resque::Plugins::ConcurrentRestriction.restricted_before_queued.should == false
63
+
61
64
  RestrictionJob.set_running_count(RestrictionJob.tracking_key, 99)
62
65
 
63
66
  run_resque_job(RestrictionJob, :queue => :normal)
@@ -74,6 +77,32 @@ describe Resque::Plugins::ConcurrentRestriction::Worker do
74
77
  RestrictionJob.restriction_queue(RestrictionJob.tracking_key, :normal).should == []
75
78
  NoRestrictionJob.run_count.should == 1
76
79
  RestrictionJob.run_count.should == 1
80
+
81
+ end
82
+
83
+ it "should prefer running a restricted job over normal one when option given" do
84
+ begin
85
+ Resque::Plugins::ConcurrentRestriction.restricted_before_queued = true
86
+
87
+ RestrictionJob.set_running_count(RestrictionJob.tracking_key, 99)
88
+
89
+ run_resque_job(RestrictionJob, :queue => :normal)
90
+ RestrictionJob.run_count.should == 0
91
+
92
+ RestrictionJob.set_running_count(RestrictionJob.tracking_key, 0)
93
+
94
+ run_resque_job(NoRestrictionJob, :queue => :normal)
95
+ RestrictionJob.restriction_queue(RestrictionJob.tracking_key, :normal).should == []
96
+ NoRestrictionJob.run_count.should == 0
97
+ RestrictionJob.run_count.should == 1
98
+
99
+ run_resque_queue(:normal)
100
+ RestrictionJob.restriction_queue(RestrictionJob.tracking_key, :normal).should == []
101
+ NoRestrictionJob.run_count.should == 1
102
+ RestrictionJob.run_count.should == 1
103
+ ensure
104
+ Resque::Plugins::ConcurrentRestriction.restricted_before_queued = false
105
+ end
77
106
  end
78
107
 
79
108
  it "should be able to run multiple restricted jobs in a row without exceeding restriction" do
@@ -154,6 +183,7 @@ describe Resque::Plugins::ConcurrentRestriction::Worker do
154
183
  Resque.redis.lrange("failed", 0, -1).size.should == 1
155
184
  ConcurrentRestrictionJob.running_count(ConcurrentRestrictionJob.tracking_key).should == 0
156
185
  Resque.redis.del("failed")
186
+ Resque.redis.del("stat:failed")
157
187
  end
158
188
 
159
189
  it "should handle jobs with custom restriction identifier" do
metadata CHANGED
@@ -1,61 +1,57 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: resque-concurrent-restriction
3
- version: !ruby/object:Gem::Version
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.4
4
5
  prerelease:
5
- version: 0.5.2
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Matt Conway
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
-
13
- date: 2011-04-11 00:00:00 -04:00
12
+ date: 2011-08-26 00:00:00.000000000 -04:00
14
13
  default_executable:
15
- dependencies:
16
- - !ruby/object:Gem::Dependency
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
17
16
  name: resque
18
- prerelease: false
19
- requirement: &id001 !ruby/object:Gem::Requirement
17
+ requirement: &2168987840 !ruby/object:Gem::Requirement
20
18
  none: false
21
- requirements:
19
+ requirements:
22
20
  - - ~>
23
- - !ruby/object:Gem::Version
24
- version: "1.10"
21
+ - !ruby/object:Gem::Version
22
+ version: '1.10'
25
23
  type: :runtime
26
- version_requirements: *id001
27
- - !ruby/object:Gem::Dependency
28
- name: rspec
29
24
  prerelease: false
30
- requirement: &id002 !ruby/object:Gem::Requirement
25
+ version_requirements: *2168987840
26
+ - !ruby/object:Gem::Dependency
27
+ name: rspec
28
+ requirement: &2168987340 !ruby/object:Gem::Requirement
31
29
  none: false
32
- requirements:
30
+ requirements:
33
31
  - - ~>
34
- - !ruby/object:Gem::Version
35
- version: "2.5"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.5'
36
34
  type: :development
37
- version_requirements: *id002
38
- - !ruby/object:Gem::Dependency
39
- name: awesome_print
40
35
  prerelease: false
41
- requirement: &id003 !ruby/object:Gem::Requirement
36
+ version_requirements: *2168987340
37
+ - !ruby/object:Gem::Dependency
38
+ name: awesome_print
39
+ requirement: &2168986960 !ruby/object:Gem::Requirement
42
40
  none: false
43
- requirements:
44
- - - ">="
45
- - !ruby/object:Gem::Version
46
- version: "0"
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
47
45
  type: :development
48
- version_requirements: *id003
46
+ prerelease: false
47
+ version_requirements: *2168986960
49
48
  description: A resque plugin for limiting how many of a specific job can run concurrently
50
- email:
49
+ email:
51
50
  - matt@conwaysplace.com
52
51
  executables: []
53
-
54
52
  extensions: []
55
-
56
53
  extra_rdoc_files: []
57
-
58
- files:
54
+ files:
59
55
  - .gitignore
60
56
  - Gemfile
61
57
  - LICENSE
@@ -74,32 +70,29 @@ files:
74
70
  has_rdoc: true
75
71
  homepage: http://github.com/wr0ngway/resque-concurrent-restriction
76
72
  licenses: []
77
-
78
73
  post_install_message:
79
74
  rdoc_options: []
80
-
81
- require_paths:
75
+ require_paths:
82
76
  - lib
83
- required_ruby_version: !ruby/object:Gem::Requirement
77
+ required_ruby_version: !ruby/object:Gem::Requirement
84
78
  none: false
85
- requirements:
86
- - - ">="
87
- - !ruby/object:Gem::Version
88
- version: "0"
89
- required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
84
  none: false
91
- requirements:
92
- - - ">="
93
- - !ruby/object:Gem::Version
94
- version: "0"
85
+ requirements:
86
+ - - ! '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
95
89
  requirements: []
96
-
97
90
  rubyforge_project: resque-concurrent-restriction
98
- rubygems_version: 1.6.1
91
+ rubygems_version: 1.6.2
99
92
  signing_key:
100
93
  specification_version: 3
101
94
  summary: A resque plugin for limiting how many of a specific job can run concurrently
102
- test_files:
95
+ test_files:
103
96
  - spec/concurrent_restriction_job_spec.rb
104
97
  - spec/redis-test.conf
105
98
  - spec/resque_worker_extensions_spec.rb