resque-rate_limited_queue 0.0.34 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +63 -7
- data/lib/resque-rate_limited_queue/version.rb +1 -1
- data/lib/resque/plugins/rate_limited_queue/apis/angellist_queue.rb +1 -1
- data/lib/resque/plugins/rate_limited_queue/apis/evernote_queue.rb +1 -1
- data/lib/resque/plugins/rate_limited_queue/apis/twitter_queue.rb +1 -1
- data/lib/resque/plugins/rate_limited_queue/rate_limited_queue.rb +1 -1
- data/lib/resque/plugins/rate_limited_queue/rate_limited_un_pause.rb +1 -0
- data/spec/apis/angellist_queue_spec.rb +1 -1
- data/spec/apis/evernote_queue_spec.rb +1 -1
- data/spec/apis/twitter_queue_spec.rb +1 -1
- data/spec/rate_limited_queue_spec.rb +25 -3
- data/spec/rate_limited_un_pause_spec.rb +11 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0adf19f43b30aaaa865beda17e99e2082b5f6301
|
4
|
+
data.tar.gz: 7260656ade9a2e129ccf07ac137ecd5c010aee45
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c978c05cc91e3c24d0a685af044e0f2791bff20b08f864a4d12722ab7a9779d94cdef347c242c6cf749eec99b45bb223204b65489afa1e9ae017d72459dc50c9
|
7
|
+
data.tar.gz: 0c6b146eedb305a0522bf920b69600c8339e9e23c62e8ecaaf5d8be9019f1184d0aa60fdf2122ee797716b493fa203c181412e0ff660f8ee3f21ffed5c777d90
|
data/README.md
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# Resque Rate Limited Queue
|
2
2
|
|
3
|
-
PLEASE NOTE THIS IS NOW SUITABLE FOR TRIAL USE - I EXPECT TO RELEASE A STABLE VERSION IN EARLY JAN 2015
|
4
|
-
|
5
3
|
A Resque plugin which makes handling jobs that use rate limited apis easier
|
6
4
|
|
7
5
|
If you have a series of jobs in a queue, this gem will pause the queue when one of the jobs hits a rate limit, and re-start the queue when the rate limit has expired.
|
@@ -44,13 +42,13 @@ Queues can be unpaused in two ways.
|
|
44
42
|
|
45
43
|
The most elegant is using [resque-scheduler](https://github.com/resque/resque-scheduler), this works well as long as you aren't running on a platform like heroku which requires a dedicated worker to run the resque-scheduler.
|
46
44
|
|
47
|
-
To tell the gem to use resque-scheduler you need to include
|
45
|
+
To tell the gem to use `resque-scheduler` you need to include it in your Gemfile - and also let the gem know which queue to use to schedule the unpause job (make sure this isn't a queue that could get paused). Put this in an initializer.
|
48
46
|
|
49
47
|
```ruby
|
50
48
|
Resque::Plugins::RateLimitedQueue::UnPause.queue = :my_queue
|
51
49
|
```
|
52
50
|
|
53
|
-
Please see the section below on how to unpause on heroku as an alternative. If you don't install resque-scheduler AND configure the queue, then the gem will not schedule unpause jobs this way.
|
51
|
+
Please see the section below on how to unpause on heroku as an alternative. If you don't install `resque-scheduler` AND configure the queue, then the gem will not schedule unpause jobs this way.
|
54
52
|
|
55
53
|
#### Workers
|
56
54
|
Queues are paused by renaming them, so a resque queue called 'twitter\_api' will be renamed 'twitter\_api\_paused' when it hits a rate limit. Of course this will only work if your resque workers are not also taking jobs from the 'twitter\_api\_paused' queue. So your worker commands need to look like:
|
@@ -115,7 +113,7 @@ class MyApiJob
|
|
115
113
|
def self.perform(*params)
|
116
114
|
do_api_stuff
|
117
115
|
rescue MyApiRateLimit
|
118
|
-
|
116
|
+
pause_until(Time.now + WAIT_TIME, name)
|
119
117
|
rate_limited_requeue(self, *params)
|
120
118
|
end
|
121
119
|
|
@@ -136,13 +134,62 @@ class MyApiQueue < Resque::Plugins::RateLimitedQueue::BaseApiQueue
|
|
136
134
|
def self.perform(klass, *params)
|
137
135
|
super
|
138
136
|
rescue MyApiRateLimit
|
139
|
-
|
137
|
+
pause_until(Time.now + WAIT_TIME, name)
|
140
138
|
rate_limited_requeue(self, klass, *params)
|
141
139
|
end
|
142
140
|
end
|
143
141
|
````
|
144
142
|
If you do this - please contribute - and I'll add to the gem.
|
145
143
|
|
144
|
+
## Development Documentation
|
145
|
+
All the functions are class methods
|
146
|
+
|
147
|
+
```ruby
|
148
|
+
rate_limited_enqueue(klass, *params)
|
149
|
+
rate_limited_requeue(klass, *params)
|
150
|
+
````
|
151
|
+
Queue the job specified to the resque queue specified by `@queue`. `rate_limited_requeue` is intended for use when you need the job to be pushed back to the queue; it just calls `rate_limited_queue`, but they are split to make testing with stubs easier.
|
152
|
+
|
153
|
+
```ruby
|
154
|
+
pause
|
155
|
+
````
|
156
|
+
Pauses the queue specified by `@queue`, if it is not already paused.
|
157
|
+
In most cases you should call `pause_until` to pause a queue when you hit a rate limit.
|
158
|
+
|
159
|
+
```ruby
|
160
|
+
un_pause
|
161
|
+
````
|
162
|
+
Un-pauses the queue specified by `@queue`, if it is paused.
|
163
|
+
|
164
|
+
```ruby
|
165
|
+
pause_until(timestamp)
|
166
|
+
````
|
167
|
+
Pauses the queue (specified by `@queue`) and then queues a job to unpause the queue specified by `@queue`, using resque-scheduler to the queue specified by `Resque::Plugins::RateLimitedQueue::UnPause.queue` at the timestamp specified.
|
168
|
+
If `resque-schedule` is not included, or `UnPause.queue` isn't specified this will just pause the queue.
|
169
|
+
|
170
|
+
This is the prefered function to call when you hit a rate limit, since it with work regardless of the unpause method used by the application.
|
171
|
+
|
172
|
+
```ruby
|
173
|
+
paused?
|
174
|
+
````
|
175
|
+
This returns true or false to indicate wheher the queue is paused. Be aware that the queue state could change get after the call returns, but before your code executes. Use `with_lock` if you need to avoid this.
|
176
|
+
|
177
|
+
```ruby
|
178
|
+
paused_queue_name
|
179
|
+
````
|
180
|
+
Returns the name of the queue when it is paused.
|
181
|
+
|
182
|
+
```ruby
|
183
|
+
with_lock(&block)
|
184
|
+
````
|
185
|
+
Takes ownership of the PauseQueue semaphor before executing the block passed. Useful if you need to test the state of the queue and take some action without the state changing.
|
186
|
+
|
187
|
+
```ruby
|
188
|
+
find_class(klass)
|
189
|
+
````
|
190
|
+
Takes the parameter passed, and if it's a string class name, tries to turn it into a class.
|
191
|
+
|
192
|
+
|
146
193
|
## Contributing
|
147
194
|
|
148
195
|
1. Fork it ( https://github.com/[my-github-username]/resque_rate_limited_queue/fork )
|
@@ -151,7 +198,16 @@ If you do this - please contribute - and I'll add to the gem.
|
|
151
198
|
4. Push to the branch (`git push origin my-new-feature`)
|
152
199
|
5. Create a new Pull Request
|
153
200
|
|
201
|
+
|
202
|
+
## Version history
|
203
|
+
|
204
|
+
0.0.x Mostly pre-release versions
|
205
|
+
|
206
|
+
1.0.0 First release version. Breaking change - renamed `pause_for` to be `pause_until` to better reflect function
|
207
|
+
|
208
|
+
|
209
|
+
|
154
210
|
## Final thoughts
|
155
|
-
Thanks to [Dominic](https://github.com/dominicsayers) for idea of renaming the redis key - and the sample
|
211
|
+
Thanks to [Dominic](https://github.com/dominicsayers) for idea of renaming the redis key - and the sample code that does this.
|
156
212
|
|
157
213
|
This is my first gem - so please forgive any errors - and feedback very welcome
|
@@ -9,7 +9,7 @@ module Resque
|
|
9
9
|
def self.perform(klass, *params)
|
10
10
|
super
|
11
11
|
rescue Evernote::EDAM::Error::EDAMSystemException => e
|
12
|
-
|
12
|
+
pause_until(Time.now + 60 * e.rateLimitDuration.seconds)
|
13
13
|
rate_limited_requeue(self, klass, *params)
|
14
14
|
end
|
15
15
|
end
|
@@ -10,7 +10,7 @@ module Resque
|
|
10
10
|
super
|
11
11
|
rescue Twitter::Error::TooManyRequests,
|
12
12
|
Twitter::Error::EnhanceYourCalm => e
|
13
|
-
|
13
|
+
pause_until(Time.now + e.rate_limit.reset_in)
|
14
14
|
rate_limited_requeue(self, klass, *params)
|
15
15
|
end
|
16
16
|
end
|
@@ -41,7 +41,7 @@ describe Resque::Plugins::RateLimitedQueue::AngellistQueue do
|
|
41
41
|
Resque::Plugins::RateLimitedQueue::AngellistQueue.stub(:rate_limited_requeue)
|
42
42
|
end
|
43
43
|
it 'pauses queue when request fails' do
|
44
|
-
Resque::Plugins::RateLimitedQueue::AngellistQueue.should_receive(:
|
44
|
+
Resque::Plugins::RateLimitedQueue::AngellistQueue.should_receive(:pause_until)
|
45
45
|
Resque::Plugins::RateLimitedQueue::AngellistQueue
|
46
46
|
.enqueue(RateLimitedTestQueueAL, false)
|
47
47
|
end
|
@@ -46,7 +46,7 @@ describe Resque::Plugins::RateLimitedQueue::EvernoteQueue do
|
|
46
46
|
Resque::Plugins::RateLimitedQueue::EvernoteQueue.stub(:rate_limited_requeue)
|
47
47
|
end
|
48
48
|
it 'pauses queue when request fails' do
|
49
|
-
Resque::Plugins::RateLimitedQueue::EvernoteQueue.should_receive(:
|
49
|
+
Resque::Plugins::RateLimitedQueue::EvernoteQueue.should_receive(:pause_until)
|
50
50
|
Resque::Plugins::RateLimitedQueue::EvernoteQueue
|
51
51
|
.enqueue(RateLimitedTestQueueEn, false)
|
52
52
|
end
|
@@ -42,7 +42,7 @@ describe Resque::Plugins::RateLimitedQueue::TwitterQueue do
|
|
42
42
|
Resque::Plugins::RateLimitedQueue::TwitterQueue.stub(:rate_limited_requeue)
|
43
43
|
end
|
44
44
|
it 'pauses queue when request fails' do
|
45
|
-
Resque::Plugins::RateLimitedQueue::TwitterQueue.should_receive(:
|
45
|
+
Resque::Plugins::RateLimitedQueue::TwitterQueue.should_receive(:pause_until)
|
46
46
|
Resque::Plugins::RateLimitedQueue::TwitterQueue
|
47
47
|
.enqueue(RateLimitedTestQueueTw, false)
|
48
48
|
end
|
@@ -72,20 +72,20 @@ describe Resque::Plugins::RateLimitedQueue do
|
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
75
|
-
describe '
|
75
|
+
describe 'pause_until' do
|
76
76
|
before do
|
77
77
|
Resque.redis.stub(:renamenx).and_return(true)
|
78
78
|
end
|
79
79
|
|
80
80
|
it 'should pause the queue' do
|
81
81
|
RateLimitedTestQueue.should_receive(:pause)
|
82
|
-
RateLimitedTestQueue.
|
82
|
+
RateLimitedTestQueue.pause_until(Time.now + (5 * 60 * 60))
|
83
83
|
end
|
84
84
|
|
85
85
|
it 'should schedule an unpause job' do
|
86
86
|
Resque::Plugins::RateLimitedQueue::UnPause.should_receive(:enqueue)
|
87
87
|
.with(nil, 'RateLimitedTestQueue')
|
88
|
-
RateLimitedTestQueue.
|
88
|
+
RateLimitedTestQueue.pause_until(nil)
|
89
89
|
end
|
90
90
|
end
|
91
91
|
end
|
@@ -174,4 +174,26 @@ describe Resque::Plugins::RateLimitedQueue do
|
|
174
174
|
end
|
175
175
|
end
|
176
176
|
end
|
177
|
+
|
178
|
+
describe 'paused?' do
|
179
|
+
context 'with paused queue' do
|
180
|
+
before do
|
181
|
+
Resque.redis.stub(:exists).and_return(true)
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'should return the true if the paused queue exists' do
|
185
|
+
expect(RateLimitedTestQueue.paused?).to eq(true)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
context 'with un paused queue' do
|
190
|
+
before do
|
191
|
+
Resque.redis.stub(:exists).and_return(false)
|
192
|
+
end
|
193
|
+
|
194
|
+
it 'should return the false if the paused queue does not exist' do
|
195
|
+
expect(RateLimitedTestQueue.paused?).to eq(false)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
177
199
|
end
|
@@ -35,4 +35,15 @@ describe Resque::Plugins::RateLimitedQueue::UnPause do
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
+
describe 'class_from_string' do
|
39
|
+
it 'converts unqualified classes' do
|
40
|
+
expect(Resque::Plugins::RateLimitedQueue::UnPause.class_from_string(RateLimitedTestQueue.to_s))
|
41
|
+
.to eq(RateLimitedTestQueue)
|
42
|
+
end
|
43
|
+
it 'converts qualified classes' do
|
44
|
+
expect(Resque::Plugins::RateLimitedQueue::UnPause.class_from_string(Resque::Plugins::RateLimitedQueue::UnPause.to_s))
|
45
|
+
.to eq(Resque::Plugins::RateLimitedQueue::UnPause)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
38
49
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: resque-rate_limited_queue
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Greg Dowling
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-12-
|
11
|
+
date: 2014-12-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: resque
|