resque-concurrent-restriction 0.5.8 → 0.5.9

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,9 @@
1
+ 0.5.9 (06/04/2013)
2
+ ------------------
3
+
4
+ Lower slice-size used during "reset_restrictions" from 100K to 10K (it was causing segfaults when testing) <b9a7b57>
5
+ Merge pull request #5 from jzaleski/stash_restrictions_more_aggressively <a0c051f>
6
+
1
7
  0.5.8 (06/07/2012)
2
8
  ------------------
3
9
 
@@ -7,6 +7,10 @@
7
7
  # # How many times to try to get a lock before giving up
8
8
  # # Worker stays busy for: 2^tries * rand(100) * 0.001 (~30s-3000s)
9
9
  # config.lock_tries = 10
10
+ # # Try this many times to reserve a job from a queue. Also, the maximum
11
+ # # number of jobs to move to the restricted queue during this process
12
+ # # before giving up
13
+ # config.reserve_queued_job_attempts = 10
10
14
  # # Try to pick jobs off of the restricted queue before normal queues
11
15
  # config.restricted_before_queued = true
12
16
  # end
@@ -18,12 +22,13 @@ module Resque
18
22
  # Allows configuring via class accessors
19
23
  class << self
20
24
  # optional
21
- attr_accessor :lock_timeout, :lock_tries, :restricted_before_queued
25
+ attr_accessor :lock_timeout, :lock_tries, :reserve_queued_job_attempts, :restricted_before_queued
22
26
  end
23
27
 
24
28
  # default values
25
29
  self.lock_timeout = 60
26
30
  self.lock_tries = 15
31
+ self.reserve_queued_job_attempts = 1
27
32
  self.restricted_before_queued = false
28
33
 
29
34
  # Allows configuring via class accessors
@@ -443,14 +448,14 @@ module Resque
443
448
  counts_reset = 0
444
449
  count_keys = Resque.redis.keys("concurrent.count.*")
445
450
  if count_keys.size > 0
446
- count_keys.each_slice(100000) do |key_slice|
451
+ count_keys.each_slice(10000) do |key_slice|
447
452
  counts_reset += Resque.redis.del(*key_slice)
448
453
  end
449
454
  end
450
455
 
451
456
  runnable_keys = Resque.redis.keys("concurrent.runnable*")
452
457
  if runnable_keys.size > 0
453
- runnable_keys.each_slice(100000) do |runnable_slice|
458
+ runnable_keys.each_slice(10000) do |runnable_slice|
454
459
  Resque.redis.del(*runnable_slice)
455
460
  end
456
461
  end
@@ -67,23 +67,27 @@ module Resque
67
67
  end
68
68
 
69
69
  def get_queued_job(queue)
70
- resque_job = reserve_without_restriction(queue)
70
+ # Bounded retry
71
+ 1.upto(ConcurrentRestriction.reserve_queued_job_attempts) do |i|
72
+ resque_job = reserve_without_restriction(queue)
71
73
 
72
- if resque_job
73
- # If there is a job on regular queues, then only run it if its not restricted
74
+ # Short-curcuit if a job was not found
75
+ return if resque_job.nil?
74
76
 
77
+ # If there is a job on regular queues, then only run it if its not restricted
75
78
  job_class = resque_job.payload_class
76
79
  job_args = resque_job.args
77
80
 
78
- # return to work on job if not a restricted job
79
- if job_class.is_a?(ConcurrentRestriction)
80
- # Move on to next if job is restricted
81
- # If job is runnable, we keep the lock until done_working
82
- resque_job = nil if job_class.stash_if_restricted(resque_job)
83
- end
81
+ # Return to work on job if not a restricted job
82
+ return resque_job unless job_class.is_a?(ConcurrentRestriction)
83
+
84
+ # Keep trying if job is restricted. If job is runnable, we keep the lock until
85
+ # done_working
86
+ return resque_job unless job_class.stash_if_restricted(resque_job)
84
87
  end
85
88
 
86
- return resque_job
89
+ # Safety net, here in case we hit the upper bound and there are still queued items
90
+ return nil
87
91
  end
88
92
 
89
93
  end
@@ -1,7 +1,7 @@
1
1
  module Resque
2
2
  module Plugins
3
3
  module ConcurrentRestriction
4
- VERSION = "0.5.8"
4
+ VERSION = "0.5.9"
5
5
  end
6
6
  end
7
7
  end
@@ -28,6 +28,16 @@ describe Resque::Plugins::ConcurrentRestriction do
28
28
  Resque::Plugins::ConcurrentRestriction.lock_timeout.should == 60
29
29
  end
30
30
 
31
+ it "should allow setting/getting global config for reserve_queued_job_attempts" do
32
+ Resque::Plugins::ConcurrentRestriction.reserve_queued_job_attempts.should == 1
33
+ Resque::Plugins::ConcurrentRestriction.configure do |config|
34
+ config.reserve_queued_job_attempts = 5
35
+ end
36
+ Resque::Plugins::ConcurrentRestriction.reserve_queued_job_attempts.should == 5
37
+ Resque::Plugins::ConcurrentRestriction.reserve_queued_job_attempts = 3
38
+ Resque::Plugins::ConcurrentRestriction.reserve_queued_job_attempts.should == 3
39
+ end
40
+
31
41
  it "should allow setting/getting global config for restricted_before_queued" do
32
42
  Resque::Plugins::ConcurrentRestriction.restricted_before_queued.should == false
33
43
  Resque::Plugins::ConcurrentRestriction.configure do |config|
@@ -591,13 +601,13 @@ describe Resque::Plugins::ConcurrentRestriction do
591
601
  # It might be better to actually populate redis with a bunch keys but that makes the test pretty slow
592
602
 
593
603
  # we have to keep this splat limitation in mind when populating test data, too
594
- concurrent_count_keys = 200001.times.collect{ |i| ["concurrent.count.#{i}", "#{i}"] }.flatten
595
- concurrent_count_keys.each_slice(100000) do |slice|
604
+ concurrent_count_keys = 20001.times.collect{ |i| ["concurrent.count.#{i}", "#{i}"] }.flatten
605
+ concurrent_count_keys.each_slice(10000) do |slice|
596
606
  Resque.redis.mset *slice
597
607
  end
598
608
 
599
- concurrent_runnable_keys = 200001.times.collect{ |i| ["concurrent.runnable.#{i}", "#{i}"] }.flatten
600
- concurrent_runnable_keys.each_slice(100000) do |slice|
609
+ concurrent_runnable_keys = 20001.times.collect{ |i| ["concurrent.runnable.#{i}", "#{i}"] }.flatten
610
+ concurrent_runnable_keys.each_slice(10000) do |slice|
601
611
  Resque.redis.mset *slice
602
612
  end
603
613
 
@@ -605,7 +615,7 @@ describe Resque::Plugins::ConcurrentRestriction do
605
615
 
606
616
  lambda{ return_value = ConcurrentRestrictionJob.reset_restrictions }.should_not raise_exception
607
617
 
608
- return_value.should == [200001, 0]
618
+ return_value.should == [20001, 0]
609
619
  end
610
620
 
611
621
  end
@@ -259,4 +259,19 @@ describe Resque::Plugins::ConcurrentRestriction::Worker do
259
259
  RestrictionJob.total_run_count.should == 3
260
260
  end
261
261
 
262
+ it "should move multiple items to the restricted queue each iteration" do
263
+ RestrictionJob.set_running_count(RestrictionJob.tracking_key, 99)
264
+
265
+ 5.times {|i| Resque.enqueue(RestrictionJob, :queue => :normal)}
266
+ Resque.size(:normal).should == 5
267
+ RestrictionJob.restriction_queue(RestrictionJob.tracking_key, :normal).size.should == 0
268
+
269
+ Resque::Plugins::ConcurrentRestriction.reserve_queued_job_attempts = 3
270
+
271
+ run_resque_queue(:normal)
272
+ RestrictionJob.run_count.should == 0
273
+ Resque.size(:normal).should == 2
274
+ RestrictionJob.restriction_queue(RestrictionJob.tracking_key, :normal).size.should == 3
275
+ end
276
+
262
277
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: resque-concurrent-restriction
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.8
4
+ version: 0.5.9
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-07 00:00:00.000000000 Z
12
+ date: 2013-06-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: resque
@@ -135,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
135
  version: '0'
136
136
  requirements: []
137
137
  rubyforge_project: resque-concurrent-restriction
138
- rubygems_version: 1.8.21
138
+ rubygems_version: 1.8.25
139
139
  signing_key:
140
140
  specification_version: 3
141
141
  summary: A resque plugin for limiting how many of a specific job can run concurrently