sidekiq 2.14.1 → 2.15.0

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 (54) hide show
  1. data/Changes.md +24 -0
  2. data/README.md +6 -3
  3. data/lib/sidekiq.rb +8 -0
  4. data/lib/sidekiq/api.rb +1 -1
  5. data/lib/sidekiq/cli.rb +1 -1
  6. data/lib/sidekiq/client.rb +24 -2
  7. data/lib/sidekiq/exception_handler.rb +2 -2
  8. data/lib/sidekiq/launcher.rb +38 -9
  9. data/lib/sidekiq/manager.rb +0 -3
  10. data/lib/sidekiq/testing.rb +65 -4
  11. data/lib/sidekiq/testing/inline.rb +27 -40
  12. data/lib/sidekiq/util.rb +1 -0
  13. data/lib/sidekiq/version.rb +1 -1
  14. data/lib/sidekiq/web.rb +16 -3
  15. data/lib/sidekiq/worker.rb +6 -8
  16. data/sidekiq.gemspec +4 -4
  17. data/test/helper.rb +8 -0
  18. data/test/test_api.rb +1 -1
  19. data/test/test_cli.rb +1 -1
  20. data/test/test_client.rb +23 -2
  21. data/test/test_exception_handler.rb +1 -1
  22. data/test/test_extensions.rb +1 -1
  23. data/test/test_fetch.rb +1 -1
  24. data/test/test_manager.rb +11 -18
  25. data/test/test_middleware.rb +1 -1
  26. data/test/test_processor.rb +1 -1
  27. data/test/test_redis_connection.rb +3 -3
  28. data/test/test_retry.rb +1 -1
  29. data/test/test_scheduled.rb +1 -1
  30. data/test/test_scheduling.rb +10 -2
  31. data/test/test_sidekiq.rb +2 -2
  32. data/test/test_testing.rb +43 -230
  33. data/test/test_testing_fake.rb +265 -0
  34. data/test/test_testing_inline.rb +4 -7
  35. data/test/test_util.rb +1 -1
  36. data/test/test_web.rb +1 -1
  37. data/web/assets/javascripts/dashboard.js +3 -1
  38. data/web/assets/stylesheets/application.css +84 -21
  39. data/web/assets/stylesheets/bootstrap.css +4 -15
  40. data/web/views/_nav.erb +12 -2
  41. data/web/views/_poll.erb +14 -0
  42. data/web/views/_status.erb +1 -1
  43. data/web/views/_summary.erb +23 -15
  44. data/web/views/_workers.erb +1 -1
  45. data/web/views/dashboard.erb +37 -34
  46. data/web/views/index.erb +2 -2
  47. data/web/views/layout.erb +3 -23
  48. data/web/views/queue.erb +4 -4
  49. data/web/views/queues.erb +1 -1
  50. data/web/views/retries.erb +10 -6
  51. data/web/views/retry.erb +1 -1
  52. data/web/views/scheduled.erb +2 -2
  53. data/web/views/scheduled_job_info.erb +1 -1
  54. metadata +13 -10
@@ -0,0 +1,265 @@
1
+ require 'helper'
2
+ require 'sidekiq'
3
+ require 'sidekiq/worker'
4
+ require 'active_record'
5
+ require 'action_mailer'
6
+ require 'sidekiq/rails'
7
+ require 'sidekiq/extensions/action_mailer'
8
+ require 'sidekiq/extensions/active_record'
9
+
10
+ Sidekiq.hook_rails!
11
+
12
+ class TestTesting < Sidekiq::Test
13
+ describe 'sidekiq testing' do
14
+ class PerformError < RuntimeError; end
15
+
16
+ class DirectWorker
17
+ include Sidekiq::Worker
18
+ def perform(a, b)
19
+ a + b
20
+ end
21
+ end
22
+
23
+ class EnqueuedWorker
24
+ include Sidekiq::Worker
25
+ def perform(a, b)
26
+ a + b
27
+ end
28
+ end
29
+
30
+ class StoredWorker
31
+ include Sidekiq::Worker
32
+ def perform(error)
33
+ raise PerformError if error
34
+ end
35
+ end
36
+
37
+ class FooMailer < ActionMailer::Base
38
+ def bar(str)
39
+ str
40
+ end
41
+ end
42
+
43
+ class FooModel < ActiveRecord::Base
44
+ def bar(str)
45
+ str
46
+ end
47
+ end
48
+
49
+ before do
50
+ require 'sidekiq/testing.rb'
51
+ Sidekiq::Testing.fake!
52
+ EnqueuedWorker.jobs.clear
53
+ DirectWorker.jobs.clear
54
+ end
55
+
56
+ after do
57
+ Sidekiq::Testing.disable!
58
+ end
59
+
60
+ it 'stubs the async call' do
61
+ assert_equal 0, DirectWorker.jobs.size
62
+ assert DirectWorker.perform_async(1, 2)
63
+ assert_equal 1, DirectWorker.jobs.size
64
+ assert DirectWorker.perform_in(10, 1, 2)
65
+ assert_equal 2, DirectWorker.jobs.size
66
+ assert DirectWorker.perform_at(10, 1, 2)
67
+ assert_equal 3, DirectWorker.jobs.size
68
+ assert_in_delta 10.seconds.from_now.to_f, DirectWorker.jobs.last['at'], 0.01
69
+ end
70
+
71
+ it 'stubs the delay call on mailers' do
72
+ assert_equal 0, Sidekiq::Extensions::DelayedMailer.jobs.size
73
+ FooMailer.delay.bar('hello!')
74
+ assert_equal 1, Sidekiq::Extensions::DelayedMailer.jobs.size
75
+ end
76
+
77
+ class Something
78
+ def self.foo(x)
79
+ end
80
+ end
81
+
82
+ it 'stubs the delay call on models' do
83
+ assert_equal 0, Sidekiq::Extensions::DelayedClass.jobs.size
84
+ Something.delay.foo(Date.today)
85
+ assert_equal 1, Sidekiq::Extensions::DelayedClass.jobs.size
86
+ end
87
+
88
+ it 'stubs the enqueue call' do
89
+ assert_equal 0, EnqueuedWorker.jobs.size
90
+ assert Sidekiq::Client.enqueue(EnqueuedWorker, 1, 2)
91
+ assert_equal 1, EnqueuedWorker.jobs.size
92
+ end
93
+
94
+ it 'stubs the enqueue_to call' do
95
+ assert_equal 0, EnqueuedWorker.jobs.size
96
+ assert Sidekiq::Client.enqueue_to('someq', EnqueuedWorker, 1, 2)
97
+ assert_equal 1, EnqueuedWorker.jobs.size
98
+ end
99
+
100
+ it 'executes all stored jobs' do
101
+ assert StoredWorker.perform_async(false)
102
+ assert StoredWorker.perform_async(true)
103
+
104
+ assert_equal 2, StoredWorker.jobs.size
105
+ assert_raises PerformError do
106
+ StoredWorker.drain
107
+ end
108
+ assert_equal 0, StoredWorker.jobs.size
109
+
110
+ end
111
+
112
+ class SpecificJidWorker
113
+ include Sidekiq::Worker
114
+ class_attribute :count
115
+ self.count = 0
116
+ def perform(worker_jid)
117
+ return unless worker_jid == self.jid
118
+ self.class.count += 1
119
+ end
120
+ end
121
+
122
+ it 'execute only jobs with assigned JID' do
123
+ 4.times do |i|
124
+ jid = SpecificJidWorker.perform_async(nil)
125
+ if i % 2 == 0
126
+ SpecificJidWorker.jobs[-1]["args"] = ["wrong_jid"]
127
+ else
128
+ SpecificJidWorker.jobs[-1]["args"] = [jid]
129
+ end
130
+ end
131
+
132
+ SpecificJidWorker.perform_one
133
+ assert_equal 0, SpecificJidWorker.count
134
+
135
+ SpecificJidWorker.perform_one
136
+ assert_equal 1, SpecificJidWorker.count
137
+
138
+ SpecificJidWorker.drain
139
+ assert_equal 2, SpecificJidWorker.count
140
+ end
141
+
142
+ it 'round trip serializes the job arguments' do
143
+ assert StoredWorker.perform_async(:mike)
144
+ job = StoredWorker.jobs.first
145
+ assert_equal "mike", job['args'].first
146
+ StoredWorker.clear
147
+ end
148
+
149
+ it 'perform_one runs only one job' do
150
+ DirectWorker.perform_async(1, 2)
151
+ DirectWorker.perform_async(3, 4)
152
+ assert_equal 2, DirectWorker.jobs.size
153
+
154
+ DirectWorker.perform_one
155
+ assert_equal 1, DirectWorker.jobs.size
156
+
157
+ DirectWorker.clear
158
+ end
159
+
160
+ it 'perform_one raise error upon empty queue' do
161
+ DirectWorker.clear
162
+ assert_raises Sidekiq::EmptyQueueError do
163
+ DirectWorker.perform_one
164
+ end
165
+ end
166
+
167
+ class FirstWorker
168
+ include Sidekiq::Worker
169
+ class_attribute :count
170
+ self.count = 0
171
+ def perform
172
+ self.class.count += 1
173
+ end
174
+ end
175
+
176
+ class SecondWorker
177
+ include Sidekiq::Worker
178
+ class_attribute :count
179
+ self.count = 0
180
+ def perform
181
+ self.class.count += 1
182
+ end
183
+ end
184
+
185
+ class ThirdWorker
186
+ include Sidekiq::Worker
187
+ class_attribute :count
188
+ def perform
189
+ FirstWorker.perform_async
190
+ SecondWorker.perform_async
191
+ end
192
+ end
193
+
194
+ it 'clears jobs across all workers' do
195
+ Sidekiq::Worker.jobs.clear
196
+ FirstWorker.count = 0
197
+ SecondWorker.count = 0
198
+
199
+ assert_equal 0, FirstWorker.jobs.size
200
+ assert_equal 0, SecondWorker.jobs.size
201
+
202
+ FirstWorker.perform_async
203
+ SecondWorker.perform_async
204
+
205
+ assert_equal 1, FirstWorker.jobs.size
206
+ assert_equal 1, SecondWorker.jobs.size
207
+
208
+ Sidekiq::Worker.clear_all
209
+
210
+ assert_equal 0, FirstWorker.jobs.size
211
+ assert_equal 0, SecondWorker.jobs.size
212
+
213
+ assert_equal 0, FirstWorker.count
214
+ assert_equal 0, SecondWorker.count
215
+ end
216
+
217
+ it 'drains jobs across all workers' do
218
+ Sidekiq::Worker.jobs.clear
219
+ FirstWorker.count = 0
220
+ SecondWorker.count = 0
221
+
222
+ assert_equal 0, FirstWorker.jobs.size
223
+ assert_equal 0, SecondWorker.jobs.size
224
+
225
+ assert_equal 0, FirstWorker.count
226
+ assert_equal 0, SecondWorker.count
227
+
228
+ FirstWorker.perform_async
229
+ SecondWorker.perform_async
230
+
231
+ assert_equal 1, FirstWorker.jobs.size
232
+ assert_equal 1, SecondWorker.jobs.size
233
+
234
+ Sidekiq::Worker.drain_all
235
+
236
+ assert_equal 0, FirstWorker.jobs.size
237
+ assert_equal 0, SecondWorker.jobs.size
238
+
239
+ assert_equal 1, FirstWorker.count
240
+ assert_equal 1, SecondWorker.count
241
+ end
242
+
243
+ it 'drains jobs across all workers even when workers create new jobs' do
244
+ Sidekiq::Worker.jobs.clear
245
+ FirstWorker.count = 0
246
+ SecondWorker.count = 0
247
+
248
+ assert_equal 0, ThirdWorker.jobs.size
249
+
250
+ assert_equal 0, FirstWorker.count
251
+ assert_equal 0, SecondWorker.count
252
+
253
+ ThirdWorker.perform_async
254
+
255
+ assert_equal 1, ThirdWorker.jobs.size
256
+
257
+ Sidekiq::Worker.drain_all
258
+
259
+ assert_equal 0, ThirdWorker.jobs.size
260
+
261
+ assert_equal 1, FirstWorker.count
262
+ assert_equal 1, SecondWorker.count
263
+ end
264
+ end
265
+ end
@@ -9,7 +9,7 @@ require 'sidekiq/extensions/active_record'
9
9
 
10
10
  Sidekiq.hook_rails!
11
11
 
12
- class TestInline < Minitest::Test
12
+ class TestInline < Sidekiq::Test
13
13
  describe 'sidekiq inline testing' do
14
14
  class InlineError < RuntimeError; end
15
15
  class ParameterIsNotString < RuntimeError; end
@@ -41,15 +41,12 @@ class TestInline < Minitest::Test
41
41
  end
42
42
 
43
43
  before do
44
- load 'sidekiq/testing/inline.rb'
44
+ require 'sidekiq/testing/inline.rb'
45
+ Sidekiq::Testing.inline!
45
46
  end
46
47
 
47
48
  after do
48
- Sidekiq::Client.singleton_class.class_eval do
49
- remove_method :raw_push
50
- alias_method :raw_push, :raw_push_old
51
- remove_method :raw_push_old
52
- end
49
+ Sidekiq::Testing.disable!
53
50
  end
54
51
 
55
52
  it 'stubs the async call when in testing mode' do
@@ -1,7 +1,7 @@
1
1
  require 'helper'
2
2
  require 'sidekiq/util'
3
3
 
4
- class TestUtil < Minitest::Test
4
+ class TestUtil < Sidekiq::Test
5
5
  describe 'util' do
6
6
  it 'generates the same process id when included in two or more classes' do
7
7
  class One
@@ -3,7 +3,7 @@ require 'sidekiq'
3
3
  require 'sidekiq/web'
4
4
  require 'rack/test'
5
5
 
6
- class TestWeb < Minitest::Test
6
+ class TestWeb < Sidekiq::Test
7
7
  describe 'sidekiq web' do
8
8
  include Rack::Test::Methods
9
9
 
@@ -6,7 +6,9 @@ n){return arguments.length?(t=+n,e):t},e.translate=function(t){return arguments.
6
6
 
7
7
  // Match width of graphs with summary bar
8
8
  var responsiveWidth = function() {
9
- return document.getElementsByClassName('summary_bar')[0].clientWidth;
9
+ //Bootstrap now uses padding instead of margin for gutters. 30px (15 on each side)
10
+ //http://getbootstrap.com/css/#grid
11
+ return document.getElementsByClassName('summary_bar')[0].clientWidth - 30;
10
12
  };
11
13
 
12
14
  // Richshaw
@@ -32,7 +32,7 @@ h1, h2, h3, h4, h5, h6, strong {
32
32
  font-weight: 700;
33
33
  }
34
34
 
35
- .brand, .navbar .brand, h5, h4, h3, h2, h1 {
35
+ .navbar-brand, .navbar .navbar-brand, h5, h4, h3, h2, h1 {
36
36
  font-family: Armata;
37
37
  font-weight: 400;
38
38
  }
@@ -79,7 +79,7 @@ h3 {
79
79
  }
80
80
 
81
81
  .admin #page {
82
- padding: 60px 0 40px 0;
82
+ padding: 60px 0;
83
83
  }
84
84
 
85
85
  .row.header .actions {
@@ -113,10 +113,15 @@ header.row .pagination {
113
113
  margin-bottom: 10px;
114
114
  border-width: 0px;
115
115
  }
116
- .summary_bar #live-poll {
117
- line-height: 28px;
116
+ .poll-wrapper {
117
+ padding: 9px 0 0 0;
118
118
  }
119
- .summary_bar #live-poll.active {
119
+ .nav #live-poll {
120
+ height: 25px;
121
+ line-height: 25px;
122
+ width: 195px;
123
+ }
124
+ #live-poll.active {
120
125
  background-color: #009300;
121
126
  }
122
127
  .summary_bar ul {
@@ -144,21 +149,21 @@ header.row .pagination {
144
149
  }
145
150
  }
146
151
  @media (max-width: 979px) and (min-width: 768px) {
147
- .summary_bar ul li.span2 {
152
+ .summary_bar ul li.col-sm-2 {
148
153
  margin: 0px 10px;
149
154
  width: 96px !important;
150
155
  }
151
156
  }
152
- @media (max-width: 1199px) and (min-width: 980px) {
153
- .summary_bar ul li.span2 {
157
+ /*@media (max-width: 1199px) and (min-width: 980px) {
158
+ .summary_bar ul li.col-sm-2 {
154
159
  width: 130px !important;
155
160
  }
156
161
  }
157
162
  @media (min-width: 1200px) {
158
- .summary_bar ul li.span2 {
163
+ .summary_bar ul li.col-sm-2 {
159
164
  width: 154px !important;
160
165
  }
161
- }
166
+ }*/
162
167
  .summary_bar ul .desc {
163
168
  display: block;
164
169
  font-size: 1em;
@@ -191,11 +196,16 @@ td form {
191
196
  margin-bottom: 0;
192
197
  }
193
198
 
194
- .navbar .brand {
199
+ .navbar .navbar-brand {
195
200
  color: #b1003e;
201
+ padding: 13px;
196
202
  text-shadow: none;
197
203
  }
198
204
 
205
+ .navbar .navbar-brand .status {
206
+ color: #585454;
207
+ }
208
+
199
209
  .navbar-footer .navbar ul.nav {
200
210
  text-align: center;
201
211
  float: none;
@@ -206,7 +216,7 @@ td form {
206
216
  padding: 15px;
207
217
  }
208
218
 
209
- .navbar-footer .navbar ul.nav a.brand {
219
+ .navbar-footer .navbar ul.nav a.navbar-brand {
210
220
  font-weight: 400;
211
221
  padding: 0 15px 0 0;
212
222
  }
@@ -232,16 +242,17 @@ img.smallogo {
232
242
 
233
243
  .status-sprite {
234
244
  background-image: url(../images/status-sd8051fd480.png);
235
- height: 30px;
236
- width: 30px;
245
+ height: 19px;
246
+ width: 20px;
237
247
  display: inline-block;
248
+ background-size: 20px;
238
249
  }
239
250
  .status-active {
240
251
  background-position: 0 0;
241
252
  }
242
253
 
243
254
  .status-idle {
244
- background-position: 0 -80px;
255
+ background-position: 0 -54px;
245
256
  }
246
257
 
247
258
  .btn {
@@ -291,6 +302,15 @@ img.smallogo {
291
302
  padding: 10px 0;
292
303
  }
293
304
 
305
+ .redis-wrapper {
306
+ width: 100%;
307
+ text-align: center;
308
+ }
309
+
310
+ .stats-container {
311
+ display: inline-block;
312
+ }
313
+
294
314
  .stat {
295
315
  float: left;
296
316
  text-align: center;
@@ -301,10 +321,33 @@ img.smallogo {
301
321
  margin-bottom: 20px;
302
322
  }
303
323
 
324
+ .stat:last-child {
325
+ margin-right: 0;
326
+ }
327
+
304
328
  .stat p {
305
329
  font-size: 0.9em;
306
330
  }
307
-
331
+ @media (max-width: 767px) {
332
+ .stats-container {
333
+ display: block;
334
+ }
335
+ .stat {
336
+ float: left;
337
+ margin-right: 10px;
338
+ width: 100%;
339
+ text-align: left;
340
+ line-height: 45px;
341
+ }
342
+ .stat h3{
343
+ float: right;
344
+ margin: 5px 10px 5px 5px;
345
+ }
346
+ .stat p{
347
+ font-size: normal;
348
+ margin: 5px 5px 5px 10px;
349
+ }
350
+ }
308
351
  .beacon {
309
352
  position: relative;
310
353
  height: 20px;
@@ -482,13 +525,14 @@ img.smallogo {
482
525
  text-decoration: none;
483
526
  }
484
527
 
485
- @media (max-width: 550px) {
528
+ @media (max-width: 768px) {
486
529
  .navbar .container {
487
530
  text-align: center
488
531
  }
489
532
 
490
- .navbar .brand {
533
+ .navbar .navbar-brand {
491
534
  float: none;
535
+ display: block;
492
536
  }
493
537
 
494
538
  .navbar ul.nav li a {
@@ -506,6 +550,11 @@ img.smallogo {
506
550
  margin-right: 0;
507
551
  }
508
552
 
553
+ .poll-wrapper {
554
+ padding: 0px 20px 5px 0px;
555
+ width: 20%;
556
+ }
557
+
509
558
  .navbar.navbar-fixed-bottom ul {
510
559
  float: none;
511
560
  margin-right: 0;
@@ -517,6 +566,7 @@ img.smallogo {
517
566
  }
518
567
 
519
568
  .navbar-text {
569
+ float:none;
520
570
  line-height: 30px;
521
571
  }
522
572
  }
@@ -532,7 +582,7 @@ img.smallogo {
532
582
  }
533
583
 
534
584
  @media (max-width: 500px) {
535
- .navbar-footer .navbar ul.nav a.brand {
585
+ .navbar-footer .navbar ul.nav a.navbar-brand {
536
586
  padding-right: 5px;
537
587
  }
538
588
  }
@@ -846,10 +896,23 @@ img.smallogo {
846
896
  border-radius: 3px;
847
897
  }
848
898
  .args {
849
- overflow: scroll;
899
+ overflow-y: scroll;
850
900
  max-height: 100px;
851
901
  }
852
902
  .args-extended {
853
- overflow: scroll;
903
+ overflow-y: scroll;
854
904
  max-height: 500px;
855
905
  }
906
+
907
+
908
+ /* BOOTSTRAP 3 FIXES */
909
+ /* @grid-float-breakpoint -1 */
910
+ .container {
911
+ padding: 0;
912
+ }
913
+ @media (max-width: 979px) {
914
+ .navbar-fixed-top, .navbar-fixed-bottom {
915
+ position: relative;
916
+ top: auto;
917
+ }
918
+ }