sidekiq 3.4.1 → 4.0.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sidekiq might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.travis.yml +3 -2
- data/4.0-Upgrade.md +50 -0
- data/COMM-LICENSE +55 -45
- data/Changes.md +85 -1
- data/Ent-Changes.md +79 -0
- data/Gemfile +7 -1
- data/Pro-2.0-Upgrade.md +2 -2
- data/Pro-3.0-Upgrade.md +46 -0
- data/Pro-Changes.md +60 -2
- data/README.md +20 -16
- data/bin/sidekiq +4 -0
- data/bin/sidekiqctl +8 -2
- data/bin/sidekiqload +167 -0
- data/lib/generators/sidekiq/templates/worker_spec.rb.erb +2 -2
- data/lib/generators/sidekiq/templates/worker_test.rb.erb +5 -5
- data/lib/sidekiq/api.rb +43 -33
- data/lib/sidekiq/cli.rb +41 -42
- data/lib/sidekiq/client.rb +5 -10
- data/lib/sidekiq/fetch.rb +35 -111
- data/lib/sidekiq/launcher.rb +102 -42
- data/lib/sidekiq/manager.rb +80 -180
- data/lib/sidekiq/middleware/server/logging.rb +13 -8
- data/lib/sidekiq/middleware/server/retry_jobs.rb +6 -6
- data/lib/sidekiq/processor.rb +126 -97
- data/lib/sidekiq/redis_connection.rb +23 -5
- data/lib/sidekiq/scheduled.rb +47 -26
- data/lib/sidekiq/testing.rb +139 -17
- data/lib/sidekiq/util.rb +20 -0
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web.rb +17 -1
- data/lib/sidekiq/web_helpers.rb +33 -5
- data/lib/sidekiq/worker.rb +16 -0
- data/lib/sidekiq.rb +37 -14
- data/sidekiq.gemspec +10 -11
- data/test/helper.rb +45 -10
- data/test/test_actors.rb +137 -0
- data/test/test_api.rb +417 -384
- data/test/test_cli.rb +29 -59
- data/test/test_client.rb +60 -135
- data/test/test_extensions.rb +29 -23
- data/test/test_fetch.rb +2 -57
- data/test/test_launcher.rb +80 -0
- data/test/test_logging.rb +1 -1
- data/test/test_manager.rb +16 -131
- data/test/test_middleware.rb +3 -5
- data/test/test_processor.rb +110 -76
- data/test/test_rails.rb +21 -0
- data/test/test_redis_connection.rb +0 -1
- data/test/test_retry.rb +114 -162
- data/test/test_scheduled.rb +11 -17
- data/test/test_scheduling.rb +20 -42
- data/test/test_sidekiq.rb +46 -16
- data/test/test_testing.rb +80 -20
- data/test/test_testing_fake.rb +83 -8
- data/test/test_testing_inline.rb +3 -3
- data/test/test_util.rb +16 -0
- data/test/test_web.rb +28 -9
- data/test/test_web_helpers.rb +3 -2
- data/web/assets/images/favicon.ico +0 -0
- data/web/assets/javascripts/application.js +6 -1
- data/web/assets/javascripts/dashboard.js +2 -8
- data/web/assets/javascripts/locales/jquery.timeago.pt-br.js +14 -14
- data/web/assets/stylesheets/application.css +33 -56
- data/web/locales/de.yml +1 -1
- data/web/locales/en.yml +2 -0
- data/web/locales/fr.yml +2 -2
- data/web/locales/ja.yml +10 -1
- data/web/locales/{no.yml → nb.yml} +10 -2
- data/web/locales/uk.yml +76 -0
- data/web/views/_footer.erb +2 -7
- data/web/views/_job_info.erb +5 -1
- data/web/views/_nav.erb +2 -2
- data/web/views/_poll_js.erb +5 -0
- data/web/views/{_poll.erb → _poll_link.erb} +0 -3
- data/web/views/busy.erb +2 -1
- data/web/views/dead.erb +1 -0
- data/web/views/layout.erb +2 -0
- data/web/views/morgue.erb +3 -0
- data/web/views/queue.erb +1 -0
- data/web/views/queues.erb +1 -0
- data/web/views/retries.erb +3 -0
- data/web/views/retry.erb +1 -0
- data/web/views/scheduled.erb +1 -0
- data/web/views/scheduled_job_info.erb +1 -0
- metadata +75 -55
- data/lib/sidekiq/actor.rb +0 -39
- data/test/test_worker_generator.rb +0 -17
data/test/test_retry.rb
CHANGED
@@ -5,158 +5,136 @@ require 'sidekiq/middleware/server/retry_jobs'
|
|
5
5
|
|
6
6
|
class TestRetry < Sidekiq::Test
|
7
7
|
describe 'middleware' do
|
8
|
+
class SomeWorker
|
9
|
+
include Sidekiq::Worker
|
10
|
+
end
|
11
|
+
|
8
12
|
before do
|
9
|
-
|
10
|
-
|
11
|
-
Sidekiq.instance_variable_set(:@redis, @redis)
|
13
|
+
Sidekiq.redis {|c| c.flushdb }
|
14
|
+
end
|
12
15
|
|
13
|
-
|
14
|
-
|
16
|
+
def worker
|
17
|
+
@worker ||= SomeWorker.new
|
15
18
|
end
|
16
19
|
|
17
|
-
|
18
|
-
Sidekiq.
|
20
|
+
def handler(options={})
|
21
|
+
@handler ||= Sidekiq::Middleware::Server::RetryJobs.new(options)
|
19
22
|
end
|
20
23
|
|
21
|
-
|
22
|
-
|
23
|
-
include ::Sidekiq::Worker
|
24
|
-
end
|
24
|
+
def job(options={})
|
25
|
+
@job ||= { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => true }.merge(options)
|
25
26
|
end
|
26
27
|
|
27
28
|
it 'allows disabling retry' do
|
28
|
-
msg = { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => false }
|
29
|
-
msg2 = msg.dup
|
30
|
-
handler = Sidekiq::Middleware::Server::RetryJobs.new
|
31
29
|
assert_raises RuntimeError do
|
32
|
-
handler.call(worker,
|
30
|
+
handler.call(worker, job('retry' => false), 'default') do
|
33
31
|
raise "kerblammo!"
|
34
32
|
end
|
35
33
|
end
|
36
|
-
assert_equal
|
34
|
+
assert_equal 0, Sidekiq::RetrySet.new.size
|
37
35
|
end
|
38
36
|
|
39
37
|
it 'allows a numeric retry' do
|
40
|
-
@redis.expect :zadd, 1, ['retry', String, String]
|
41
|
-
msg = { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => 2 }
|
42
|
-
msg2 = msg.dup
|
43
|
-
handler = Sidekiq::Middleware::Server::RetryJobs.new
|
44
38
|
assert_raises RuntimeError do
|
45
|
-
handler.call(worker,
|
39
|
+
handler.call(worker, job('retry' => 2), 'default') do
|
46
40
|
raise "kerblammo!"
|
47
41
|
end
|
48
42
|
end
|
49
|
-
|
50
|
-
assert_equal
|
51
|
-
|
43
|
+
assert_equal 1, Sidekiq::RetrySet.new.size
|
44
|
+
assert_equal 0, Sidekiq::DeadSet.new.size
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'allows 0 retry => no retry and dead queue' do
|
48
|
+
assert_raises RuntimeError do
|
49
|
+
handler.call(worker, job('retry' => 0), 'default') do
|
50
|
+
raise "kerblammo!"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
assert_equal 0, Sidekiq::RetrySet.new.size
|
54
|
+
assert_equal 1, Sidekiq::DeadSet.new.size
|
52
55
|
end
|
53
56
|
|
54
57
|
it 'handles zany characters in error message, #1705' do
|
55
58
|
skip 'skipped! test requires ruby 2.1+' if RUBY_VERSION <= '2.1.0'
|
56
|
-
|
57
|
-
msg = { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => 2 }
|
58
|
-
msg2 = msg.dup
|
59
|
-
handler = Sidekiq::Middleware::Server::RetryJobs.new
|
59
|
+
|
60
60
|
assert_raises RuntimeError do
|
61
|
-
handler.call(worker,
|
61
|
+
handler.call(worker, job, 'default') do
|
62
62
|
raise "kerblammo! #{195.chr}"
|
63
63
|
end
|
64
64
|
end
|
65
|
-
|
66
|
-
assert_equal({"class"=>"Bob", "args"=>[1, 2, "foo"], "retry"=>2, "queue"=>"default", "error_message"=>"kerblammo! �", "error_class"=>"RuntimeError", "retry_count"=>0}, msg2)
|
67
|
-
@redis.verify
|
65
|
+
assert_equal "kerblammo! �", job["error_message"]
|
68
66
|
end
|
69
67
|
|
70
68
|
|
71
69
|
it 'allows a max_retries option in initializer' do
|
72
70
|
max_retries = 7
|
73
|
-
1.upto(max_retries) do
|
74
|
-
@redis.expect :zadd, 1, ['retry', String, String]
|
75
|
-
end
|
76
|
-
@redis.expect :zadd, 1, ['dead', Float, String]
|
77
|
-
@redis.expect :zremrangebyscore, 0, ['dead', String, Float]
|
78
|
-
@redis.expect :zremrangebyrank, 0, ['dead', Numeric, Numeric]
|
79
|
-
msg = { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => true }
|
80
|
-
handler = Sidekiq::Middleware::Server::RetryJobs.new({:max_retries => max_retries})
|
81
71
|
1.upto(max_retries + 1) do
|
82
72
|
assert_raises RuntimeError do
|
83
|
-
handler.call(worker,
|
73
|
+
handler(:max_retries => max_retries).call(worker, job, 'default') do
|
84
74
|
raise "kerblammo!"
|
85
75
|
end
|
86
76
|
end
|
87
77
|
end
|
88
|
-
|
78
|
+
|
79
|
+
assert_equal max_retries, Sidekiq::RetrySet.new.size
|
80
|
+
assert_equal 1, Sidekiq::DeadSet.new.size
|
89
81
|
end
|
90
82
|
|
91
83
|
it 'saves backtraces' do
|
92
|
-
@redis.expect :zadd, 1, ['retry', String, String]
|
93
|
-
msg = { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => true, 'backtrace' => true }
|
94
|
-
handler = Sidekiq::Middleware::Server::RetryJobs.new
|
95
84
|
c = nil
|
96
85
|
assert_raises RuntimeError do
|
97
|
-
handler.call(worker,
|
86
|
+
handler.call(worker, job('backtrace' => true), 'default') do
|
98
87
|
c = caller(0); raise "kerblammo!"
|
99
88
|
end
|
100
89
|
end
|
101
|
-
assert
|
102
|
-
assert_equal c[0],
|
103
|
-
@redis.verify
|
90
|
+
assert job["error_backtrace"]
|
91
|
+
assert_equal c[0], job["error_backtrace"][0]
|
104
92
|
end
|
105
93
|
|
106
94
|
it 'saves partial backtraces' do
|
107
|
-
@redis.expect :zadd, 1, ['retry', String, String]
|
108
|
-
msg = { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => true, 'backtrace' => 3 }
|
109
|
-
handler = Sidekiq::Middleware::Server::RetryJobs.new
|
110
95
|
c = nil
|
111
96
|
assert_raises RuntimeError do
|
112
|
-
handler.call(worker,
|
97
|
+
handler.call(worker, job('backtrace' => 3), 'default') do
|
113
98
|
c = caller(0)[0...3]; raise "kerblammo!"
|
114
99
|
end
|
115
100
|
end
|
116
|
-
assert
|
117
|
-
assert_equal c,
|
101
|
+
assert job["error_backtrace"]
|
102
|
+
assert_equal c, job["error_backtrace"]
|
118
103
|
assert_equal 3, c.size
|
119
|
-
assert_equal 3, msg["error_backtrace"].size
|
120
104
|
end
|
121
105
|
|
122
106
|
it 'handles a new failed message' do
|
123
|
-
@redis.expect :zadd, 1, ['retry', String, String]
|
124
|
-
msg = { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => true }
|
125
|
-
handler = Sidekiq::Middleware::Server::RetryJobs.new
|
126
107
|
assert_raises RuntimeError do
|
127
|
-
handler.call(worker,
|
108
|
+
handler.call(worker, job, 'default') do
|
128
109
|
raise "kerblammo!"
|
129
110
|
end
|
130
111
|
end
|
131
|
-
assert_equal 'default',
|
132
|
-
assert_equal 'kerblammo!',
|
133
|
-
assert_equal 'RuntimeError',
|
134
|
-
assert_equal 0,
|
135
|
-
refute
|
136
|
-
assert
|
137
|
-
@redis.verify
|
112
|
+
assert_equal 'default', job["queue"]
|
113
|
+
assert_equal 'kerblammo!', job["error_message"]
|
114
|
+
assert_equal 'RuntimeError', job["error_class"]
|
115
|
+
assert_equal 0, job["retry_count"]
|
116
|
+
refute job["error_backtrace"]
|
117
|
+
assert job["failed_at"]
|
138
118
|
end
|
139
119
|
|
140
120
|
it 'shuts down without retrying work-in-progress, which will resume' do
|
141
|
-
|
121
|
+
rs = Sidekiq::RetrySet.new
|
122
|
+
assert_equal 0, rs.size
|
142
123
|
msg = { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => true }
|
143
|
-
handler = Sidekiq::Middleware::Server::RetryJobs.new
|
144
124
|
assert_raises Sidekiq::Shutdown do
|
145
125
|
handler.call(worker, msg, 'default') do
|
146
126
|
raise Sidekiq::Shutdown
|
147
127
|
end
|
148
128
|
end
|
149
|
-
|
150
|
-
@redis.verify
|
151
|
-
end
|
129
|
+
assert_equal 0, rs.size
|
152
130
|
end
|
153
131
|
|
154
132
|
it 'shuts down cleanly when shutdown causes exception' do
|
155
133
|
skip('Not supported in Ruby < 2.1.0') if RUBY_VERSION < '2.1.0'
|
156
134
|
|
157
|
-
|
135
|
+
rs = Sidekiq::RetrySet.new
|
136
|
+
assert_equal 0, rs.size
|
158
137
|
msg = { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => true }
|
159
|
-
handler = Sidekiq::Middleware::Server::RetryJobs.new
|
160
138
|
assert_raises Sidekiq::Shutdown do
|
161
139
|
handler.call(worker, msg, 'default') do
|
162
140
|
begin
|
@@ -166,19 +144,16 @@ class TestRetry < Sidekiq::Test
|
|
166
144
|
end
|
167
145
|
end
|
168
146
|
end
|
169
|
-
|
170
|
-
@redis.verify
|
171
|
-
end
|
147
|
+
assert_equal 0, rs.size
|
172
148
|
end
|
173
149
|
|
174
150
|
it 'shuts down cleanly when shutdown causes chained exceptions' do
|
175
151
|
skip('Not supported in Ruby < 2.1.0') if RUBY_VERSION < '2.1.0'
|
176
152
|
|
177
|
-
|
178
|
-
|
179
|
-
handler = Sidekiq::Middleware::Server::RetryJobs.new
|
153
|
+
rs = Sidekiq::RetrySet.new
|
154
|
+
assert_equal 0, rs.size
|
180
155
|
assert_raises Sidekiq::Shutdown do
|
181
|
-
handler.call(worker,
|
156
|
+
handler.call(worker, job, 'default') do
|
182
157
|
begin
|
183
158
|
raise Sidekiq::Shutdown
|
184
159
|
rescue Interrupt
|
@@ -190,93 +165,55 @@ class TestRetry < Sidekiq::Test
|
|
190
165
|
end
|
191
166
|
end
|
192
167
|
end
|
193
|
-
|
194
|
-
@redis.verify
|
195
|
-
end
|
168
|
+
assert_equal 0, rs.size
|
196
169
|
end
|
197
170
|
|
198
171
|
it 'allows a retry queue' do
|
199
|
-
@redis.expect :zadd, 1, ['retry', String, String]
|
200
|
-
msg = { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => true, 'retry_queue' => 'retry' }
|
201
|
-
handler = Sidekiq::Middleware::Server::RetryJobs.new
|
202
172
|
assert_raises RuntimeError do
|
203
|
-
handler.call(worker,
|
173
|
+
handler.call(worker, job("retry_queue" => 'retryx'), 'default') do
|
204
174
|
raise "kerblammo!"
|
205
175
|
end
|
206
176
|
end
|
207
|
-
assert_equal '
|
208
|
-
assert_equal 'kerblammo!',
|
209
|
-
assert_equal 'RuntimeError',
|
210
|
-
assert_equal 0,
|
211
|
-
refute
|
212
|
-
assert
|
213
|
-
@redis.verify
|
177
|
+
assert_equal 'retryx', job["queue"]
|
178
|
+
assert_equal 'kerblammo!', job["error_message"]
|
179
|
+
assert_equal 'RuntimeError', job["error_class"]
|
180
|
+
assert_equal 0, job["retry_count"]
|
181
|
+
refute job["error_backtrace"]
|
182
|
+
assert job["failed_at"]
|
214
183
|
end
|
215
184
|
|
216
185
|
it 'handles a recurring failed message' do
|
217
|
-
@redis.expect :zadd, 1, ['retry', String, String]
|
218
|
-
now = Time.now.to_f
|
219
|
-
msg = {"class"=>"Bob", "args"=>[1, 2, "foo"], 'retry' => true, "queue"=>"default", "error_message"=>"kerblammo!", "error_class"=>"RuntimeError", "failed_at"=>now, "retry_count"=>10}
|
220
|
-
handler = Sidekiq::Middleware::Server::RetryJobs.new
|
221
|
-
assert_raises RuntimeError do
|
222
|
-
handler.call(worker, msg, 'default') do
|
223
|
-
raise "kerblammo!"
|
224
|
-
end
|
225
|
-
end
|
226
|
-
assert_equal 'default', msg["queue"]
|
227
|
-
assert_equal 'kerblammo!', msg["error_message"]
|
228
|
-
assert_equal 'RuntimeError', msg["error_class"]
|
229
|
-
assert_equal 11, msg["retry_count"]
|
230
|
-
assert msg["failed_at"]
|
231
|
-
@redis.verify
|
232
|
-
end
|
233
|
-
|
234
|
-
it 'handles a recurring failed message before reaching user-specifed max' do
|
235
|
-
@redis.expect :zadd, 1, ['retry', String, String]
|
236
186
|
now = Time.now.to_f
|
237
|
-
msg = {"
|
238
|
-
handler = Sidekiq::Middleware::Server::RetryJobs.new
|
187
|
+
msg = {"queue"=>"default", "error_message"=>"kerblammo!", "error_class"=>"RuntimeError", "failed_at"=>now, "retry_count"=>10}
|
239
188
|
assert_raises RuntimeError do
|
240
|
-
handler.call(worker, msg, 'default') do
|
189
|
+
handler.call(worker, job(msg), 'default') do
|
241
190
|
raise "kerblammo!"
|
242
191
|
end
|
243
192
|
end
|
244
|
-
assert_equal 'default',
|
245
|
-
assert_equal 'kerblammo!',
|
246
|
-
assert_equal 'RuntimeError',
|
247
|
-
assert_equal
|
248
|
-
assert
|
249
|
-
@redis.verify
|
193
|
+
assert_equal 'default', job["queue"]
|
194
|
+
assert_equal 'kerblammo!', job["error_message"]
|
195
|
+
assert_equal 'RuntimeError', job["error_class"]
|
196
|
+
assert_equal 11, job["retry_count"]
|
197
|
+
assert job["failed_at"]
|
250
198
|
end
|
251
199
|
|
252
200
|
it 'throws away old messages after too many retries (using the default)' do
|
201
|
+
q = Sidekiq::Queue.new
|
202
|
+
rs = Sidekiq::RetrySet.new
|
203
|
+
ds = Sidekiq::DeadSet.new
|
204
|
+
assert_equal 0, q.size
|
205
|
+
assert_equal 0, rs.size
|
206
|
+
assert_equal 0, ds.size
|
253
207
|
now = Time.now.to_f
|
254
|
-
msg = {"
|
255
|
-
@redis.expect :zadd, 1, ['dead', Float, String]
|
256
|
-
@redis.expect :zremrangebyscore, 0, ['dead', String, Float]
|
257
|
-
@redis.expect :zremrangebyrank, 0, ['dead', Numeric, Numeric]
|
258
|
-
handler = Sidekiq::Middleware::Server::RetryJobs.new
|
259
|
-
assert_raises RuntimeError do
|
260
|
-
handler.call(worker, msg, 'default') do
|
261
|
-
raise "kerblammo!"
|
262
|
-
end
|
263
|
-
end
|
264
|
-
@redis.verify
|
265
|
-
end
|
266
|
-
|
267
|
-
it 'throws away old messages after too many retries (using user-specified max)' do
|
268
|
-
now = Time.now.to_f
|
269
|
-
msg = {"class"=>"Bob", "args"=>[1, 2, "foo"], "queue"=>"default", "error_message"=>"kerblammo!", "error_class"=>"RuntimeError", "failed_at"=>now, "retry"=>3, "retry_count"=>3}
|
270
|
-
@redis.expect :zadd, 1, ['dead', Float, String]
|
271
|
-
@redis.expect :zremrangebyscore, 0, ['dead', String, Float]
|
272
|
-
@redis.expect :zremrangebyrank, 0, ['dead', Numeric, Numeric]
|
273
|
-
handler = Sidekiq::Middleware::Server::RetryJobs.new
|
208
|
+
msg = {"queue"=>"default", "error_message"=>"kerblammo!", "error_class"=>"RuntimeError", "failed_at"=>now, "retry_count"=>25}
|
274
209
|
assert_raises RuntimeError do
|
275
|
-
handler.call(worker, msg, 'default') do
|
210
|
+
handler.call(worker, job(msg), 'default') do
|
276
211
|
raise "kerblammo!"
|
277
212
|
end
|
278
213
|
end
|
279
|
-
|
214
|
+
assert_equal 0, q.size
|
215
|
+
assert_equal 0, rs.size
|
216
|
+
assert_equal 1, ds.size
|
280
217
|
end
|
281
218
|
|
282
219
|
describe "custom retry delay" do
|
@@ -292,38 +229,53 @@ class TestRetry < Sidekiq::Test
|
|
292
229
|
File.unlink @tmp_log_path if File.exist?(@tmp_log_path)
|
293
230
|
end
|
294
231
|
|
295
|
-
|
296
|
-
|
297
|
-
include ::Sidekiq::Worker
|
232
|
+
class CustomWorkerWithoutException
|
233
|
+
include Sidekiq::Worker
|
298
234
|
|
299
|
-
|
300
|
-
|
301
|
-
end
|
235
|
+
sidekiq_retry_in do |count|
|
236
|
+
count * 2
|
302
237
|
end
|
303
238
|
end
|
304
239
|
|
305
|
-
|
306
|
-
|
307
|
-
include ::Sidekiq::Worker
|
240
|
+
class CustomWorkerWithException
|
241
|
+
include Sidekiq::Worker
|
308
242
|
|
309
|
-
|
310
|
-
|
243
|
+
sidekiq_retry_in do |count, exception|
|
244
|
+
case exception
|
245
|
+
when ArgumentError
|
246
|
+
count * 4
|
247
|
+
else
|
248
|
+
count * 2
|
311
249
|
end
|
312
250
|
end
|
313
251
|
end
|
314
252
|
|
315
|
-
|
253
|
+
class ErrorWorker
|
254
|
+
include Sidekiq::Worker
|
255
|
+
|
256
|
+
sidekiq_retry_in do |count|
|
257
|
+
count / 0
|
258
|
+
end
|
259
|
+
end
|
316
260
|
|
317
261
|
it "retries with a default delay" do
|
318
|
-
refute_equal 4, handler.__send__(:delay_for, worker, 2)
|
262
|
+
refute_equal 4, handler.__send__(:delay_for, worker, 2, StandardError.new)
|
263
|
+
end
|
264
|
+
|
265
|
+
it "retries with a custom delay and exception 1" do
|
266
|
+
assert_equal 8, handler.__send__(:delay_for, CustomWorkerWithException, 2, ArgumentError.new)
|
267
|
+
end
|
268
|
+
|
269
|
+
it "retries with a custom delay and exception 2" do
|
270
|
+
assert_equal 4, handler.__send__(:delay_for, CustomWorkerWithException, 2, StandardError.new)
|
319
271
|
end
|
320
272
|
|
321
|
-
it "retries with a custom delay" do
|
322
|
-
assert_equal 4, handler.__send__(:delay_for,
|
273
|
+
it "retries with a custom delay without exception" do
|
274
|
+
assert_equal 4, handler.__send__(:delay_for, CustomWorkerWithoutException, 2, StandardError.new)
|
323
275
|
end
|
324
276
|
|
325
277
|
it "falls back to the default retry on exception" do
|
326
|
-
refute_equal 4, handler.__send__(:delay_for,
|
278
|
+
refute_equal 4, handler.__send__(:delay_for, ErrorWorker, 2, StandardError.new)
|
327
279
|
assert_match(/Failure scheduling retry using the defined `sidekiq_retry_in`/,
|
328
280
|
File.read(@tmp_log_path), 'Log entry missing for sidekiq_retry_in')
|
329
281
|
end
|
@@ -354,7 +306,7 @@ class TestRetry < Sidekiq::Test
|
|
354
306
|
rescue ::StandardError => e1
|
355
307
|
begin
|
356
308
|
raise ::StandardError, 'Error 2'
|
357
|
-
rescue ::StandardError
|
309
|
+
rescue ::StandardError
|
358
310
|
raise e1
|
359
311
|
end
|
360
312
|
end
|
data/test/test_scheduled.rb
CHANGED
@@ -10,11 +10,7 @@ class TestScheduled < Sidekiq::Test
|
|
10
10
|
|
11
11
|
describe 'poller' do
|
12
12
|
before do
|
13
|
-
Sidekiq.redis
|
14
|
-
Sidekiq.redis do |conn|
|
15
|
-
conn.flushdb
|
16
|
-
end
|
17
|
-
|
13
|
+
Sidekiq.redis{|c| c.flushdb}
|
18
14
|
@error_1 = { 'class' => ScheduledWorker.name, 'args' => [0], 'queue' => 'queue_1' }
|
19
15
|
@error_2 = { 'class' => ScheduledWorker.name, 'args' => [1], 'queue' => 'queue_2' }
|
20
16
|
@error_3 = { 'class' => ScheduledWorker.name, 'args' => [2], 'queue' => 'queue_3' }
|
@@ -28,8 +24,8 @@ class TestScheduled < Sidekiq::Test
|
|
28
24
|
end
|
29
25
|
|
30
26
|
class Stopper
|
31
|
-
def call(worker_class,
|
32
|
-
yield if
|
27
|
+
def call(worker_class, job, queue, r)
|
28
|
+
yield if job['args'].first.odd?
|
33
29
|
end
|
34
30
|
end
|
35
31
|
|
@@ -41,14 +37,12 @@ class TestScheduled < Sidekiq::Test
|
|
41
37
|
@scheduled.schedule (Time.now - 60).to_f, @future_2
|
42
38
|
@scheduled.schedule (Time.now - 60).to_f, @future_3
|
43
39
|
|
44
|
-
@poller.
|
40
|
+
@poller.enqueue
|
45
41
|
|
46
|
-
Sidekiq.
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
assert_equal 1, conn.llen("queue:queue_6")
|
51
|
-
end
|
42
|
+
assert_equal 0, Sidekiq::Queue.new("queue_1").size
|
43
|
+
assert_equal 1, Sidekiq::Queue.new("queue_2").size
|
44
|
+
assert_equal 0, Sidekiq::Queue.new("queue_5").size
|
45
|
+
assert_equal 1, Sidekiq::Queue.new("queue_6").size
|
52
46
|
ensure
|
53
47
|
Sidekiq.client_middleware.remove Stopper
|
54
48
|
end
|
@@ -68,7 +62,7 @@ class TestScheduled < Sidekiq::Test
|
|
68
62
|
end
|
69
63
|
|
70
64
|
Time.stub(:now, enqueued_time) do
|
71
|
-
@poller.
|
65
|
+
@poller.enqueue
|
72
66
|
|
73
67
|
Sidekiq.redis do |conn|
|
74
68
|
%w(queue:queue_1 queue:queue_2 queue:queue_4 queue:queue_5).each do |queue_name|
|
@@ -98,8 +92,8 @@ class TestScheduled < Sidekiq::Test
|
|
98
92
|
i = 500
|
99
93
|
intervals = i.times.map{ @poller.send(:random_poll_interval) }
|
100
94
|
|
101
|
-
assert intervals.all?{|
|
102
|
-
assert intervals.all?{|
|
95
|
+
assert intervals.all?{|x| x >= 5}
|
96
|
+
assert intervals.all?{|x| x <= 15}
|
103
97
|
assert_in_delta 10, intervals.reduce(&:+).to_f / i, 0.5
|
104
98
|
end
|
105
99
|
end
|
data/test/test_scheduling.rb
CHANGED
@@ -3,20 +3,6 @@ require 'sidekiq/scheduled'
|
|
3
3
|
|
4
4
|
class TestScheduling < Sidekiq::Test
|
5
5
|
describe 'middleware' do
|
6
|
-
before do
|
7
|
-
Sidekiq::Client.instance_variable_set(:@default, nil)
|
8
|
-
@redis = Minitest::Mock.new
|
9
|
-
# Ugh, this is terrible.
|
10
|
-
Sidekiq.instance_variable_set(:@redis, @redis)
|
11
|
-
def @redis.multi; [yield] * 2 if block_given?; end
|
12
|
-
def @redis.with; yield self; end
|
13
|
-
end
|
14
|
-
|
15
|
-
after do
|
16
|
-
Sidekiq::Client.instance_variable_set(:@default, nil)
|
17
|
-
Sidekiq.instance_variable_set(:@redis, REDIS)
|
18
|
-
end
|
19
|
-
|
20
6
|
class ScheduledWorker
|
21
7
|
include Sidekiq::Worker
|
22
8
|
sidekiq_options :queue => :custom_queue
|
@@ -24,47 +10,39 @@ class TestScheduling < Sidekiq::Test
|
|
24
10
|
end
|
25
11
|
end
|
26
12
|
|
27
|
-
it 'schedules
|
28
|
-
|
13
|
+
it 'schedules jobs' do
|
14
|
+
ss = Sidekiq::ScheduledSet.new
|
15
|
+
ss.clear
|
16
|
+
|
17
|
+
assert_equal 0, ss.size
|
18
|
+
|
29
19
|
assert ScheduledWorker.perform_in(600, 'mike')
|
30
|
-
|
31
|
-
end
|
20
|
+
assert_equal 1, ss.size
|
32
21
|
|
33
|
-
it 'schedules a job in one month' do
|
34
|
-
@redis.expect :zadd, true do |key, args|
|
35
|
-
assert_equal 'schedule', key
|
36
|
-
assert_in_delta 1.month.since.to_f, args[0][0].to_f, 1
|
37
|
-
end
|
38
22
|
assert ScheduledWorker.perform_in(1.month, 'mike')
|
39
|
-
|
40
|
-
end
|
23
|
+
assert_equal 2, ss.size
|
41
24
|
|
42
|
-
it 'schedules a job via timestamp' do
|
43
|
-
@redis.expect :zadd, true, ['schedule', Array]
|
44
25
|
assert ScheduledWorker.perform_in(5.days.from_now, 'mike')
|
45
|
-
|
46
|
-
end
|
26
|
+
assert_equal 3, ss.size
|
47
27
|
|
48
|
-
|
49
|
-
|
50
|
-
@redis.expect :lpush, true, ['queue:custom_queue', Array]
|
28
|
+
q = Sidekiq::Queue.new("custom_queue")
|
29
|
+
qs = q.size
|
51
30
|
assert ScheduledWorker.perform_in(-300, 'mike')
|
52
|
-
|
53
|
-
|
31
|
+
assert_equal 3, ss.size
|
32
|
+
assert_equal qs+1, q.size
|
54
33
|
|
55
|
-
it 'schedules multiple jobs at once' do
|
56
|
-
@redis.expect :zadd, true, ['schedule', Array]
|
57
34
|
assert Sidekiq::Client.push_bulk('class' => ScheduledWorker, 'args' => [['mike'], ['mike']], 'at' => 600)
|
58
|
-
|
35
|
+
assert_equal 5, ss.size
|
59
36
|
end
|
60
37
|
|
61
38
|
it 'removes the enqueued_at field when scheduling' do
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
end
|
39
|
+
ss = Sidekiq::ScheduledSet.new
|
40
|
+
ss.clear
|
41
|
+
|
66
42
|
assert ScheduledWorker.perform_in(1.month, 'mike')
|
67
|
-
|
43
|
+
job = ss.first
|
44
|
+
assert job['created_at']
|
45
|
+
refute job['enqueued_at']
|
68
46
|
end
|
69
47
|
end
|
70
48
|
|
data/test/test_sidekiq.rb
CHANGED
@@ -3,24 +3,16 @@ require_relative 'helper'
|
|
3
3
|
|
4
4
|
class TestSidekiq < Sidekiq::Test
|
5
5
|
describe 'json processing' do
|
6
|
-
it '
|
7
|
-
assert_equal
|
8
|
-
end
|
9
|
-
|
10
|
-
it 'dumps json' do
|
6
|
+
it 'handles json' do
|
7
|
+
assert_equal({"foo" => "bar"}, Sidekiq.load_json("{\"foo\":\"bar\"}"))
|
11
8
|
assert_equal "{\"foo\":\"bar\"}", Sidekiq.dump_json({ "foo" => "bar" })
|
12
9
|
end
|
13
10
|
end
|
14
11
|
|
15
12
|
describe "redis connection" do
|
16
13
|
it "returns error without creating a connection if block is not given" do
|
17
|
-
|
18
|
-
mock.expect :create, nil #Sidekiq::RedisConnection, create
|
19
|
-
assert_raises(ArgumentError) {
|
14
|
+
assert_raises(ArgumentError) do
|
20
15
|
Sidekiq.redis
|
21
|
-
}
|
22
|
-
assert_raises(MockExpectationError, "create should not be called") do
|
23
|
-
mock.verify
|
24
16
|
end
|
25
17
|
end
|
26
18
|
end
|
@@ -56,14 +48,52 @@ class TestSidekiq < Sidekiq::Test
|
|
56
48
|
end
|
57
49
|
|
58
50
|
describe 'default_worker_options' do
|
59
|
-
|
51
|
+
it 'stringifies keys' do
|
60
52
|
@old_options = Sidekiq.default_worker_options
|
53
|
+
begin
|
54
|
+
Sidekiq.default_worker_options = { queue: 'cat'}
|
55
|
+
assert_equal 'cat', Sidekiq.default_worker_options['queue']
|
56
|
+
ensure
|
57
|
+
Sidekiq.default_worker_options = @old_options
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe 'error handling' do
|
63
|
+
it 'deals with user-specified error handlers which raise errors' do
|
64
|
+
output = capture_logging do
|
65
|
+
begin
|
66
|
+
Sidekiq.error_handlers << proc {|x, hash|
|
67
|
+
raise 'boom'
|
68
|
+
}
|
69
|
+
cli = Sidekiq::CLI.new
|
70
|
+
cli.handle_exception(RuntimeError.new("hello"))
|
71
|
+
ensure
|
72
|
+
Sidekiq.error_handlers.pop
|
73
|
+
end
|
74
|
+
end
|
75
|
+
assert_includes output, "boom"
|
76
|
+
assert_includes output, "ERROR"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe 'redis connection' do
|
81
|
+
it 'does not continually retry' do
|
82
|
+
assert_raises Redis::CommandError do
|
83
|
+
Sidekiq.redis do |c|
|
84
|
+
raise Redis::CommandError, "READONLY You can't write against a read only slave."
|
85
|
+
end
|
86
|
+
end
|
61
87
|
end
|
62
|
-
after { Sidekiq.default_worker_options = @old_options }
|
63
88
|
|
64
|
-
it '
|
65
|
-
|
66
|
-
|
89
|
+
it 'reconnects if connection is flagged as readonly' do
|
90
|
+
counts = []
|
91
|
+
Sidekiq.redis do |c|
|
92
|
+
counts << c.info['total_connections_received'].to_i
|
93
|
+
raise Redis::CommandError, "READONLY You can't write against a read only slave." if counts.size == 1
|
94
|
+
end
|
95
|
+
assert_equal 2, counts.size
|
96
|
+
assert_equal counts[0] + 1, counts[1]
|
67
97
|
end
|
68
98
|
end
|
69
99
|
end
|