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.

Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -2
  3. data/4.0-Upgrade.md +50 -0
  4. data/COMM-LICENSE +55 -45
  5. data/Changes.md +85 -1
  6. data/Ent-Changes.md +79 -0
  7. data/Gemfile +7 -1
  8. data/Pro-2.0-Upgrade.md +2 -2
  9. data/Pro-3.0-Upgrade.md +46 -0
  10. data/Pro-Changes.md +60 -2
  11. data/README.md +20 -16
  12. data/bin/sidekiq +4 -0
  13. data/bin/sidekiqctl +8 -2
  14. data/bin/sidekiqload +167 -0
  15. data/lib/generators/sidekiq/templates/worker_spec.rb.erb +2 -2
  16. data/lib/generators/sidekiq/templates/worker_test.rb.erb +5 -5
  17. data/lib/sidekiq/api.rb +43 -33
  18. data/lib/sidekiq/cli.rb +41 -42
  19. data/lib/sidekiq/client.rb +5 -10
  20. data/lib/sidekiq/fetch.rb +35 -111
  21. data/lib/sidekiq/launcher.rb +102 -42
  22. data/lib/sidekiq/manager.rb +80 -180
  23. data/lib/sidekiq/middleware/server/logging.rb +13 -8
  24. data/lib/sidekiq/middleware/server/retry_jobs.rb +6 -6
  25. data/lib/sidekiq/processor.rb +126 -97
  26. data/lib/sidekiq/redis_connection.rb +23 -5
  27. data/lib/sidekiq/scheduled.rb +47 -26
  28. data/lib/sidekiq/testing.rb +139 -17
  29. data/lib/sidekiq/util.rb +20 -0
  30. data/lib/sidekiq/version.rb +1 -1
  31. data/lib/sidekiq/web.rb +17 -1
  32. data/lib/sidekiq/web_helpers.rb +33 -5
  33. data/lib/sidekiq/worker.rb +16 -0
  34. data/lib/sidekiq.rb +37 -14
  35. data/sidekiq.gemspec +10 -11
  36. data/test/helper.rb +45 -10
  37. data/test/test_actors.rb +137 -0
  38. data/test/test_api.rb +417 -384
  39. data/test/test_cli.rb +29 -59
  40. data/test/test_client.rb +60 -135
  41. data/test/test_extensions.rb +29 -23
  42. data/test/test_fetch.rb +2 -57
  43. data/test/test_launcher.rb +80 -0
  44. data/test/test_logging.rb +1 -1
  45. data/test/test_manager.rb +16 -131
  46. data/test/test_middleware.rb +3 -5
  47. data/test/test_processor.rb +110 -76
  48. data/test/test_rails.rb +21 -0
  49. data/test/test_redis_connection.rb +0 -1
  50. data/test/test_retry.rb +114 -162
  51. data/test/test_scheduled.rb +11 -17
  52. data/test/test_scheduling.rb +20 -42
  53. data/test/test_sidekiq.rb +46 -16
  54. data/test/test_testing.rb +80 -20
  55. data/test/test_testing_fake.rb +83 -8
  56. data/test/test_testing_inline.rb +3 -3
  57. data/test/test_util.rb +16 -0
  58. data/test/test_web.rb +28 -9
  59. data/test/test_web_helpers.rb +3 -2
  60. data/web/assets/images/favicon.ico +0 -0
  61. data/web/assets/javascripts/application.js +6 -1
  62. data/web/assets/javascripts/dashboard.js +2 -8
  63. data/web/assets/javascripts/locales/jquery.timeago.pt-br.js +14 -14
  64. data/web/assets/stylesheets/application.css +33 -56
  65. data/web/locales/de.yml +1 -1
  66. data/web/locales/en.yml +2 -0
  67. data/web/locales/fr.yml +2 -2
  68. data/web/locales/ja.yml +10 -1
  69. data/web/locales/{no.yml → nb.yml} +10 -2
  70. data/web/locales/uk.yml +76 -0
  71. data/web/views/_footer.erb +2 -7
  72. data/web/views/_job_info.erb +5 -1
  73. data/web/views/_nav.erb +2 -2
  74. data/web/views/_poll_js.erb +5 -0
  75. data/web/views/{_poll.erb → _poll_link.erb} +0 -3
  76. data/web/views/busy.erb +2 -1
  77. data/web/views/dead.erb +1 -0
  78. data/web/views/layout.erb +2 -0
  79. data/web/views/morgue.erb +3 -0
  80. data/web/views/queue.erb +1 -0
  81. data/web/views/queues.erb +1 -0
  82. data/web/views/retries.erb +3 -0
  83. data/web/views/retry.erb +1 -0
  84. data/web/views/scheduled.erb +1 -0
  85. data/web/views/scheduled_job_info.erb +1 -0
  86. metadata +75 -55
  87. data/lib/sidekiq/actor.rb +0 -39
  88. 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
- @redis = Minitest::Mock.new
10
- # Ugh, this is terrible.
11
- Sidekiq.instance_variable_set(:@redis, @redis)
13
+ Sidekiq.redis {|c| c.flushdb }
14
+ end
12
15
 
13
- def @redis.with; yield self; end
14
- def @redis.multi; yield self; end
16
+ def worker
17
+ @worker ||= SomeWorker.new
15
18
  end
16
19
 
17
- after do
18
- Sidekiq.redis = REDIS
20
+ def handler(options={})
21
+ @handler ||= Sidekiq::Middleware::Server::RetryJobs.new(options)
19
22
  end
20
23
 
21
- let(:worker) do
22
- Class.new do
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, msg2, 'default') do
30
+ handler.call(worker, job('retry' => false), 'default') do
33
31
  raise "kerblammo!"
34
32
  end
35
33
  end
36
- assert_equal msg, msg2
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, msg2, 'default') do
39
+ handler.call(worker, job('retry' => 2), 'default') do
46
40
  raise "kerblammo!"
47
41
  end
48
42
  end
49
- msg2.delete('failed_at')
50
- assert_equal({"class"=>"Bob", "args"=>[1, 2, "foo"], "retry"=>2, "queue"=>"default", "error_message"=>"kerblammo!", "error_class"=>"RuntimeError", "retry_count"=>0}, msg2)
51
- @redis.verify
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
- @redis.expect :zadd, 1, ['retry', String, String]
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, msg2, 'default') do
61
+ handler.call(worker, job, 'default') do
62
62
  raise "kerblammo! #{195.chr}"
63
63
  end
64
64
  end
65
- msg2.delete('failed_at')
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, msg, 'default') do
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
- @redis.verify
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, msg, 'default') do
86
+ handler.call(worker, job('backtrace' => true), 'default') do
98
87
  c = caller(0); raise "kerblammo!"
99
88
  end
100
89
  end
101
- assert msg["error_backtrace"]
102
- assert_equal c[0], msg["error_backtrace"][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, msg, 'default') do
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 msg["error_backtrace"]
117
- assert_equal c, msg["error_backtrace"]
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, msg, 'default') do
108
+ handler.call(worker, job, 'default') do
128
109
  raise "kerblammo!"
129
110
  end
130
111
  end
131
- assert_equal 'default', msg["queue"]
132
- assert_equal 'kerblammo!', msg["error_message"]
133
- assert_equal 'RuntimeError', msg["error_class"]
134
- assert_equal 0, msg["retry_count"]
135
- refute msg["error_backtrace"]
136
- assert msg["failed_at"]
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
- @redis.expect :zadd, 1, ['retry', String, String]
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
- assert_raises(MockExpectationError, "zadd should not be called") do
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
- @redis.expect :zadd, 1, ['retry', String, String]
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
- assert_raises(MockExpectationError, "zadd should not be called") do
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
- @redis.expect :zadd, 1, ['retry', String, String]
178
- msg = { 'class' => 'Bob', 'args' => [1,2,'foo'], 'retry' => true }
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, msg, 'default') do
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
- assert_raises(MockExpectationError, "zadd should not be called") do
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, msg, 'default') do
173
+ handler.call(worker, job("retry_queue" => 'retryx'), 'default') do
204
174
  raise "kerblammo!"
205
175
  end
206
176
  end
207
- assert_equal 'retry', msg["queue"]
208
- assert_equal 'kerblammo!', msg["error_message"]
209
- assert_equal 'RuntimeError', msg["error_class"]
210
- assert_equal 0, msg["retry_count"]
211
- refute msg["error_backtrace"]
212
- assert msg["failed_at"]
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 = {"class"=>"Bob", "args"=>[1, 2, "foo"], 'retry' => 10, "queue"=>"default", "error_message"=>"kerblammo!", "error_class"=>"RuntimeError", "failed_at"=>now, "retry_count"=>8}
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', msg["queue"]
245
- assert_equal 'kerblammo!', msg["error_message"]
246
- assert_equal 'RuntimeError', msg["error_class"]
247
- assert_equal 9, msg["retry_count"]
248
- assert msg["failed_at"]
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 = {"class"=>"Bob", "args"=>[1, 2, "foo"], "queue"=>"default", "error_message"=>"kerblammo!", "error_class"=>"RuntimeError", "failed_at"=>now, "retry"=>true, "retry_count"=>25}
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
- @redis.verify
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
- let(:custom_worker) do
296
- Class.new do
297
- include ::Sidekiq::Worker
232
+ class CustomWorkerWithoutException
233
+ include Sidekiq::Worker
298
234
 
299
- sidekiq_retry_in do |count|
300
- count * 2
301
- end
235
+ sidekiq_retry_in do |count|
236
+ count * 2
302
237
  end
303
238
  end
304
239
 
305
- let(:error_worker) do
306
- Class.new do
307
- include ::Sidekiq::Worker
240
+ class CustomWorkerWithException
241
+ include Sidekiq::Worker
308
242
 
309
- sidekiq_retry_in do |count|
310
- count / 0
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
- let(:handler) { Sidekiq::Middleware::Server::RetryJobs.new }
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, custom_worker, 2)
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, error_worker, 2)
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 => e2
309
+ rescue ::StandardError
358
310
  raise e1
359
311
  end
360
312
  end
@@ -10,11 +10,7 @@ class TestScheduled < Sidekiq::Test
10
10
 
11
11
  describe 'poller' do
12
12
  before do
13
- Sidekiq.redis = 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, message, queue, r)
32
- yield if message['args'].first.odd?
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.poll
40
+ @poller.enqueue
45
41
 
46
- Sidekiq.redis do |conn|
47
- assert_equal 0, conn.llen("queue:queue_1")
48
- assert_equal 1, conn.llen("queue:queue_2")
49
- assert_equal 0, conn.llen("queue:queue_5")
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.poll
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?{|i| i >= 5}
102
- assert intervals.all?{|i| i <= 15}
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
@@ -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 a job via interval' do
28
- @redis.expect :zadd, true, ['schedule', Array]
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
- @redis.verify
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
- @redis.verify
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
- @redis.verify
46
- end
26
+ assert_equal 3, ss.size
47
27
 
48
- it 'schedules job right away on negative timestamp/interval' do
49
- @redis.expect :sadd, true, ['queues', 'custom_queue']
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
- @redis.verify
53
- end
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
- @redis.verify
35
+ assert_equal 5, ss.size
59
36
  end
60
37
 
61
38
  it 'removes the enqueued_at field when scheduling' do
62
- @redis.expect :zadd, true do |key, args|
63
- job = Sidekiq.load_json(args.first.last)
64
- job.key?('created_at') && !job.key?('enqueued_at')
65
- end
39
+ ss = Sidekiq::ScheduledSet.new
40
+ ss.clear
41
+
66
42
  assert ScheduledWorker.perform_in(1.month, 'mike')
67
- @redis.verify
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 'loads json' do
7
- assert_equal ({"foo" => "bar"}), Sidekiq.load_json("{\"foo\":\"bar\"}")
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
- mock = Minitest::Mock.new
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
- before do
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 'stringify keys' do
65
- Sidekiq.default_worker_options = { queue: 'cat'}
66
- assert_equal 'cat', Sidekiq.default_worker_options['queue']
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