onyx-resque-retry 0.1.0
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.
- data/HISTORY.md +33 -0
- data/LICENSE +21 -0
- data/README.md +289 -0
- data/Rakefile +25 -0
- data/lib/resque-retry.rb +6 -0
- data/lib/resque-retry/server.rb +51 -0
- data/lib/resque-retry/server/views/retry.erb +48 -0
- data/lib/resque-retry/server/views/retry_timestamp.erb +59 -0
- data/lib/resque/failure/multiple_with_retry_suppression.rb +93 -0
- data/lib/resque/plugins/exponential_backoff.rb +64 -0
- data/lib/resque/plugins/retry.rb +221 -0
- data/test/exponential_backoff_test.rb +62 -0
- data/test/multiple_failure_test.rb +86 -0
- data/test/redis-test.conf +132 -0
- data/test/resque_test.rb +18 -0
- data/test/retry_criteria_test.rb +75 -0
- data/test/retry_inheriting_checks_test.rb +33 -0
- data/test/retry_test.rb +173 -0
- data/test/test_helper.rb +78 -0
- data/test/test_jobs.rb +280 -0
- metadata +189 -0
data/test/test_helper.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
dir = File.dirname(File.expand_path(__FILE__))
|
2
|
+
$LOAD_PATH.unshift dir + '/../lib'
|
3
|
+
$TESTING = true
|
4
|
+
|
5
|
+
require 'test/unit'
|
6
|
+
require 'rubygems'
|
7
|
+
require 'turn'
|
8
|
+
require 'simplecov'
|
9
|
+
|
10
|
+
SimpleCov.start do
|
11
|
+
add_filter "/test/"
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'resque-retry'
|
15
|
+
require dir + '/test_jobs'
|
16
|
+
|
17
|
+
|
18
|
+
# make sure we can run redis
|
19
|
+
if !system("which redis-server")
|
20
|
+
puts '', "** can't find `redis-server` in your path"
|
21
|
+
puts "** try running `sudo rake install`"
|
22
|
+
abort ''
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
# start our own redis when the tests start,
|
27
|
+
# kill it when they end
|
28
|
+
at_exit do
|
29
|
+
next if $!
|
30
|
+
|
31
|
+
if defined?(MiniTest)
|
32
|
+
exit_code = MiniTest::Unit.new.run(ARGV)
|
33
|
+
else
|
34
|
+
exit_code = Test::Unit::AutoRunner.run
|
35
|
+
end
|
36
|
+
|
37
|
+
pid = `ps -e -o pid,command | grep [r]edis-test`.split(" ")[0]
|
38
|
+
puts "Killing test redis server..."
|
39
|
+
`rm -f #{dir}/dump.rdb`
|
40
|
+
Process.kill("KILL", pid.to_i)
|
41
|
+
exit exit_code
|
42
|
+
end
|
43
|
+
|
44
|
+
puts "Starting redis for testing at localhost:9736..."
|
45
|
+
`redis-server #{dir}/redis-test.conf`
|
46
|
+
Resque.redis = '127.0.0.1:9736'
|
47
|
+
|
48
|
+
# Mock failure backend for testing MultipleWithRetrySuppression
|
49
|
+
class MockFailureBackend < Resque::Failure::Base
|
50
|
+
class << self
|
51
|
+
attr_accessor :errors
|
52
|
+
end
|
53
|
+
|
54
|
+
def save
|
55
|
+
self.class.errors << exception.to_s
|
56
|
+
end
|
57
|
+
|
58
|
+
self.errors = []
|
59
|
+
end
|
60
|
+
|
61
|
+
# Test helpers
|
62
|
+
class Test::Unit::TestCase
|
63
|
+
def perform_next_job(worker, &block)
|
64
|
+
return unless job = @worker.reserve
|
65
|
+
@worker.perform(job, &block)
|
66
|
+
@worker.done_working
|
67
|
+
end
|
68
|
+
|
69
|
+
def clean_perform_job(klass, *args)
|
70
|
+
Resque.redis.flushall
|
71
|
+
Resque.enqueue(klass, *args)
|
72
|
+
|
73
|
+
worker = Resque::Worker.new(:testing)
|
74
|
+
return false unless job = worker.reserve
|
75
|
+
worker.perform(job)
|
76
|
+
worker.done_working
|
77
|
+
end
|
78
|
+
end
|
data/test/test_jobs.rb
ADDED
@@ -0,0 +1,280 @@
|
|
1
|
+
CustomException = Class.new(StandardError)
|
2
|
+
HierarchyCustomException = Class.new(CustomException)
|
3
|
+
AnotherCustomException = Class.new(StandardError)
|
4
|
+
|
5
|
+
class NoRetryJob
|
6
|
+
@queue = :testing
|
7
|
+
|
8
|
+
def self.perform(*args)
|
9
|
+
raise "error"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class GoodJob
|
14
|
+
extend Resque::Plugins::Retry
|
15
|
+
@queue = :testing
|
16
|
+
def self.perform(*args)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class RetryDefaultsJob
|
21
|
+
extend Resque::Plugins::Retry
|
22
|
+
@queue = :testing
|
23
|
+
|
24
|
+
def self.perform(*args)
|
25
|
+
raise
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class JobRetryQueue
|
30
|
+
extend Resque::Plugins::Retry
|
31
|
+
@queue = :testing_retry
|
32
|
+
|
33
|
+
def self.perform(*args)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class JobWithRetryQueue
|
38
|
+
extend Resque::Plugins::Retry
|
39
|
+
@queue = :testing
|
40
|
+
@retry_job_class = JobRetryQueue
|
41
|
+
|
42
|
+
def self.perform(*args)
|
43
|
+
raise
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class DelayedJobWithRetryQueue
|
48
|
+
extend Resque::Plugins::Retry
|
49
|
+
@queue = :testing
|
50
|
+
@retry_delay = 1
|
51
|
+
@retry_job_class = JobRetryQueue
|
52
|
+
|
53
|
+
def self.perform(*args)
|
54
|
+
raise
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class InheritTestJob < RetryDefaultsJob
|
59
|
+
end
|
60
|
+
|
61
|
+
class InheritTestWithExtraJob < InheritTestJob
|
62
|
+
retry_criteria_check do |exception, *args|
|
63
|
+
false
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class InheritTestWithMoreExtraJob < InheritTestWithExtraJob
|
68
|
+
retry_criteria_check do |exception, *args|
|
69
|
+
false
|
70
|
+
end
|
71
|
+
|
72
|
+
retry_criteria_check do |exception, *args|
|
73
|
+
false
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class RetryWithModifiedArgsJob < RetryDefaultsJob
|
78
|
+
@queue = :testing
|
79
|
+
|
80
|
+
def self.args_for_retry(*args)
|
81
|
+
args.each { |arg| arg << 'bar' }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class NeverGiveUpJob < RetryDefaultsJob
|
86
|
+
@queue = :testing
|
87
|
+
@retry_limit = 0
|
88
|
+
end
|
89
|
+
|
90
|
+
class LimitThreeJob < RetryDefaultsJob
|
91
|
+
@queue = :testing
|
92
|
+
@retry_limit = 3
|
93
|
+
|
94
|
+
def self.perform(*args)
|
95
|
+
raise ArgumentError, "custom message"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
class FailFiveTimesJob < RetryDefaultsJob
|
100
|
+
@queue = :testing
|
101
|
+
@retry_limit = 6
|
102
|
+
|
103
|
+
def self.perform(*args)
|
104
|
+
raise if retry_attempt <= 4
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class ExponentialBackoffJob < RetryDefaultsJob
|
109
|
+
extend Resque::Plugins::ExponentialBackoff
|
110
|
+
@queue = :testing
|
111
|
+
end
|
112
|
+
|
113
|
+
class CustomExponentialBackoffJob
|
114
|
+
extend Resque::Plugins::ExponentialBackoff
|
115
|
+
@queue = :testing
|
116
|
+
|
117
|
+
@retry_limit = 4
|
118
|
+
@backoff_strategy = [10, 20, 30]
|
119
|
+
|
120
|
+
def self.perform(url, hook_id, hmac_key)
|
121
|
+
raise
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
class RetryCustomExceptionsJob < RetryDefaultsJob
|
126
|
+
@queue = :testing
|
127
|
+
|
128
|
+
@retry_limit = 5
|
129
|
+
@retry_exceptions = [CustomException, HierarchyCustomException]
|
130
|
+
|
131
|
+
def self.perform(exception)
|
132
|
+
case exception
|
133
|
+
when 'CustomException' then raise CustomException
|
134
|
+
when 'HierarchyCustomException' then raise HierarchyCustomException
|
135
|
+
when 'AnotherCustomException' then raise AnotherCustomException
|
136
|
+
else raise StandardError
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
module RetryModuleDefaultsJob
|
142
|
+
extend Resque::Plugins::Retry
|
143
|
+
@queue = :testing
|
144
|
+
|
145
|
+
def self.perform(*args)
|
146
|
+
raise
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
module RetryModuleCustomRetryCriteriaCheck
|
151
|
+
extend Resque::Plugins::Retry
|
152
|
+
@queue = :testing
|
153
|
+
|
154
|
+
# make sure the retry exceptions check will return false.
|
155
|
+
@retry_exceptions = [CustomException]
|
156
|
+
|
157
|
+
retry_criteria_check do |exception, *args|
|
158
|
+
true
|
159
|
+
end
|
160
|
+
|
161
|
+
def self.perform(*args)
|
162
|
+
raise
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
class CustomRetryCriteriaCheckDontRetry < RetryDefaultsJob
|
167
|
+
@queue = :testing
|
168
|
+
|
169
|
+
# make sure the retry exceptions check will return false.
|
170
|
+
@retry_exceptions = [CustomException]
|
171
|
+
|
172
|
+
retry_criteria_check do |exception, *args|
|
173
|
+
false
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
class CustomRetryCriteriaCheckDoRetry < CustomRetryCriteriaCheckDontRetry
|
178
|
+
@queue = :testing
|
179
|
+
|
180
|
+
# make sure the retry exceptions check will return false.
|
181
|
+
@retry_exceptions = [CustomException]
|
182
|
+
|
183
|
+
retry_criteria_check do |exception, *args|
|
184
|
+
true
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
# A job using multiple custom retry criteria checks.
|
189
|
+
# It always fails 2 times.
|
190
|
+
class CustomRetryCriteriaCheckMultipleFailTwice
|
191
|
+
extend Resque::Plugins::Retry
|
192
|
+
@retry_limit = 6
|
193
|
+
@queue = :testing
|
194
|
+
|
195
|
+
# make sure we dont retry due to default exception behaviour.
|
196
|
+
@retry_exceptions = []
|
197
|
+
|
198
|
+
retry_criteria_check do |exception, *args|
|
199
|
+
exception.message == 'dont' ? false : true
|
200
|
+
end
|
201
|
+
|
202
|
+
retry_criteria_check do |exception, *args|
|
203
|
+
exception.message == 'do' ? true : false
|
204
|
+
end
|
205
|
+
|
206
|
+
retry_criteria_check do |exception, *args|
|
207
|
+
exception.message == 'do_again' ? true : false
|
208
|
+
end
|
209
|
+
|
210
|
+
def self.perform(msg)
|
211
|
+
if retry_attempt < 2 # always fail twice please.
|
212
|
+
raise StandardError, msg
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
# A job to test whether self.inherited is respected
|
218
|
+
# when added by other modules.
|
219
|
+
class InheritOrderingJobExtendFirst
|
220
|
+
extend Resque::Plugins::Retry
|
221
|
+
|
222
|
+
retry_criteria_check do |exception, *args|
|
223
|
+
false
|
224
|
+
end
|
225
|
+
|
226
|
+
class << self
|
227
|
+
attr_accessor :test_value
|
228
|
+
end
|
229
|
+
|
230
|
+
def self.inherited(subclass)
|
231
|
+
super(subclass)
|
232
|
+
subclass.test_value = 'test'
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
# This job switches to successful after
|
237
|
+
# n +tries+.
|
238
|
+
class SwitchToSuccessJob < GoodJob
|
239
|
+
@queue = :testing
|
240
|
+
@max_retries = 3
|
241
|
+
|
242
|
+
class << self
|
243
|
+
attr_accessor :successful_after
|
244
|
+
attr_accessor :tries
|
245
|
+
|
246
|
+
def reset_defaults
|
247
|
+
self.tries = 0
|
248
|
+
self.successful_after = 2
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
reset_defaults
|
253
|
+
|
254
|
+
def self.perform(*args)
|
255
|
+
if self.tries < self.successful_after
|
256
|
+
self.tries += 1
|
257
|
+
raise "error"
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
class InheritOrderingJobExtendLast
|
263
|
+
class << self
|
264
|
+
attr_accessor :test_value
|
265
|
+
end
|
266
|
+
|
267
|
+
def self.inherited(subclass)
|
268
|
+
super(subclass)
|
269
|
+
subclass.test_value = 'test'
|
270
|
+
end
|
271
|
+
|
272
|
+
extend Resque::Plugins::Retry
|
273
|
+
|
274
|
+
retry_criteria_check do |exception, *args|
|
275
|
+
false
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
class InheritOrderingJobExtendFirstSubclass < InheritOrderingJobExtendFirst; end
|
280
|
+
class InheritOrderingJobExtendLastSubclass < InheritOrderingJobExtendLast; end
|
metadata
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: onyx-resque-retry
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Onyx Team
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-10-13 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: resque
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 55
|
30
|
+
segments:
|
31
|
+
- 1
|
32
|
+
- 8
|
33
|
+
- 0
|
34
|
+
version: 1.8.0
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: resque-scheduler
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 55
|
46
|
+
segments:
|
47
|
+
- 1
|
48
|
+
- 8
|
49
|
+
- 0
|
50
|
+
version: 1.8.0
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: test-unit
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 3
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
version: "0"
|
65
|
+
type: :development
|
66
|
+
version_requirements: *id003
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: turn
|
69
|
+
prerelease: false
|
70
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
hash: 3
|
76
|
+
segments:
|
77
|
+
- 0
|
78
|
+
version: "0"
|
79
|
+
type: :development
|
80
|
+
version_requirements: *id004
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: yard
|
83
|
+
prerelease: false
|
84
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
hash: 3
|
90
|
+
segments:
|
91
|
+
- 0
|
92
|
+
version: "0"
|
93
|
+
type: :development
|
94
|
+
version_requirements: *id005
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: simplecov
|
97
|
+
prerelease: false
|
98
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
99
|
+
none: false
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
hash: 19
|
104
|
+
segments:
|
105
|
+
- 0
|
106
|
+
- 3
|
107
|
+
- 0
|
108
|
+
version: 0.3.0
|
109
|
+
type: :development
|
110
|
+
version_requirements: *id006
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: mocha
|
113
|
+
prerelease: false
|
114
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
115
|
+
none: false
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
hash: 3
|
120
|
+
segments:
|
121
|
+
- 0
|
122
|
+
version: "0"
|
123
|
+
type: :development
|
124
|
+
version_requirements: *id007
|
125
|
+
description: " resque-retry provides retry, delay and exponential backoff support for\n resque jobs.\n\n Features:\n\n * Redis backed retry count/limit.\n * Retry on all or specific exceptions.\n * Exponential backoff (varying the delay between retrys).\n * Multiple failure backend with retry suppression & resque-web tab.\n * Small & Extendable - plenty of places to override retry logic/settings.\n"
|
126
|
+
email: rob.sweet@ove.com
|
127
|
+
executables: []
|
128
|
+
|
129
|
+
extensions: []
|
130
|
+
|
131
|
+
extra_rdoc_files: []
|
132
|
+
|
133
|
+
files:
|
134
|
+
- LICENSE
|
135
|
+
- Rakefile
|
136
|
+
- README.md
|
137
|
+
- HISTORY.md
|
138
|
+
- test/retry_test.rb
|
139
|
+
- test/multiple_failure_test.rb
|
140
|
+
- test/retry_inheriting_checks_test.rb
|
141
|
+
- test/redis-test.conf
|
142
|
+
- test/retry_criteria_test.rb
|
143
|
+
- test/resque_test.rb
|
144
|
+
- test/exponential_backoff_test.rb
|
145
|
+
- test/test_helper.rb
|
146
|
+
- test/test_jobs.rb
|
147
|
+
- lib/resque/failure/multiple_with_retry_suppression.rb
|
148
|
+
- lib/resque/plugins/exponential_backoff.rb
|
149
|
+
- lib/resque/plugins/retry.rb
|
150
|
+
- lib/resque-retry.rb
|
151
|
+
- lib/resque-retry/server/views/retry.erb
|
152
|
+
- lib/resque-retry/server/views/retry_timestamp.erb
|
153
|
+
- lib/resque-retry/server.rb
|
154
|
+
has_rdoc: false
|
155
|
+
homepage: http://github.com/onyx/resque-retry
|
156
|
+
licenses: []
|
157
|
+
|
158
|
+
post_install_message:
|
159
|
+
rdoc_options: []
|
160
|
+
|
161
|
+
require_paths:
|
162
|
+
- lib
|
163
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
164
|
+
none: false
|
165
|
+
requirements:
|
166
|
+
- - ">="
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
hash: 3
|
169
|
+
segments:
|
170
|
+
- 0
|
171
|
+
version: "0"
|
172
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
173
|
+
none: false
|
174
|
+
requirements:
|
175
|
+
- - ">="
|
176
|
+
- !ruby/object:Gem::Version
|
177
|
+
hash: 3
|
178
|
+
segments:
|
179
|
+
- 0
|
180
|
+
version: "0"
|
181
|
+
requirements: []
|
182
|
+
|
183
|
+
rubyforge_project:
|
184
|
+
rubygems_version: 1.3.7
|
185
|
+
signing_key:
|
186
|
+
specification_version: 3
|
187
|
+
summary: A resque plugin; provides retry, delay and exponential backoff support for resque jobs.
|
188
|
+
test_files: []
|
189
|
+
|