resque-restriction 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,2 +1,4 @@
1
1
  spec/dump.rdb
2
2
  pkg/**
3
+ .idea
4
+
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.1
1
+ 0.2.2
@@ -4,12 +4,28 @@ module Resque
4
4
  alias_method :origin_reserve, :reserve
5
5
 
6
6
  def reserve(queue)
7
- if queue == 'restriction' && payload = Resque.pop(queue)
8
- constantize(payload['class']).repush(*payload['args'])
9
- return
7
+ if queue =~ /^#{Plugins::Restriction::RESTRICTION_QUEUE_PREFIX}/
8
+ # If processing the restriction queue, when poping and pushing to end,
9
+ # we can't tell when we reach the original one, so just walk the length
10
+ # of the queue so we don't run infinitely long
11
+ Resque.size(queue).times do |i|
12
+ # For the job at the head of the queue, repush to restricition queue
13
+ # if still restricted, otherwise we have a runnable job, so create it
14
+ # and return
15
+ payload = Resque.pop(queue)
16
+ if payload
17
+ if ! constantize(payload['class']).repush(*payload['args'])
18
+ return new(queue, payload)
19
+ end
20
+ end
21
+ end
22
+ return nil
23
+ else
24
+ # drop through to original Job::Reserve if not restriction queue
25
+ origin_reserve(queue)
10
26
  end
11
- origin_reserve(queue)
12
27
  end
28
+
13
29
  end
14
30
  end
15
31
  end
@@ -9,6 +9,7 @@ module Resque
9
9
  :per_month => 31*24*60*60,
10
10
  :per_year => 366*24*60*60
11
11
  }
12
+ RESTRICTION_QUEUE_PREFIX = 'restriction'
12
13
 
13
14
  def settings
14
15
  @options ||= {}
@@ -40,7 +41,7 @@ module Resque
40
41
  # reincrement the keys if one of the periods triggers DontPerform so
41
42
  # that we accurately track capacity
42
43
  keys_decremented.each {|k| Resque.redis.incrby(k, 1) }
43
- Resque.push "restriction", :class => to_s, :args => args
44
+ Resque.push restriction_queue_name, :class => to_s, :args => args
44
45
  raise Resque::Job::DontPerform
45
46
  end
46
47
  end
@@ -72,6 +73,11 @@ module Resque
72
73
  self.to_s
73
74
  end
74
75
 
76
+ def restriction_queue_name
77
+ queue_name = Resque.queue_from_class(self)
78
+ "#{RESTRICTION_QUEUE_PREFIX}_#{queue_name}"
79
+ end
80
+
75
81
  def seconds(period)
76
82
  if SECONDS.keys.include? period
77
83
  SECONDS[period]
@@ -80,18 +86,23 @@ module Resque
80
86
  end
81
87
  end
82
88
 
89
+ # if job is still restricted, push back to restriction queue, otherwise push
90
+ # to real queue. Since the restrictions will be checked again when run from
91
+ # real queue, job will just get pushed back onto restriction queue then if
92
+ # restriction conditions have changed
83
93
  def repush(*args)
84
- no_restrictions = true
85
- queue_name = Resque.queue_from_class(self)
94
+ has_restrictions = false
86
95
  settings.each do |period, number|
87
96
  key = redis_key(period, *args)
88
97
  value = Resque.redis.get(key)
89
- no_restrictions &&= (value.nil? or value == "" or value.to_i > 0)
98
+ has_restrictions = value && value != "" && value.to_i <= 0
99
+ break if has_restrictions
90
100
  end
91
- if no_restrictions
92
- Resque.push queue_name, :class => to_s, :args => args
101
+ if has_restrictions
102
+ Resque.push restriction_queue_name, :class => to_s, :args => args
103
+ return true
93
104
  else
94
- Resque.push "restriction", :class => to_s, :args => args
105
+ return false
95
106
  end
96
107
  end
97
108
 
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{resque-restriction}
8
- s.version = "0.2.1"
8
+ s.version = "0.2.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Richard Huang"]
12
- s.date = %q{2010-07-10}
12
+ s.date = %q{2010-09-09}
13
13
  s.description = %q{resque-restriction is an extension to resque queue system that restricts the execution number of certain jobs in a period time, the exceeded jobs will be executed at the next period.}
14
14
  s.email = %q{flyerhzm@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -1,20 +1,22 @@
1
1
  require File.join(File.dirname(__FILE__) + '/../spec_helper')
2
2
 
3
3
  describe Resque::Job do
4
- it "should repush restriction queue when reserve" do
4
+ before(:each) do
5
5
  Resque.redis.flushall
6
- Resque.push('restriction', :class => 'OneHourRestrictionJob', :args => ['any args'])
7
- Resque::Job.reserve('restriction').should be_nil
8
- Resque::Job.reserve('normal').should == Resque::Job.new('normal', {'class' => 'OneHourRestrictionJob', 'args' => ['any args']})
6
+ end
7
+
8
+ it "should repush restriction queue when reserve" do
9
+ Resque.push('restriction_normal', :class => 'OneHourRestrictionJob', :args => ['any args'])
10
+ Resque::Job.reserve('restriction_normal').should == Resque::Job.new('restriction_normal', {'class' => 'OneHourRestrictionJob', 'args' => ['any args']})
11
+ Resque::Job.reserve('restriction_normal').should be_nil
9
12
  Resque::Job.reserve('normal').should be_nil
10
13
  end
11
14
 
12
15
  it "should push back to restriction queue when still restricted" do
13
- Resque.redis.flushall
14
16
  Resque.redis.set(OneHourRestrictionJob.redis_key(:per_hour), -1)
15
- Resque.push('restriction', :class => 'OneHourRestrictionJob', :args => ['any args'])
16
- Resque::Job.reserve('restriction').should be_nil
17
- Resque.pop('restriction').should == {'class' => 'OneHourRestrictionJob', 'args' => ['any args']}
17
+ Resque.push('restriction_normal', :class => 'OneHourRestrictionJob', :args => ['any args'])
18
+ Resque::Job.reserve('restriction_normal').should be_nil
19
+ Resque.pop('restriction_normal').should == {'class' => 'OneHourRestrictionJob', 'args' => ['any args']}
18
20
  Resque::Job.reserve('normal').should be_nil
19
21
  end
20
22
 
@@ -22,5 +24,16 @@ describe Resque::Job do
22
24
  Resque.push('normal', :class => 'OneHourRestrictionJob', :args => ['any args'])
23
25
  Resque::Job.reserve('normal').should == Resque::Job.new('normal', {'class' => 'OneHourRestrictionJob', 'args' => ['any args']})
24
26
  Resque::Job.reserve('normal').should be_nil
27
+ Resque::Job.reserve('restriction_normal').should be_nil
25
28
  end
29
+
30
+ it "should only push back queue_length times to restriction queue" do
31
+ Resque.redis.set(OneHourRestrictionJob.redis_key(:per_hour), -1)
32
+ 3.times { Resque.push('restriction_normal', :class => 'OneHourRestrictionJob', :args => ['any args']) }
33
+ Resque.size('restriction_normal').should == 3
34
+ OneHourRestrictionJob.should_receive(:repush).exactly(3).times.and_return(true)
35
+ Resque::Job.reserve('restriction_normal')
36
+ end
37
+
38
+
26
39
  end
@@ -82,7 +82,7 @@ describe Resque::Plugins::RestrictionJob do
82
82
  result = perform_job(OneHourRestrictionJob, "any args")
83
83
  result.should_not be_true
84
84
  Resque.redis.get(OneHourRestrictionJob.redis_key(:per_hour)).should == "0"
85
- Resque.redis.lrange("queue:restriction", 0, -1).should == [Resque.encode(:class => "OneHourRestrictionJob", :args => ["any args"])]
85
+ Resque.redis.lrange("queue:restriction_normal", 0, -1).should == [Resque.encode(:class => "OneHourRestrictionJob", :args => ["any args"])]
86
86
  end
87
87
 
88
88
  context "multiple restrict" do
@@ -107,5 +107,20 @@ describe Resque::Plugins::RestrictionJob do
107
107
  Resque.redis.get(MultipleRestrictionJob.redis_key(:per_300)).should == "1"
108
108
  end
109
109
  end
110
+
111
+ context "repush" do
112
+ it "should push restricted jobs onto restriction queue" do
113
+ Resque.redis.set(OneHourRestrictionJob.redis_key(:per_hour), -1)
114
+ Resque.should_receive(:push).once.with('restriction_normal', :class => 'OneHourRestrictionJob', :args => ['any args'])
115
+ OneHourRestrictionJob.repush('any args').should be_true
116
+ end
117
+
118
+ it "should not push unrestricted jobs onto restriction queue" do
119
+ Resque.redis.set(OneHourRestrictionJob.redis_key(:per_hour), 1)
120
+ Resque.should_not_receive(:push)
121
+ OneHourRestrictionJob.repush('any args').should be_false
122
+ end
123
+
124
+ end
110
125
  end
111
126
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 2
8
- - 1
9
- version: 0.2.1
8
+ - 2
9
+ version: 0.2.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Richard Huang
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-07-10 00:00:00 +08:00
17
+ date: 2010-09-09 00:00:00 +08:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency