sidekiq 4.2.9 → 4.2.10

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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/.github/issue_template.md +6 -1
  3. data/.travis.yml +10 -5
  4. data/Changes.md +9 -0
  5. data/Ent-Changes.md +9 -0
  6. data/Pro-Changes.md +29 -0
  7. data/bin/sidekiqload +11 -11
  8. data/lib/sidekiq.rb +1 -1
  9. data/lib/sidekiq/api.rb +20 -12
  10. data/lib/sidekiq/middleware/server/logging.rb +8 -17
  11. data/lib/sidekiq/processor.rb +16 -7
  12. data/lib/sidekiq/testing.rb +6 -0
  13. data/lib/sidekiq/version.rb +1 -1
  14. data/lib/sidekiq/web/application.rb +2 -2
  15. data/lib/sidekiq/web/helpers.rb +2 -1
  16. data/sidekiq.gemspec +8 -2
  17. data/web/assets/javascripts/dashboard.js +1 -1
  18. data/web/locales/fa.yml +79 -0
  19. data/web/views/_job_info.erb +1 -1
  20. data/web/views/dashboard.erb +2 -2
  21. data/web/views/morgue.erb +2 -0
  22. data/web/views/queue.erb +2 -2
  23. data/web/views/queues.erb +2 -2
  24. data/web/views/retry.erb +1 -1
  25. metadata +74 -63
  26. data/test/config.yml +0 -9
  27. data/test/env_based_config.yml +0 -11
  28. data/test/fake_env.rb +0 -1
  29. data/test/fixtures/en.yml +0 -2
  30. data/test/helper.rb +0 -75
  31. data/test/test_actors.rb +0 -138
  32. data/test/test_api.rb +0 -528
  33. data/test/test_cli.rb +0 -418
  34. data/test/test_client.rb +0 -266
  35. data/test/test_exception_handler.rb +0 -56
  36. data/test/test_extensions.rb +0 -129
  37. data/test/test_fetch.rb +0 -50
  38. data/test/test_launcher.rb +0 -92
  39. data/test/test_logging.rb +0 -35
  40. data/test/test_manager.rb +0 -50
  41. data/test/test_middleware.rb +0 -158
  42. data/test/test_processor.rb +0 -249
  43. data/test/test_rails.rb +0 -22
  44. data/test/test_redis_connection.rb +0 -132
  45. data/test/test_retry.rb +0 -326
  46. data/test/test_retry_exhausted.rb +0 -149
  47. data/test/test_scheduled.rb +0 -115
  48. data/test/test_scheduling.rb +0 -58
  49. data/test/test_sidekiq.rb +0 -107
  50. data/test/test_testing.rb +0 -143
  51. data/test/test_testing_fake.rb +0 -359
  52. data/test/test_testing_inline.rb +0 -94
  53. data/test/test_util.rb +0 -13
  54. data/test/test_web.rb +0 -679
  55. data/test/test_web_helpers.rb +0 -54
@@ -1,528 +0,0 @@
1
- # frozen_string_literal: true
2
- require_relative 'helper'
3
- require 'sidekiq/api'
4
- require 'active_job'
5
- require 'action_mailer'
6
-
7
- class TestApi < Sidekiq::Test
8
- describe 'api' do
9
- before do
10
- Sidekiq.redis {|c| c.flushdb }
11
- end
12
-
13
- describe "stats" do
14
- it "is initially zero" do
15
- s = Sidekiq::Stats.new
16
- assert_equal 0, s.processed
17
- assert_equal 0, s.failed
18
- assert_equal 0, s.enqueued
19
- end
20
-
21
- describe "processed" do
22
- it "returns number of processed jobs" do
23
- Sidekiq.redis { |conn| conn.set("stat:processed", 5) }
24
- s = Sidekiq::Stats.new
25
- assert_equal 5, s.processed
26
- end
27
- end
28
-
29
- describe "failed" do
30
- it "returns number of failed jobs" do
31
- Sidekiq.redis { |conn| conn.set("stat:failed", 5) }
32
- s = Sidekiq::Stats.new
33
- assert_equal 5, s.failed
34
- end
35
- end
36
-
37
- describe "reset" do
38
- before do
39
- Sidekiq.redis do |conn|
40
- conn.set('stat:processed', 5)
41
- conn.set('stat:failed', 10)
42
- end
43
- end
44
-
45
- it 'will reset all stats by default' do
46
- Sidekiq::Stats.new.reset
47
- s = Sidekiq::Stats.new
48
- assert_equal 0, s.failed
49
- assert_equal 0, s.processed
50
- end
51
-
52
- it 'can reset individual stats' do
53
- Sidekiq::Stats.new.reset('failed')
54
- s = Sidekiq::Stats.new
55
- assert_equal 0, s.failed
56
- assert_equal 5, s.processed
57
- end
58
-
59
- it 'can accept anything that responds to #to_s' do
60
- Sidekiq::Stats.new.reset(:failed)
61
- s = Sidekiq::Stats.new
62
- assert_equal 0, s.failed
63
- assert_equal 5, s.processed
64
- end
65
-
66
- it 'ignores anything other than "failed" or "processed"' do
67
- Sidekiq::Stats.new.reset((1..10).to_a, ['failed'])
68
- s = Sidekiq::Stats.new
69
- assert_equal 0, s.failed
70
- assert_equal 5, s.processed
71
- end
72
- end
73
-
74
- describe "queues" do
75
- it "is initially empty" do
76
- s = Sidekiq::Stats::Queues.new
77
- assert_equal 0, s.lengths.size
78
- end
79
-
80
- it "returns a hash of queue and size in order" do
81
- Sidekiq.redis do |conn|
82
- conn.rpush 'queue:foo', '{}'
83
- conn.sadd 'queues', 'foo'
84
-
85
- 3.times { conn.rpush 'queue:bar', '{}' }
86
- conn.sadd 'queues', 'bar'
87
- end
88
-
89
- s = Sidekiq::Stats::Queues.new
90
- assert_equal ({ "foo" => 1, "bar" => 3 }), s.lengths
91
- assert_equal "bar", s.lengths.first.first
92
-
93
- assert_equal Sidekiq::Stats.new.queues, Sidekiq::Stats::Queues.new.lengths
94
- end
95
- end
96
-
97
- describe "enqueued" do
98
- it "returns total enqueued jobs" do
99
- Sidekiq.redis do |conn|
100
- conn.rpush 'queue:foo', '{}'
101
- conn.sadd 'queues', 'foo'
102
-
103
- 3.times { conn.rpush 'queue:bar', '{}' }
104
- conn.sadd 'queues', 'bar'
105
- end
106
-
107
- s = Sidekiq::Stats.new
108
- assert_equal 4, s.enqueued
109
- end
110
- end
111
-
112
- describe "over time" do
113
- before do
114
- require 'active_support/core_ext/time/conversions'
115
- @before = Time::DATE_FORMATS[:default]
116
- Time::DATE_FORMATS[:default] = "%d/%m/%Y %H:%M:%S"
117
- end
118
-
119
- after do
120
- Time::DATE_FORMATS[:default] = @before
121
- end
122
-
123
- describe "processed" do
124
- it 'retrieves hash of dates' do
125
- Sidekiq.redis do |c|
126
- c.incrby("stat:processed:2012-12-24", 4)
127
- c.incrby("stat:processed:2012-12-25", 1)
128
- c.incrby("stat:processed:2012-12-26", 6)
129
- c.incrby("stat:processed:2012-12-27", 2)
130
- end
131
- Time.stub(:now, Time.parse("2012-12-26 1:00:00 -0500")) do
132
- s = Sidekiq::Stats::History.new(2)
133
- assert_equal({ "2012-12-26" => 6, "2012-12-25" => 1 }, s.processed)
134
-
135
- s = Sidekiq::Stats::History.new(3)
136
- assert_equal({ "2012-12-26" => 6, "2012-12-25" => 1, "2012-12-24" => 4 }, s.processed)
137
-
138
- s = Sidekiq::Stats::History.new(2, Date.parse("2012-12-25"))
139
- assert_equal({ "2012-12-25" => 1, "2012-12-24" => 4 }, s.processed)
140
- end
141
- end
142
- end
143
-
144
- describe "failed" do
145
- it 'retrieves hash of dates' do
146
- Sidekiq.redis do |c|
147
- c.incrby("stat:failed:2012-12-24", 4)
148
- c.incrby("stat:failed:2012-12-25", 1)
149
- c.incrby("stat:failed:2012-12-26", 6)
150
- c.incrby("stat:failed:2012-12-27", 2)
151
- end
152
- Time.stub(:now, Time.parse("2012-12-26 1:00:00 -0500")) do
153
- s = Sidekiq::Stats::History.new(2)
154
- assert_equal ({ "2012-12-26" => 6, "2012-12-25" => 1 }), s.failed
155
-
156
- s = Sidekiq::Stats::History.new(3)
157
- assert_equal ({ "2012-12-26" => 6, "2012-12-25" => 1, "2012-12-24" => 4 }), s.failed
158
-
159
- s = Sidekiq::Stats::History.new(2, Date.parse("2012-12-25"))
160
- assert_equal ({ "2012-12-25" => 1, "2012-12-24" => 4 }), s.failed
161
- end
162
- end
163
- end
164
- end
165
- end
166
-
167
- describe 'with an empty database' do
168
- it 'shows queue as empty' do
169
- q = Sidekiq::Queue.new
170
- assert_equal 0, q.size
171
- assert_equal 0, q.latency
172
- end
173
-
174
- before do
175
- ActiveJob::Base.queue_adapter = :sidekiq
176
- ActiveJob::Base.logger = nil
177
- end
178
-
179
- class ApiMailer < ActionMailer::Base
180
- def test_email(*)
181
- end
182
- end
183
-
184
- class ApiJob < ActiveJob::Base
185
- def perform(*)
186
- end
187
- end
188
-
189
- class ApiWorker
190
- include Sidekiq::Worker
191
- end
192
-
193
- it 'can enumerate jobs' do
194
- q = Sidekiq::Queue.new
195
- Time.stub(:now, Time.new(2012, 12, 26)) do
196
- ApiWorker.perform_async(1, 'mike')
197
- assert_equal ['TestApi::ApiWorker'], q.map(&:klass)
198
-
199
- job = q.first
200
- assert_equal 24, job.jid.size
201
- assert_equal [1, 'mike'], job.args
202
- assert_equal Time.new(2012, 12, 26), job.enqueued_at
203
- end
204
- assert q.latency > 10_000_000
205
-
206
- q = Sidekiq::Queue.new('other')
207
- assert_equal 0, q.size
208
- end
209
-
210
- it 'has no enqueued_at time for jobs enqueued in the future' do
211
- job_id = ApiWorker.perform_in(100, 1, 'foo')
212
- job = Sidekiq::ScheduledSet.new.find_job(job_id)
213
- assert_nil job.enqueued_at
214
- end
215
-
216
- it 'unwraps delayed jobs' do
217
- Sidekiq::Queue.delay.foo(1,2,3)
218
- q = Sidekiq::Queue.new
219
- x = q.first
220
- assert_equal "Sidekiq::Queue.foo", x.display_class
221
- assert_equal [1,2,3], x.display_args
222
- end
223
-
224
- it 'unwraps ActiveJob jobs' do
225
- ApiJob.perform_later(1, 2, 3)
226
- q = Sidekiq::Queue.new
227
- x = q.first
228
- assert_equal "TestApi::ApiJob", x.display_class
229
- assert_equal [1,2,3], x.display_args
230
- end
231
-
232
- it 'unwraps ActionMailer jobs' do
233
- ApiMailer.test_email(1, 2, 3).deliver_later
234
- q = Sidekiq::Queue.new('mailers')
235
- x = q.first
236
- assert_equal "TestApi::ApiMailer#test_email", x.display_class
237
- assert_equal [1,2,3], x.display_args
238
- end
239
-
240
- it 'has no enqueued_at time for jobs enqueued in the future' do
241
- job_id = ApiWorker.perform_in(100, 1, 'foo')
242
- job = Sidekiq::ScheduledSet.new.find_job(job_id)
243
- assert_nil job.enqueued_at
244
- end
245
-
246
- it 'can delete jobs' do
247
- q = Sidekiq::Queue.new
248
- ApiWorker.perform_async(1, 'mike')
249
- assert_equal 1, q.size
250
-
251
- x = q.first
252
- assert_equal "TestApi::ApiWorker", x.display_class
253
- assert_equal [1,'mike'], x.display_args
254
-
255
- assert_equal [true], q.map(&:delete)
256
- assert_equal 0, q.size
257
- end
258
-
259
- it "can move scheduled job to queue" do
260
- remain_id = ApiWorker.perform_in(100, 1, 'jason')
261
- job_id = ApiWorker.perform_in(100, 1, 'jason')
262
- job = Sidekiq::ScheduledSet.new.find_job(job_id)
263
- q = Sidekiq::Queue.new
264
- job.add_to_queue
265
- queued_job = q.find_job(job_id)
266
- refute_nil queued_job
267
- assert_equal queued_job.jid, job_id
268
- assert_nil Sidekiq::ScheduledSet.new.find_job(job_id)
269
- refute_nil Sidekiq::ScheduledSet.new.find_job(remain_id)
270
- end
271
-
272
- it "handles multiple scheduled jobs when moving to queue" do
273
- jids = Sidekiq::Client.push_bulk('class' => ApiWorker,
274
- 'args' => [[1, 'jason'], [2, 'jason']],
275
- 'at' => Time.now.to_f)
276
- assert_equal 2, jids.size
277
- (remain_id, job_id) = jids
278
- job = Sidekiq::ScheduledSet.new.find_job(job_id)
279
- q = Sidekiq::Queue.new
280
- job.add_to_queue
281
- queued_job = q.find_job(job_id)
282
- refute_nil queued_job
283
- assert_equal queued_job.jid, job_id
284
- assert_nil Sidekiq::ScheduledSet.new.find_job(job_id)
285
- refute_nil Sidekiq::ScheduledSet.new.find_job(remain_id)
286
- end
287
-
288
- it 'can find job by id in sorted sets' do
289
- job_id = ApiWorker.perform_in(100, 1, 'jason')
290
- job = Sidekiq::ScheduledSet.new.find_job(job_id)
291
- refute_nil job
292
- assert_equal job_id, job.jid
293
- assert_in_delta job.latency, 0.0, 0.1
294
- end
295
-
296
- it 'can remove jobs when iterating over a sorted set' do
297
- # scheduled jobs must be greater than SortedSet#each underlying page size
298
- 51.times do
299
- ApiWorker.perform_in(100, 'aaron')
300
- end
301
- set = Sidekiq::ScheduledSet.new
302
- set.map(&:delete)
303
- assert_equal set.size, 0
304
- end
305
-
306
- it 'can remove jobs when iterating over a queue' do
307
- # initial queue size must be greater than Queue#each underlying page size
308
- 51.times do
309
- ApiWorker.perform_async(1, 'aaron')
310
- end
311
- q = Sidekiq::Queue.new
312
- q.map(&:delete)
313
- assert_equal q.size, 0
314
- end
315
-
316
- it 'can find job by id in queues' do
317
- q = Sidekiq::Queue.new
318
- job_id = ApiWorker.perform_async(1, 'jason')
319
- job = q.find_job(job_id)
320
- refute_nil job
321
- assert_equal job_id, job.jid
322
- end
323
-
324
- it 'can clear a queue' do
325
- q = Sidekiq::Queue.new
326
- 2.times { ApiWorker.perform_async(1, 'mike') }
327
- q.clear
328
-
329
- Sidekiq.redis do |conn|
330
- refute conn.smembers('queues').include?('foo')
331
- refute conn.exists('queue:foo')
332
- end
333
- end
334
-
335
- it 'can fetch by score' do
336
- same_time = Time.now.to_f
337
- add_retry('bob1', same_time)
338
- add_retry('bob2', same_time)
339
- r = Sidekiq::RetrySet.new
340
- assert_equal 2, r.fetch(same_time).size
341
- end
342
-
343
- it 'can fetch by score and jid' do
344
- same_time = Time.now.to_f
345
- add_retry('bob1', same_time)
346
- add_retry('bob2', same_time)
347
- r = Sidekiq::RetrySet.new
348
- assert_equal 1, r.fetch(same_time, 'bob1').size
349
- end
350
-
351
- it 'shows empty retries' do
352
- r = Sidekiq::RetrySet.new
353
- assert_equal 0, r.size
354
- end
355
-
356
- it 'can enumerate retries' do
357
- add_retry
358
-
359
- r = Sidekiq::RetrySet.new
360
- assert_equal 1, r.size
361
- array = r.to_a
362
- assert_equal 1, array.size
363
-
364
- retri = array.first
365
- assert_equal 'ApiWorker', retri.klass
366
- assert_equal 'default', retri.queue
367
- assert_equal 'bob', retri.jid
368
- assert_in_delta Time.now.to_f, retri.at.to_f, 0.02
369
- end
370
-
371
- it 'requires a jid to delete an entry' do
372
- start_time = Time.now.to_f
373
- add_retry('bob2', Time.now.to_f)
374
- assert_raises(ArgumentError) do
375
- Sidekiq::RetrySet.new.delete(start_time)
376
- end
377
- end
378
-
379
- it 'can delete a single retry from score and jid' do
380
- same_time = Time.now.to_f
381
- add_retry('bob1', same_time)
382
- add_retry('bob2', same_time)
383
- r = Sidekiq::RetrySet.new
384
- assert_equal 2, r.size
385
- Sidekiq::RetrySet.new.delete(same_time, 'bob1')
386
- assert_equal 1, r.size
387
- end
388
-
389
- it 'can retry a retry' do
390
- add_retry
391
- r = Sidekiq::RetrySet.new
392
- assert_equal 1, r.size
393
- r.first.retry
394
- assert_equal 0, r.size
395
- assert_equal 1, Sidekiq::Queue.new('default').size
396
- job = Sidekiq::Queue.new('default').first
397
- assert_equal 'bob', job.jid
398
- assert_equal 1, job['retry_count']
399
- end
400
-
401
- it 'can clear retries' do
402
- add_retry
403
- add_retry('test')
404
- r = Sidekiq::RetrySet.new
405
- assert_equal 2, r.size
406
- r.clear
407
- assert_equal 0, r.size
408
- end
409
-
410
- it 'can enumerate processes' do
411
- identity_string = "identity_string"
412
- odata = {
413
- 'pid' => 123,
414
- 'hostname' => Socket.gethostname,
415
- 'key' => identity_string,
416
- 'identity' => identity_string,
417
- 'started_at' => Time.now.to_f - 15,
418
- }
419
-
420
- time = Time.now.to_f
421
- Sidekiq.redis do |conn|
422
- conn.multi do
423
- conn.sadd('processes', odata['key'])
424
- conn.hmset(odata['key'], 'info', Sidekiq.dump_json(odata), 'busy', 10, 'beat', time)
425
- conn.sadd('processes', 'fake:pid')
426
- end
427
- end
428
-
429
- ps = Sidekiq::ProcessSet.new.to_a
430
- assert_equal 1, ps.size
431
- data = ps.first
432
- assert_equal 10, data['busy']
433
- assert_equal time, data['beat']
434
- assert_equal 123, data['pid']
435
- data.quiet!
436
- data.stop!
437
- signals_string = "#{odata['key']}-signals"
438
- assert_equal "TERM", Sidekiq.redis{|c| c.lpop(signals_string) }
439
- assert_equal "USR1", Sidekiq.redis{|c| c.lpop(signals_string) }
440
- end
441
-
442
- it 'can enumerate workers' do
443
- w = Sidekiq::Workers.new
444
- assert_equal 0, w.size
445
- w.each do
446
- assert false
447
- end
448
-
449
- hn = Socket.gethostname
450
- key = "#{hn}:#{$$}"
451
- pdata = { 'pid' => $$, 'hostname' => hn, 'started_at' => Time.now.to_i }
452
- Sidekiq.redis do |conn|
453
- conn.sadd('processes', key)
454
- conn.hmset(key, 'info', Sidekiq.dump_json(pdata), 'busy', 0, 'beat', Time.now.to_f)
455
- end
456
-
457
- s = "#{key}:workers"
458
- data = Sidekiq.dump_json({ 'payload' => {}, 'queue' => 'default', 'run_at' => Time.now.to_i })
459
- Sidekiq.redis do |c|
460
- c.hmset(s, '1234', data)
461
- end
462
-
463
- w.each do |p, x, y|
464
- assert_equal key, p
465
- assert_equal "1234", x
466
- assert_equal 'default', y['queue']
467
- assert_equal Time.now.year, Time.at(y['run_at']).year
468
- end
469
-
470
- s = "#{key}:workers"
471
- data = Sidekiq.dump_json({ 'payload' => {}, 'queue' => 'default', 'run_at' => (Time.now.to_i - 2*60*60) })
472
- Sidekiq.redis do |c|
473
- c.multi do
474
- c.hmset(s, '5678', data)
475
- c.hmset("b#{s}", '5678', data)
476
- end
477
- end
478
-
479
- assert_equal ['1234', '5678'], w.map { |_, tid, _| tid }
480
- end
481
-
482
- it 'can reschedule jobs' do
483
- add_retry('foo1')
484
- add_retry('foo2')
485
-
486
- retries = Sidekiq::RetrySet.new
487
- assert_equal 2, retries.size
488
- refute(retries.map { |r| r.score > (Time.now.to_f + 9) }.any?)
489
-
490
- retries.each do |retri|
491
- retri.reschedule(Time.now.to_f + 10) if retri.jid == 'foo2'
492
- end
493
-
494
- assert_equal 2, retries.size
495
- assert(retries.map { |r| r.score > (Time.now.to_f + 9) }.any?)
496
- end
497
-
498
- it 'prunes processes which have died' do
499
- data = { 'pid' => rand(10_000), 'hostname' => "app#{rand(1_000)}", 'started_at' => Time.now.to_f }
500
- key = "#{data['hostname']}:#{data['pid']}"
501
- Sidekiq.redis do |conn|
502
- conn.sadd('processes', key)
503
- conn.hmset(key, 'info', Sidekiq.dump_json(data), 'busy', 0, 'beat', Time.now.to_f)
504
- end
505
-
506
- ps = Sidekiq::ProcessSet.new
507
- assert_equal 1, ps.size
508
- assert_equal 1, ps.to_a.size
509
-
510
- Sidekiq.redis do |conn|
511
- conn.sadd('processes', "bar:987")
512
- conn.sadd('processes', "bar:986")
513
- end
514
-
515
- ps = Sidekiq::ProcessSet.new
516
- assert_equal 1, ps.size
517
- assert_equal 1, ps.to_a.size
518
- end
519
-
520
- def add_retry(jid = 'bob', at = Time.now.to_f)
521
- payload = Sidekiq.dump_json('class' => 'ApiWorker', 'args' => [1, 'mike'], 'queue' => 'default', 'jid' => jid, 'retry_count' => 2, 'failed_at' => Time.now.to_f)
522
- Sidekiq.redis do |conn|
523
- conn.zadd('retry', at.to_s, payload)
524
- end
525
- end
526
- end
527
- end
528
- end