resque-concurrent-restriction 0.5.2 → 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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