sidekiq 3.5.4 → 5.2.7

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 (175) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +61 -0
  3. data/{Contributing.md → .github/contributing.md} +0 -0
  4. data/.github/issue_template.md +11 -0
  5. data/.gitignore +3 -0
  6. data/.travis.yml +5 -10
  7. data/4.0-Upgrade.md +53 -0
  8. data/5.0-Upgrade.md +56 -0
  9. data/COMM-LICENSE +13 -11
  10. data/Changes.md +376 -1
  11. data/Ent-Changes.md +201 -2
  12. data/Gemfile +14 -18
  13. data/LICENSE +1 -1
  14. data/Pro-3.0-Upgrade.md +44 -0
  15. data/Pro-4.0-Upgrade.md +35 -0
  16. data/Pro-Changes.md +307 -2
  17. data/README.md +34 -22
  18. data/Rakefile +3 -3
  19. data/bin/sidekiq +0 -1
  20. data/bin/sidekiqctl +13 -86
  21. data/bin/sidekiqload +23 -27
  22. data/code_of_conduct.md +50 -0
  23. data/lib/generators/sidekiq/templates/worker_spec.rb.erb +3 -3
  24. data/lib/generators/sidekiq/templates/worker_test.rb.erb +6 -6
  25. data/lib/sidekiq.rb +72 -25
  26. data/lib/sidekiq/api.rb +206 -73
  27. data/lib/sidekiq/cli.rb +145 -101
  28. data/lib/sidekiq/client.rb +42 -36
  29. data/lib/sidekiq/core_ext.rb +1 -105
  30. data/lib/sidekiq/ctl.rb +221 -0
  31. data/lib/sidekiq/delay.rb +42 -0
  32. data/lib/sidekiq/exception_handler.rb +4 -5
  33. data/lib/sidekiq/extensions/action_mailer.rb +1 -0
  34. data/lib/sidekiq/extensions/active_record.rb +1 -0
  35. data/lib/sidekiq/extensions/class_methods.rb +1 -0
  36. data/lib/sidekiq/extensions/generic_proxy.rb +8 -1
  37. data/lib/sidekiq/fetch.rb +36 -111
  38. data/lib/sidekiq/job_logger.rb +25 -0
  39. data/lib/sidekiq/job_retry.rb +262 -0
  40. data/lib/sidekiq/launcher.rb +129 -55
  41. data/lib/sidekiq/logging.rb +21 -3
  42. data/lib/sidekiq/manager.rb +83 -182
  43. data/lib/sidekiq/middleware/chain.rb +1 -0
  44. data/lib/sidekiq/middleware/i18n.rb +1 -0
  45. data/lib/sidekiq/middleware/server/active_record.rb +10 -0
  46. data/lib/sidekiq/paginator.rb +1 -0
  47. data/lib/sidekiq/processor.rb +221 -103
  48. data/lib/sidekiq/rails.rb +47 -27
  49. data/lib/sidekiq/redis_connection.rb +74 -7
  50. data/lib/sidekiq/scheduled.rb +87 -28
  51. data/lib/sidekiq/testing.rb +150 -19
  52. data/lib/sidekiq/testing/inline.rb +1 -0
  53. data/lib/sidekiq/util.rb +15 -17
  54. data/lib/sidekiq/version.rb +2 -1
  55. data/lib/sidekiq/web.rb +120 -184
  56. data/lib/sidekiq/web/action.rb +89 -0
  57. data/lib/sidekiq/web/application.rb +353 -0
  58. data/lib/sidekiq/{web_helpers.rb → web/helpers.rb} +123 -47
  59. data/lib/sidekiq/web/router.rb +100 -0
  60. data/lib/sidekiq/worker.rb +135 -18
  61. data/sidekiq.gemspec +8 -14
  62. data/web/assets/images/{status-sd8051fd480.png → status.png} +0 -0
  63. data/web/assets/javascripts/application.js +24 -20
  64. data/web/assets/javascripts/dashboard.js +33 -18
  65. data/web/assets/stylesheets/application-rtl.css +246 -0
  66. data/web/assets/stylesheets/application.css +401 -7
  67. data/web/assets/stylesheets/bootstrap-rtl.min.css +9 -0
  68. data/web/assets/stylesheets/bootstrap.css +4 -8
  69. data/web/locales/ar.yml +81 -0
  70. data/web/locales/cs.yml +11 -1
  71. data/web/locales/de.yml +1 -1
  72. data/web/locales/en.yml +4 -0
  73. data/web/locales/es.yml +4 -3
  74. data/web/locales/fa.yml +80 -0
  75. data/web/locales/fr.yml +21 -12
  76. data/web/locales/he.yml +79 -0
  77. data/web/locales/ja.yml +24 -13
  78. data/web/locales/ru.yml +3 -0
  79. data/web/locales/ur.yml +80 -0
  80. data/web/views/_footer.erb +7 -9
  81. data/web/views/_job_info.erb +5 -1
  82. data/web/views/_nav.erb +5 -19
  83. data/web/views/_paging.erb +1 -1
  84. data/web/views/busy.erb +18 -9
  85. data/web/views/dashboard.erb +5 -5
  86. data/web/views/dead.erb +1 -1
  87. data/web/views/layout.erb +13 -5
  88. data/web/views/morgue.erb +16 -12
  89. data/web/views/queue.erb +12 -11
  90. data/web/views/queues.erb +5 -3
  91. data/web/views/retries.erb +19 -13
  92. data/web/views/retry.erb +2 -2
  93. data/web/views/scheduled.erb +4 -4
  94. data/web/views/scheduled_job_info.erb +1 -1
  95. metadata +45 -227
  96. data/lib/sidekiq/actor.rb +0 -39
  97. data/lib/sidekiq/middleware/server/logging.rb +0 -40
  98. data/lib/sidekiq/middleware/server/retry_jobs.rb +0 -206
  99. data/test/config.yml +0 -9
  100. data/test/env_based_config.yml +0 -11
  101. data/test/fake_env.rb +0 -0
  102. data/test/fixtures/en.yml +0 -2
  103. data/test/helper.rb +0 -49
  104. data/test/test_api.rb +0 -493
  105. data/test/test_cli.rb +0 -335
  106. data/test/test_client.rb +0 -194
  107. data/test/test_exception_handler.rb +0 -55
  108. data/test/test_extensions.rb +0 -126
  109. data/test/test_fetch.rb +0 -104
  110. data/test/test_logging.rb +0 -34
  111. data/test/test_manager.rb +0 -168
  112. data/test/test_middleware.rb +0 -159
  113. data/test/test_processor.rb +0 -237
  114. data/test/test_rails.rb +0 -21
  115. data/test/test_redis_connection.rb +0 -126
  116. data/test/test_retry.rb +0 -325
  117. data/test/test_scheduled.rb +0 -114
  118. data/test/test_scheduling.rb +0 -49
  119. data/test/test_sidekiq.rb +0 -99
  120. data/test/test_testing.rb +0 -142
  121. data/test/test_testing_fake.rb +0 -268
  122. data/test/test_testing_inline.rb +0 -93
  123. data/test/test_util.rb +0 -16
  124. data/test/test_web.rb +0 -608
  125. data/test/test_web_helpers.rb +0 -53
  126. data/web/assets/images/bootstrap/glyphicons-halflings-white.png +0 -0
  127. data/web/assets/images/bootstrap/glyphicons-halflings.png +0 -0
  128. data/web/assets/images/status/active.png +0 -0
  129. data/web/assets/images/status/idle.png +0 -0
  130. data/web/assets/javascripts/locales/README.md +0 -27
  131. data/web/assets/javascripts/locales/jquery.timeago.ar.js +0 -96
  132. data/web/assets/javascripts/locales/jquery.timeago.bg.js +0 -18
  133. data/web/assets/javascripts/locales/jquery.timeago.bs.js +0 -49
  134. data/web/assets/javascripts/locales/jquery.timeago.ca.js +0 -18
  135. data/web/assets/javascripts/locales/jquery.timeago.cs.js +0 -18
  136. data/web/assets/javascripts/locales/jquery.timeago.cy.js +0 -20
  137. data/web/assets/javascripts/locales/jquery.timeago.da.js +0 -18
  138. data/web/assets/javascripts/locales/jquery.timeago.de.js +0 -18
  139. data/web/assets/javascripts/locales/jquery.timeago.el.js +0 -18
  140. data/web/assets/javascripts/locales/jquery.timeago.en-short.js +0 -20
  141. data/web/assets/javascripts/locales/jquery.timeago.en.js +0 -20
  142. data/web/assets/javascripts/locales/jquery.timeago.es.js +0 -18
  143. data/web/assets/javascripts/locales/jquery.timeago.et.js +0 -18
  144. data/web/assets/javascripts/locales/jquery.timeago.fa.js +0 -22
  145. data/web/assets/javascripts/locales/jquery.timeago.fi.js +0 -28
  146. data/web/assets/javascripts/locales/jquery.timeago.fr-short.js +0 -16
  147. data/web/assets/javascripts/locales/jquery.timeago.fr.js +0 -17
  148. data/web/assets/javascripts/locales/jquery.timeago.he.js +0 -18
  149. data/web/assets/javascripts/locales/jquery.timeago.hr.js +0 -49
  150. data/web/assets/javascripts/locales/jquery.timeago.hu.js +0 -18
  151. data/web/assets/javascripts/locales/jquery.timeago.hy.js +0 -18
  152. data/web/assets/javascripts/locales/jquery.timeago.id.js +0 -18
  153. data/web/assets/javascripts/locales/jquery.timeago.it.js +0 -16
  154. data/web/assets/javascripts/locales/jquery.timeago.ja.js +0 -19
  155. data/web/assets/javascripts/locales/jquery.timeago.ko.js +0 -17
  156. data/web/assets/javascripts/locales/jquery.timeago.lt.js +0 -20
  157. data/web/assets/javascripts/locales/jquery.timeago.mk.js +0 -20
  158. data/web/assets/javascripts/locales/jquery.timeago.nl.js +0 -20
  159. data/web/assets/javascripts/locales/jquery.timeago.no.js +0 -18
  160. data/web/assets/javascripts/locales/jquery.timeago.pl.js +0 -31
  161. data/web/assets/javascripts/locales/jquery.timeago.pt-br.js +0 -16
  162. data/web/assets/javascripts/locales/jquery.timeago.pt.js +0 -16
  163. data/web/assets/javascripts/locales/jquery.timeago.ro.js +0 -18
  164. data/web/assets/javascripts/locales/jquery.timeago.rs.js +0 -49
  165. data/web/assets/javascripts/locales/jquery.timeago.ru.js +0 -34
  166. data/web/assets/javascripts/locales/jquery.timeago.sk.js +0 -18
  167. data/web/assets/javascripts/locales/jquery.timeago.sl.js +0 -44
  168. data/web/assets/javascripts/locales/jquery.timeago.sv.js +0 -18
  169. data/web/assets/javascripts/locales/jquery.timeago.th.js +0 -20
  170. data/web/assets/javascripts/locales/jquery.timeago.tr.js +0 -16
  171. data/web/assets/javascripts/locales/jquery.timeago.uk.js +0 -34
  172. data/web/assets/javascripts/locales/jquery.timeago.uz.js +0 -19
  173. data/web/assets/javascripts/locales/jquery.timeago.zh-cn.js +0 -20
  174. data/web/assets/javascripts/locales/jquery.timeago.zh-tw.js +0 -20
  175. data/web/views/_poll_js.erb +0 -5
@@ -1,93 +0,0 @@
1
- require_relative 'helper'
2
-
3
- require 'active_record'
4
- require 'action_mailer'
5
- require 'sidekiq/rails'
6
- require 'sidekiq/extensions/action_mailer'
7
- require 'sidekiq/extensions/active_record'
8
-
9
- Sidekiq.hook_rails!
10
-
11
- class TestInline < Sidekiq::Test
12
- describe 'sidekiq inline testing' do
13
- class InlineError < RuntimeError; end
14
- class ParameterIsNotString < RuntimeError; end
15
-
16
- class InlineWorker
17
- include Sidekiq::Worker
18
- def perform(pass)
19
- raise ArgumentError, "no jid" unless jid
20
- raise InlineError unless pass
21
- end
22
- end
23
-
24
- class InlineWorkerWithTimeParam
25
- include Sidekiq::Worker
26
- def perform(time)
27
- raise ParameterIsNotString unless time.is_a?(String) || time.is_a?(Numeric)
28
- end
29
- end
30
-
31
- class InlineFooMailer < ActionMailer::Base
32
- def bar(str)
33
- raise InlineError
34
- end
35
- end
36
-
37
- class InlineFooModel < ActiveRecord::Base
38
- def self.bar(str)
39
- raise InlineError
40
- end
41
- end
42
-
43
- before do
44
- require 'sidekiq/testing/inline'
45
- Sidekiq::Testing.inline!
46
- end
47
-
48
- after do
49
- Sidekiq::Testing.disable!
50
- end
51
-
52
- it 'stubs the async call when in testing mode' do
53
- assert InlineWorker.perform_async(true)
54
-
55
- assert_raises InlineError do
56
- InlineWorker.perform_async(false)
57
- end
58
- end
59
-
60
- it 'stubs the delay call on mailers' do
61
- assert_raises InlineError do
62
- InlineFooMailer.delay.bar('three')
63
- end
64
- end
65
-
66
- it 'stubs the delay call on models' do
67
- assert_raises InlineError do
68
- InlineFooModel.delay.bar('three')
69
- end
70
- end
71
-
72
- it 'stubs the enqueue call when in testing mode' do
73
- assert Sidekiq::Client.enqueue(InlineWorker, true)
74
-
75
- assert_raises InlineError do
76
- Sidekiq::Client.enqueue(InlineWorker, false)
77
- end
78
- end
79
-
80
- it 'stubs the push_bulk call when in testing mode' do
81
- assert Sidekiq::Client.push_bulk({'class' => InlineWorker, 'args' => [[true], [true]]})
82
-
83
- assert_raises InlineError do
84
- Sidekiq::Client.push_bulk({'class' => InlineWorker, 'args' => [[true], [false]]})
85
- end
86
- end
87
-
88
- it 'should relay parameters through json' do
89
- assert Sidekiq::Client.enqueue(InlineWorkerWithTimeParam, Time.now)
90
- end
91
-
92
- end
93
- end
@@ -1,16 +0,0 @@
1
- require_relative 'helper'
2
-
3
- class TestUtil < Sidekiq::Test
4
-
5
- class Helpers
6
- include Sidekiq::Util
7
- end
8
-
9
- def test_hertz_donut
10
- obj = Helpers.new
11
- output = capture_logging(Logger::DEBUG) do
12
- assert_equal false, obj.want_a_hertz_donut?
13
- end
14
- assert_includes output, "hz: 10"
15
- end
16
- end
@@ -1,608 +0,0 @@
1
- # encoding: utf-8
2
- require_relative 'helper'
3
- require 'sidekiq/web'
4
- require 'rack/test'
5
- require 'tilt/erubis'
6
-
7
- class TestWeb < Sidekiq::Test
8
-
9
- describe 'sidekiq web' do
10
- include Rack::Test::Methods
11
-
12
- def app
13
- Sidekiq::Web
14
- end
15
-
16
- def job_params(job, score)
17
- "#{score}-#{job['jid']}"
18
- end
19
-
20
- before do
21
- Sidekiq.redis {|c| c.flushdb }
22
- end
23
-
24
- class WebWorker
25
- include Sidekiq::Worker
26
-
27
- def perform(a, b)
28
- a + b
29
- end
30
- end
31
-
32
- it 'can show text with any locales' do
33
- rackenv = {'HTTP_ACCEPT_LANGUAGE' => 'ru,en'}
34
- get '/', {}, rackenv
35
- assert_match(/Панель управления/, last_response.body)
36
- rackenv = {'HTTP_ACCEPT_LANGUAGE' => 'es,en'}
37
- get '/', {}, rackenv
38
- assert_match(/Panel de Control/, last_response.body)
39
- rackenv = {'HTTP_ACCEPT_LANGUAGE' => 'en-us'}
40
- get '/', {}, rackenv
41
- assert_match(/Dashboard/, last_response.body)
42
- rackenv = {'HTTP_ACCEPT_LANGUAGE' => 'zh-cn'}
43
- get '/', {}, rackenv
44
- assert_match(/信息板/, last_response.body)
45
- rackenv = {'HTTP_ACCEPT_LANGUAGE' => 'zh-tw'}
46
- get '/', {}, rackenv
47
- assert_match(/資訊主頁/, last_response.body)
48
- rackenv = {'HTTP_ACCEPT_LANGUAGE' => 'nb'}
49
- get '/', {}, rackenv
50
- assert_match(/Oversikt/, last_response.body)
51
- end
52
-
53
- describe 'busy' do
54
-
55
- it 'can display workers' do
56
- Sidekiq.redis do |conn|
57
- conn.incr('busy')
58
- conn.sadd('processes', 'foo:1234')
59
- conn.hmset('foo:1234', 'info', Sidekiq.dump_json('hostname' => 'foo', 'started_at' => Time.now.to_f, "queues" => []), 'at', Time.now.to_f, 'busy', 4)
60
- identity = 'foo:1234:workers'
61
- hash = {:queue => 'critical', :payload => { 'class' => WebWorker.name, 'args' => [1,'abc'] }, :run_at => Time.now.to_i }
62
- conn.hmset(identity, 1001, Sidekiq.dump_json(hash))
63
- end
64
- assert_equal ['1001'], Sidekiq::Workers.new.map { |pid, tid, data| tid }
65
-
66
- get '/busy'
67
- assert_equal 200, last_response.status
68
- assert_match(/status-active/, last_response.body)
69
- assert_match(/critical/, last_response.body)
70
- assert_match(/WebWorker/, last_response.body)
71
- end
72
-
73
- it 'can quiet a process' do
74
- identity = 'identity'
75
- signals_key = "#{identity}-signals"
76
-
77
- assert_nil Sidekiq.redis { |c| c.lpop signals_key }
78
- post '/busy', 'quiet' => '1', 'identity' => identity
79
- assert_equal 302, last_response.status
80
- assert_equal 'USR1', Sidekiq.redis { |c| c.lpop signals_key }
81
- end
82
-
83
- it 'can stop a process' do
84
- identity = 'identity'
85
- signals_key = "#{identity}-signals"
86
-
87
- assert_nil Sidekiq.redis { |c| c.lpop signals_key }
88
- post '/busy', 'stop' => '1', 'identity' => identity
89
- assert_equal 302, last_response.status
90
- assert_equal 'TERM', Sidekiq.redis { |c| c.lpop signals_key }
91
- end
92
- end
93
-
94
- it 'can display queues' do
95
- assert Sidekiq::Client.push('queue' => :foo, 'class' => WebWorker, 'args' => [1, 3])
96
-
97
- get '/queues'
98
- assert_equal 200, last_response.status
99
- assert_match(/foo/, last_response.body)
100
- refute_match(/HardWorker/, last_response.body)
101
- end
102
-
103
- it 'handles queue view' do
104
- get '/queues/default'
105
- assert_equal 200, last_response.status
106
- end
107
-
108
- it 'can delete a queue' do
109
- Sidekiq.redis do |conn|
110
- conn.rpush('queue:foo', '{}')
111
- conn.sadd('queues', 'foo')
112
- end
113
-
114
- get '/queues/foo'
115
- assert_equal 200, last_response.status
116
-
117
- post '/queues/foo'
118
- assert_equal 302, last_response.status
119
-
120
- Sidekiq.redis do |conn|
121
- refute conn.smembers('queues').include?('foo')
122
- refute conn.exists('queue:foo')
123
- end
124
- end
125
-
126
- it 'can delete a job' do
127
- Sidekiq.redis do |conn|
128
- conn.rpush('queue:foo', "{}")
129
- conn.rpush('queue:foo', "{\"foo\":\"bar\"}")
130
- conn.rpush('queue:foo', "{\"foo2\":\"bar2\"}")
131
- end
132
-
133
- get '/queues/foo'
134
- assert_equal 200, last_response.status
135
-
136
- post '/queues/foo/delete', key_val: "{\"foo\":\"bar\"}"
137
- assert_equal 302, last_response.status
138
-
139
- Sidekiq.redis do |conn|
140
- refute conn.lrange('queue:foo', 0, -1).include?("{\"foo\":\"bar\"}")
141
- end
142
- end
143
-
144
- it 'can display retries' do
145
- get '/retries'
146
- assert_equal 200, last_response.status
147
- assert_match(/found/, last_response.body)
148
- refute_match(/HardWorker/, last_response.body)
149
-
150
- add_retry
151
-
152
- get '/retries'
153
- assert_equal 200, last_response.status
154
- refute_match(/found/, last_response.body)
155
- assert_match(/HardWorker/, last_response.body)
156
- end
157
-
158
- it 'can display a single retry' do
159
- params = add_retry
160
- get '/retries/0-shouldntexist'
161
- assert_equal 302, last_response.status
162
- get "/retries/#{job_params(*params)}"
163
- assert_equal 200, last_response.status
164
- assert_match(/HardWorker/, last_response.body)
165
- end
166
-
167
- it 'handles missing retry' do
168
- get "/retries/0-shouldntexist"
169
- assert_equal 302, last_response.status
170
- end
171
-
172
- it 'can delete a single retry' do
173
- params = add_retry
174
- post "/retries/#{job_params(*params)}", 'delete' => 'Delete'
175
- assert_equal 302, last_response.status
176
- assert_equal 'http://example.org/retries', last_response.header['Location']
177
-
178
- get "/retries"
179
- assert_equal 200, last_response.status
180
- refute_match(/#{params.first['args'][2]}/, last_response.body)
181
- end
182
-
183
- it 'can delete all retries' do
184
- 3.times { add_retry }
185
-
186
- post "/retries/all/delete", 'delete' => 'Delete'
187
- assert_equal 0, Sidekiq::RetrySet.new.size
188
- assert_equal 302, last_response.status
189
- assert_equal 'http://example.org/retries', last_response.header['Location']
190
- end
191
-
192
- it 'can retry a single retry now' do
193
- params = add_retry
194
- post "/retries/#{job_params(*params)}", 'retry' => 'Retry'
195
- assert_equal 302, last_response.status
196
- assert_equal 'http://example.org/retries', last_response.header['Location']
197
-
198
- get '/queues/default'
199
- assert_equal 200, last_response.status
200
- assert_match(/#{params.first['args'][2]}/, last_response.body)
201
- end
202
-
203
- it 'can kill a single retry now' do
204
- params = add_retry
205
- post "/retries/#{job_params(*params)}", 'kill' => 'Kill'
206
- assert_equal 302, last_response.status
207
- assert_equal 'http://example.org/retries', last_response.header['Location']
208
-
209
- get '/morgue'
210
- assert_equal 200, last_response.status
211
- assert_match(/#{params.first['args'][2]}/, last_response.body)
212
- end
213
-
214
- it 'can display scheduled' do
215
- get '/scheduled'
216
- assert_equal 200, last_response.status
217
- assert_match(/found/, last_response.body)
218
- refute_match(/HardWorker/, last_response.body)
219
-
220
- add_scheduled
221
-
222
- get '/scheduled'
223
- assert_equal 200, last_response.status
224
- refute_match(/found/, last_response.body)
225
- assert_match(/HardWorker/, last_response.body)
226
- end
227
-
228
- it 'can display a single scheduled job' do
229
- params = add_scheduled
230
- get '/scheduled/0-shouldntexist'
231
- assert_equal 302, last_response.status
232
- get "/scheduled/#{job_params(*params)}"
233
- assert_equal 200, last_response.status
234
- assert_match(/HardWorker/, last_response.body)
235
- end
236
-
237
- it 'handles missing scheduled job' do
238
- get "/scheduled/0-shouldntexist"
239
- assert_equal 302, last_response.status
240
- end
241
-
242
- it 'can add to queue a single scheduled job' do
243
- params = add_scheduled
244
- post "/scheduled/#{job_params(*params)}", 'add_to_queue' => true
245
- assert_equal 302, last_response.status
246
- assert_equal 'http://example.org/scheduled', last_response.header['Location']
247
-
248
- get '/queues/default'
249
- assert_equal 200, last_response.status
250
- assert_match(/#{params.first['args'][2]}/, last_response.body)
251
- end
252
-
253
- it 'can delete a single scheduled job' do
254
- params = add_scheduled
255
- post "/scheduled/#{job_params(*params)}", 'delete' => 'Delete'
256
- assert_equal 302, last_response.status
257
- assert_equal 'http://example.org/scheduled', last_response.header['Location']
258
-
259
- get "/scheduled"
260
- assert_equal 200, last_response.status
261
- refute_match(/#{params.first['args'][2]}/, last_response.body)
262
- end
263
-
264
- it 'can delete scheduled' do
265
- params = add_scheduled
266
- Sidekiq.redis do |conn|
267
- assert_equal 1, conn.zcard('schedule')
268
- post '/scheduled', 'key' => [job_params(*params)], 'delete' => 'Delete'
269
- assert_equal 302, last_response.status
270
- assert_equal 'http://example.org/scheduled', last_response.header['Location']
271
- assert_equal 0, conn.zcard('schedule')
272
- end
273
- end
274
-
275
- it "can move scheduled to default queue" do
276
- q = Sidekiq::Queue.new
277
- params = add_scheduled
278
- Sidekiq.redis do |conn|
279
- assert_equal 1, conn.zcard('schedule')
280
- assert_equal 0, q.size
281
- post '/scheduled', 'key' => [job_params(*params)], 'add_to_queue' => 'AddToQueue'
282
- assert_equal 302, last_response.status
283
- assert_equal 'http://example.org/scheduled', last_response.header['Location']
284
- assert_equal 0, conn.zcard('schedule')
285
- assert_equal 1, q.size
286
- get '/queues/default'
287
- assert_equal 200, last_response.status
288
- assert_match(/#{params[0]['args'][2]}/, last_response.body)
289
- end
290
- end
291
-
292
- it 'can retry all retries' do
293
- msg = add_retry.first
294
- add_retry
295
-
296
- post "/retries/all/retry", 'retry' => 'Retry'
297
- assert_equal 302, last_response.status
298
- assert_equal 'http://example.org/retries', last_response.header['Location']
299
- assert_equal 2, Sidekiq::Queue.new("default").size
300
-
301
- get '/queues/default'
302
- assert_equal 200, last_response.status
303
- assert_match(/#{msg['args'][2]}/, last_response.body)
304
- end
305
-
306
- it 'calls updatePage() once when polling' do
307
- get '/busy?poll=true'
308
- assert_equal 200, last_response.status
309
- assert_equal 1, last_response.body.scan('updatePage(').count
310
- end
311
-
312
- it 'escape job args and error messages' do
313
- # on /retries page
314
- params = add_xss_retry
315
- get '/retries'
316
- assert_equal 200, last_response.status
317
- assert_match(/FailWorker/, last_response.body)
318
-
319
- assert last_response.body.include?( "fail message: &lt;a&gt;hello&lt;&#x2F;a&gt;" )
320
- assert !last_response.body.include?( "fail message: <a>hello</a>" )
321
-
322
- assert last_response.body.include?( "args\">&quot;&lt;a&gt;hello&lt;&#x2F;a&gt;&quot;<" )
323
- assert !last_response.body.include?( "args\"><a>hello</a><" )
324
-
325
- # on /workers page
326
- Sidekiq.redis do |conn|
327
- pro = 'foo:1234'
328
- conn.sadd('processes', pro)
329
- conn.hmset(pro, 'info', Sidekiq.dump_json('started_at' => Time.now.to_f, 'labels' => ['frumduz'], 'queues' =>[]), 'busy', 1, 'beat', Time.now.to_f)
330
- identity = "#{pro}:workers"
331
- hash = {:queue => 'critical', :payload => { 'class' => "FailWorker", 'args' => ["<a>hello</a>"] }, :run_at => Time.now.to_i }
332
- conn.hmset(identity, 100001, Sidekiq.dump_json(hash))
333
- conn.incr('busy')
334
- end
335
-
336
- get '/busy'
337
- assert_equal 200, last_response.status
338
- assert_match(/FailWorker/, last_response.body)
339
- assert_match(/frumduz/, last_response.body)
340
- assert last_response.body.include?( "&lt;a&gt;hello&lt;&#x2F;a&gt;" )
341
- assert !last_response.body.include?( "<a>hello</a>" )
342
-
343
-
344
- # on /queues page
345
- params = add_xss_retry # sorry, don't know how to easily make this show up on queues page otherwise.
346
- post "/retries/#{job_params(*params)}", 'retry' => 'Retry'
347
- assert_equal 302, last_response.status
348
-
349
- get '/queues/foo'
350
- assert_equal 200, last_response.status
351
- assert last_response.body.include?( "&lt;a&gt;hello&lt;&#x2F;a&gt;" )
352
- assert !last_response.body.include?( "<a>hello</a>" )
353
- end
354
-
355
- it 'can show user defined tab' do
356
- begin
357
- Sidekiq::Web.tabs['Custom Tab'] = '/custom'
358
-
359
- get '/'
360
- assert_match 'Custom Tab', last_response.body
361
-
362
- ensure
363
- Sidekiq::Web.tabs.delete 'Custom Tab'
364
- end
365
- end
366
-
367
- it 'can display home' do
368
- get '/'
369
- assert_equal 200, last_response.status
370
- end
371
-
372
- Sidekiq::Web.settings.locales << File.join(File.dirname(__FILE__), "fixtures")
373
- it 'can show user defined tab with custom locales' do
374
- begin
375
- Sidekiq::Web.tabs['Custom Tab'] = '/custom'
376
- Sidekiq::Web.get('/custom') do
377
- t('translated_text')
378
- end
379
-
380
- get '/custom'
381
- assert_match(/Changed text/, last_response.body)
382
-
383
- ensure
384
- Sidekiq::Web.tabs.delete 'Custom Tab'
385
- end
386
- end
387
-
388
- describe 'dashboard/stats' do
389
- it 'redirects to stats' do
390
- get '/dashboard/stats'
391
- assert_equal 302, last_response.status
392
- assert_equal 'http://example.org/stats', last_response.header['Location']
393
- end
394
- end
395
-
396
- describe 'stats' do
397
- include Sidekiq::Util
398
-
399
- before do
400
- Sidekiq.redis do |conn|
401
- conn.set("stat:processed", 5)
402
- conn.set("stat:failed", 2)
403
- conn.sadd("queues", "default")
404
- end
405
- 2.times { add_retry }
406
- 3.times { add_scheduled }
407
- 4.times { add_worker }
408
-
409
- get '/stats'
410
- @response = Sidekiq.load_json(last_response.body)
411
- end
412
-
413
- it 'can refresh dashboard stats' do
414
- assert_equal 200, last_response.status
415
- end
416
-
417
- describe "for sidekiq" do
418
- it 'are namespaced' do
419
- assert_includes @response.keys, "sidekiq"
420
- end
421
-
422
- it 'reports processed' do
423
- assert_equal 5, @response["sidekiq"]["processed"]
424
- end
425
-
426
- it 'reports failed' do
427
- assert_equal 2, @response["sidekiq"]["failed"]
428
- end
429
-
430
- it 'reports busy' do
431
- assert_equal 4, @response["sidekiq"]["busy"]
432
- end
433
-
434
- it 'reports processes' do
435
- assert_equal 1, @response["sidekiq"]["processes"]
436
- end
437
-
438
- it 'reports retries' do
439
- assert_equal 2, @response["sidekiq"]["retries"]
440
- end
441
-
442
- it 'reports scheduled' do
443
- assert_equal 3, @response["sidekiq"]["scheduled"]
444
- end
445
-
446
- it 'reports latency' do
447
- assert_equal 0, @response["sidekiq"]["default_latency"]
448
- end
449
- end
450
-
451
- describe "for redis" do
452
- it 'are namespaced' do
453
- assert_includes @response.keys, "redis"
454
- end
455
-
456
- it 'reports version' do
457
- assert_includes @response["redis"].keys, "redis_version"
458
- end
459
-
460
- it 'reports uptime' do
461
- assert_includes @response["redis"].keys, "uptime_in_days"
462
- end
463
-
464
- it 'reports connected clients' do
465
- assert_includes @response["redis"].keys, "connected_clients"
466
- end
467
-
468
- it 'reports user memory' do
469
- assert_includes @response["redis"].keys, "used_memory_human"
470
- end
471
-
472
- it 'reports memory peak' do
473
- assert_includes @response["redis"].keys, "used_memory_peak_human"
474
- end
475
- end
476
- end
477
-
478
- describe 'stats/queues' do
479
- include Sidekiq::Util
480
-
481
- before do
482
- Sidekiq.redis do |conn|
483
- conn.set("stat:processed", 5)
484
- conn.set("stat:failed", 2)
485
- conn.sadd("queues", "default")
486
- conn.sadd("queues", "queue2")
487
- end
488
- 2.times { add_retry }
489
- 3.times { add_scheduled }
490
- 4.times { add_worker }
491
-
492
- get '/stats/queues'
493
- @response = Sidekiq.load_json(last_response.body)
494
- end
495
-
496
- it 'reports the queue depth' do
497
- assert_equal 0, @response["default"]
498
- assert_equal 0, @response["queue2"]
499
- end
500
- end
501
-
502
- describe 'dead jobs' do
503
- it 'shows empty index' do
504
- get 'morgue'
505
- assert_equal 200, last_response.status
506
- end
507
-
508
- it 'shows index with jobs' do
509
- (_, score) = add_dead
510
- get 'morgue'
511
- assert_equal 200, last_response.status
512
- assert_match(/#{score}/, last_response.body)
513
- end
514
-
515
- it 'can delete all dead' do
516
- 3.times { add_dead }
517
-
518
- assert_equal 3, Sidekiq::DeadSet.new.size
519
- post "/morgue/all/delete", 'delete' => 'Delete'
520
- assert_equal 0, Sidekiq::DeadSet.new.size
521
- assert_equal 302, last_response.status
522
- assert_equal 'http://example.org/morgue', last_response.header['Location']
523
- end
524
-
525
- it 'can retry a dead job' do
526
- params = add_dead
527
- post "/morgue/#{job_params(*params)}", 'retry' => 'Retry'
528
- assert_equal 302, last_response.status
529
- assert_equal 'http://example.org/morgue', last_response.header['Location']
530
-
531
- get '/queues/foo'
532
- assert_equal 200, last_response.status
533
- assert_match(/#{params.first['args'][2]}/, last_response.body)
534
- end
535
- end
536
-
537
- def add_scheduled
538
- score = Time.now.to_f
539
- msg = { 'class' => 'HardWorker',
540
- 'args' => ['bob', 1, Time.now.to_f],
541
- 'jid' => SecureRandom.hex(12) }
542
- Sidekiq.redis do |conn|
543
- conn.zadd('schedule', score, Sidekiq.dump_json(msg))
544
- end
545
- [msg, score]
546
- end
547
-
548
- def add_retry
549
- msg = { 'class' => 'HardWorker',
550
- 'args' => ['bob', 1, Time.now.to_f],
551
- 'queue' => 'default',
552
- 'error_message' => 'Some fake message',
553
- 'error_class' => 'RuntimeError',
554
- 'retry_count' => 0,
555
- 'failed_at' => Time.now.to_f,
556
- 'jid' => SecureRandom.hex(12) }
557
- score = Time.now.to_f
558
- Sidekiq.redis do |conn|
559
- conn.zadd('retry', score, Sidekiq.dump_json(msg))
560
- end
561
- [msg, score]
562
- end
563
-
564
- def add_dead
565
- msg = { 'class' => 'HardWorker',
566
- 'args' => ['bob', 1, Time.now.to_f],
567
- 'queue' => 'foo',
568
- 'error_message' => 'Some fake message',
569
- 'error_class' => 'RuntimeError',
570
- 'retry_count' => 0,
571
- 'failed_at' => Time.now.utc,
572
- 'jid' => SecureRandom.hex(12) }
573
- score = Time.now.to_f
574
- Sidekiq.redis do |conn|
575
- conn.zadd('dead', score, Sidekiq.dump_json(msg))
576
- end
577
- [msg, score]
578
- end
579
-
580
- def add_xss_retry
581
- msg = { 'class' => 'FailWorker',
582
- 'args' => ['<a>hello</a>'],
583
- 'queue' => 'foo',
584
- 'error_message' => 'fail message: <a>hello</a>',
585
- 'error_class' => 'RuntimeError',
586
- 'retry_count' => 0,
587
- 'failed_at' => Time.now.to_f,
588
- 'jid' => SecureRandom.hex(12) }
589
- score = Time.now.to_f
590
- Sidekiq.redis do |conn|
591
- conn.zadd('retry', score, Sidekiq.dump_json(msg))
592
- end
593
- [msg, score]
594
- end
595
-
596
- def add_worker
597
- key = "#{hostname}:#{$$}"
598
- msg = "{\"queue\":\"default\",\"payload\":{\"retry\":true,\"queue\":\"default\",\"timeout\":20,\"backtrace\":5,\"class\":\"HardWorker\",\"args\":[\"bob\",10,5],\"jid\":\"2b5ad2b016f5e063a1c62872\"},\"run_at\":1361208995}"
599
- Sidekiq.redis do |conn|
600
- conn.multi do
601
- conn.sadd("processes", key)
602
- conn.hmset(key, 'info', Sidekiq.dump_json('hostname' => 'foo', 'started_at' => Time.now.to_f, "queues" => []), 'at', Time.now.to_f, 'busy', 4)
603
- conn.hmset("#{key}:workers", Time.now.to_f, msg)
604
- end
605
- end
606
- end
607
- end
608
- end