sidekiq 3.4.1 → 7.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (235) hide show
  1. checksums.yaml +5 -5
  2. data/Changes.md +1118 -4
  3. data/LICENSE.txt +9 -0
  4. data/README.md +55 -47
  5. data/bin/multi_queue_bench +271 -0
  6. data/bin/sidekiq +26 -3
  7. data/bin/sidekiqload +247 -0
  8. data/bin/sidekiqmon +11 -0
  9. data/lib/generators/sidekiq/job_generator.rb +57 -0
  10. data/lib/generators/sidekiq/templates/{worker.rb.erb → job.rb.erb} +2 -2
  11. data/lib/generators/sidekiq/templates/job_spec.rb.erb +6 -0
  12. data/lib/generators/sidekiq/templates/job_test.rb.erb +8 -0
  13. data/lib/sidekiq/api.rb +714 -312
  14. data/lib/sidekiq/capsule.rb +130 -0
  15. data/lib/sidekiq/cli.rb +275 -241
  16. data/lib/sidekiq/client.rb +141 -110
  17. data/lib/sidekiq/component.rb +68 -0
  18. data/lib/sidekiq/config.rb +291 -0
  19. data/lib/sidekiq/deploy.rb +62 -0
  20. data/lib/sidekiq/embedded.rb +61 -0
  21. data/lib/sidekiq/fetch.rb +53 -121
  22. data/lib/sidekiq/iterable_job.rb +53 -0
  23. data/lib/sidekiq/job/interrupt_handler.rb +22 -0
  24. data/lib/sidekiq/job/iterable/active_record_enumerator.rb +53 -0
  25. data/lib/sidekiq/job/iterable/csv_enumerator.rb +47 -0
  26. data/lib/sidekiq/job/iterable/enumerators.rb +135 -0
  27. data/lib/sidekiq/job/iterable.rb +231 -0
  28. data/lib/sidekiq/job.rb +385 -0
  29. data/lib/sidekiq/job_logger.rb +64 -0
  30. data/lib/sidekiq/job_retry.rb +305 -0
  31. data/lib/sidekiq/job_util.rb +107 -0
  32. data/lib/sidekiq/launcher.rb +241 -66
  33. data/lib/sidekiq/logger.rb +131 -0
  34. data/lib/sidekiq/manager.rb +91 -192
  35. data/lib/sidekiq/metrics/query.rb +156 -0
  36. data/lib/sidekiq/metrics/shared.rb +95 -0
  37. data/lib/sidekiq/metrics/tracking.rb +140 -0
  38. data/lib/sidekiq/middleware/chain.rb +114 -56
  39. data/lib/sidekiq/middleware/current_attributes.rb +111 -0
  40. data/lib/sidekiq/middleware/i18n.rb +8 -7
  41. data/lib/sidekiq/middleware/modules.rb +21 -0
  42. data/lib/sidekiq/monitor.rb +146 -0
  43. data/lib/sidekiq/paginator.rb +29 -16
  44. data/lib/sidekiq/processor.rb +248 -112
  45. data/lib/sidekiq/rails.rb +61 -27
  46. data/lib/sidekiq/redis_client_adapter.rb +114 -0
  47. data/lib/sidekiq/redis_connection.rb +68 -48
  48. data/lib/sidekiq/ring_buffer.rb +29 -0
  49. data/lib/sidekiq/scheduled.rb +173 -52
  50. data/lib/sidekiq/sd_notify.rb +149 -0
  51. data/lib/sidekiq/systemd.rb +24 -0
  52. data/lib/sidekiq/testing/inline.rb +7 -5
  53. data/lib/sidekiq/testing.rb +206 -65
  54. data/lib/sidekiq/transaction_aware_client.rb +51 -0
  55. data/lib/sidekiq/version.rb +4 -1
  56. data/lib/sidekiq/web/action.rb +99 -0
  57. data/lib/sidekiq/web/application.rb +479 -0
  58. data/lib/sidekiq/web/csrf_protection.rb +183 -0
  59. data/lib/sidekiq/web/helpers.rb +415 -0
  60. data/lib/sidekiq/web/router.rb +104 -0
  61. data/lib/sidekiq/web.rb +158 -200
  62. data/lib/sidekiq/worker_compatibility_alias.rb +13 -0
  63. data/lib/sidekiq.rb +100 -132
  64. data/sidekiq.gemspec +27 -23
  65. data/web/assets/images/apple-touch-icon.png +0 -0
  66. data/web/assets/images/favicon.ico +0 -0
  67. data/web/assets/javascripts/application.js +177 -72
  68. data/web/assets/javascripts/base-charts.js +106 -0
  69. data/web/assets/javascripts/chart.min.js +13 -0
  70. data/web/assets/javascripts/chartjs-plugin-annotation.min.js +7 -0
  71. data/web/assets/javascripts/dashboard-charts.js +192 -0
  72. data/web/assets/javascripts/dashboard.js +37 -286
  73. data/web/assets/javascripts/metrics.js +298 -0
  74. data/web/assets/stylesheets/application-dark.css +147 -0
  75. data/web/assets/stylesheets/application-rtl.css +163 -0
  76. data/web/assets/stylesheets/application.css +228 -247
  77. data/web/assets/stylesheets/bootstrap-rtl.min.css +9 -0
  78. data/web/assets/stylesheets/bootstrap.css +4 -8
  79. data/web/locales/ar.yml +87 -0
  80. data/web/locales/cs.yml +62 -52
  81. data/web/locales/da.yml +60 -53
  82. data/web/locales/de.yml +65 -53
  83. data/web/locales/el.yml +43 -24
  84. data/web/locales/en.yml +86 -61
  85. data/web/locales/es.yml +70 -53
  86. data/web/locales/fa.yml +80 -0
  87. data/web/locales/fr.yml +86 -56
  88. data/web/locales/gd.yml +99 -0
  89. data/web/locales/he.yml +80 -0
  90. data/web/locales/hi.yml +59 -59
  91. data/web/locales/it.yml +53 -53
  92. data/web/locales/ja.yml +78 -56
  93. data/web/locales/ko.yml +52 -52
  94. data/web/locales/lt.yml +83 -0
  95. data/web/locales/{no.yml → nb.yml} +62 -54
  96. data/web/locales/nl.yml +52 -52
  97. data/web/locales/pl.yml +45 -45
  98. data/web/locales/pt-br.yml +83 -55
  99. data/web/locales/pt.yml +51 -51
  100. data/web/locales/ru.yml +68 -60
  101. data/web/locales/sv.yml +53 -53
  102. data/web/locales/ta.yml +60 -60
  103. data/web/locales/tr.yml +101 -0
  104. data/web/locales/uk.yml +77 -0
  105. data/web/locales/ur.yml +80 -0
  106. data/web/locales/vi.yml +83 -0
  107. data/web/locales/zh-cn.yml +43 -16
  108. data/web/locales/zh-tw.yml +42 -8
  109. data/web/views/_footer.erb +22 -9
  110. data/web/views/_job_info.erb +27 -6
  111. data/web/views/_metrics_period_select.erb +12 -0
  112. data/web/views/_nav.erb +8 -22
  113. data/web/views/_paging.erb +3 -1
  114. data/web/views/_poll_link.erb +4 -0
  115. data/web/views/_summary.erb +7 -7
  116. data/web/views/busy.erb +91 -31
  117. data/web/views/dashboard.erb +52 -22
  118. data/web/views/dead.erb +5 -4
  119. data/web/views/filtering.erb +7 -0
  120. data/web/views/layout.erb +19 -7
  121. data/web/views/metrics.erb +91 -0
  122. data/web/views/metrics_for_job.erb +59 -0
  123. data/web/views/morgue.erb +26 -20
  124. data/web/views/queue.erb +36 -25
  125. data/web/views/queues.erb +24 -7
  126. data/web/views/retries.erb +29 -21
  127. data/web/views/retry.erb +6 -5
  128. data/web/views/scheduled.erb +20 -17
  129. data/web/views/scheduled_job_info.erb +2 -1
  130. metadata +101 -232
  131. data/.gitignore +0 -12
  132. data/.travis.yml +0 -16
  133. data/3.0-Upgrade.md +0 -70
  134. data/COMM-LICENSE +0 -85
  135. data/Contributing.md +0 -32
  136. data/Gemfile +0 -22
  137. data/LICENSE +0 -9
  138. data/Pro-2.0-Upgrade.md +0 -138
  139. data/Pro-Changes.md +0 -412
  140. data/Rakefile +0 -9
  141. data/bin/sidekiqctl +0 -93
  142. data/lib/generators/sidekiq/templates/worker_spec.rb.erb +0 -6
  143. data/lib/generators/sidekiq/templates/worker_test.rb.erb +0 -8
  144. data/lib/generators/sidekiq/worker_generator.rb +0 -49
  145. data/lib/sidekiq/actor.rb +0 -39
  146. data/lib/sidekiq/core_ext.rb +0 -105
  147. data/lib/sidekiq/exception_handler.rb +0 -30
  148. data/lib/sidekiq/extensions/action_mailer.rb +0 -56
  149. data/lib/sidekiq/extensions/active_record.rb +0 -39
  150. data/lib/sidekiq/extensions/class_methods.rb +0 -39
  151. data/lib/sidekiq/extensions/generic_proxy.rb +0 -24
  152. data/lib/sidekiq/logging.rb +0 -104
  153. data/lib/sidekiq/middleware/server/active_record.rb +0 -13
  154. data/lib/sidekiq/middleware/server/logging.rb +0 -35
  155. data/lib/sidekiq/middleware/server/retry_jobs.rb +0 -206
  156. data/lib/sidekiq/util.rb +0 -55
  157. data/lib/sidekiq/web_helpers.rb +0 -234
  158. data/lib/sidekiq/worker.rb +0 -89
  159. data/test/config.yml +0 -9
  160. data/test/env_based_config.yml +0 -11
  161. data/test/fake_env.rb +0 -0
  162. data/test/fixtures/en.yml +0 -2
  163. data/test/helper.rb +0 -39
  164. data/test/test_api.rb +0 -494
  165. data/test/test_cli.rb +0 -365
  166. data/test/test_client.rb +0 -269
  167. data/test/test_exception_handler.rb +0 -55
  168. data/test/test_extensions.rb +0 -120
  169. data/test/test_fetch.rb +0 -104
  170. data/test/test_logging.rb +0 -34
  171. data/test/test_manager.rb +0 -164
  172. data/test/test_middleware.rb +0 -159
  173. data/test/test_processor.rb +0 -166
  174. data/test/test_redis_connection.rb +0 -127
  175. data/test/test_retry.rb +0 -373
  176. data/test/test_scheduled.rb +0 -120
  177. data/test/test_scheduling.rb +0 -71
  178. data/test/test_sidekiq.rb +0 -69
  179. data/test/test_testing.rb +0 -82
  180. data/test/test_testing_fake.rb +0 -271
  181. data/test/test_testing_inline.rb +0 -93
  182. data/test/test_web.rb +0 -594
  183. data/test/test_web_helpers.rb +0 -52
  184. data/test/test_worker_generator.rb +0 -17
  185. data/web/assets/images/bootstrap/glyphicons-halflings-white.png +0 -0
  186. data/web/assets/images/bootstrap/glyphicons-halflings.png +0 -0
  187. data/web/assets/images/status/active.png +0 -0
  188. data/web/assets/images/status/idle.png +0 -0
  189. data/web/assets/javascripts/locales/README.md +0 -27
  190. data/web/assets/javascripts/locales/jquery.timeago.ar.js +0 -96
  191. data/web/assets/javascripts/locales/jquery.timeago.bg.js +0 -18
  192. data/web/assets/javascripts/locales/jquery.timeago.bs.js +0 -49
  193. data/web/assets/javascripts/locales/jquery.timeago.ca.js +0 -18
  194. data/web/assets/javascripts/locales/jquery.timeago.cs.js +0 -18
  195. data/web/assets/javascripts/locales/jquery.timeago.cy.js +0 -20
  196. data/web/assets/javascripts/locales/jquery.timeago.da.js +0 -18
  197. data/web/assets/javascripts/locales/jquery.timeago.de.js +0 -18
  198. data/web/assets/javascripts/locales/jquery.timeago.el.js +0 -18
  199. data/web/assets/javascripts/locales/jquery.timeago.en-short.js +0 -20
  200. data/web/assets/javascripts/locales/jquery.timeago.en.js +0 -20
  201. data/web/assets/javascripts/locales/jquery.timeago.es.js +0 -18
  202. data/web/assets/javascripts/locales/jquery.timeago.et.js +0 -18
  203. data/web/assets/javascripts/locales/jquery.timeago.fa.js +0 -22
  204. data/web/assets/javascripts/locales/jquery.timeago.fi.js +0 -28
  205. data/web/assets/javascripts/locales/jquery.timeago.fr-short.js +0 -16
  206. data/web/assets/javascripts/locales/jquery.timeago.fr.js +0 -17
  207. data/web/assets/javascripts/locales/jquery.timeago.he.js +0 -18
  208. data/web/assets/javascripts/locales/jquery.timeago.hr.js +0 -49
  209. data/web/assets/javascripts/locales/jquery.timeago.hu.js +0 -18
  210. data/web/assets/javascripts/locales/jquery.timeago.hy.js +0 -18
  211. data/web/assets/javascripts/locales/jquery.timeago.id.js +0 -18
  212. data/web/assets/javascripts/locales/jquery.timeago.it.js +0 -16
  213. data/web/assets/javascripts/locales/jquery.timeago.ja.js +0 -19
  214. data/web/assets/javascripts/locales/jquery.timeago.ko.js +0 -17
  215. data/web/assets/javascripts/locales/jquery.timeago.lt.js +0 -20
  216. data/web/assets/javascripts/locales/jquery.timeago.mk.js +0 -20
  217. data/web/assets/javascripts/locales/jquery.timeago.nl.js +0 -20
  218. data/web/assets/javascripts/locales/jquery.timeago.no.js +0 -18
  219. data/web/assets/javascripts/locales/jquery.timeago.pl.js +0 -31
  220. data/web/assets/javascripts/locales/jquery.timeago.pt-br.js +0 -16
  221. data/web/assets/javascripts/locales/jquery.timeago.pt.js +0 -16
  222. data/web/assets/javascripts/locales/jquery.timeago.ro.js +0 -18
  223. data/web/assets/javascripts/locales/jquery.timeago.rs.js +0 -49
  224. data/web/assets/javascripts/locales/jquery.timeago.ru.js +0 -34
  225. data/web/assets/javascripts/locales/jquery.timeago.sk.js +0 -18
  226. data/web/assets/javascripts/locales/jquery.timeago.sl.js +0 -44
  227. data/web/assets/javascripts/locales/jquery.timeago.sv.js +0 -18
  228. data/web/assets/javascripts/locales/jquery.timeago.th.js +0 -20
  229. data/web/assets/javascripts/locales/jquery.timeago.tr.js +0 -16
  230. data/web/assets/javascripts/locales/jquery.timeago.uk.js +0 -34
  231. data/web/assets/javascripts/locales/jquery.timeago.uz.js +0 -19
  232. data/web/assets/javascripts/locales/jquery.timeago.zh-cn.js +0 -20
  233. data/web/assets/javascripts/locales/jquery.timeago.zh-tw.js +0 -20
  234. data/web/views/_poll.erb +0 -10
  235. /data/web/assets/images/{status-sd8051fd480.png → status.png} +0 -0
data/test/test_api.rb DELETED
@@ -1,494 +0,0 @@
1
- require_relative 'helper'
2
-
3
- class TestApi < Sidekiq::Test
4
-
5
- describe "stats" do
6
- before do
7
- Sidekiq.redis = REDIS
8
- Sidekiq.redis {|c| c.flushdb }
9
- end
10
-
11
- describe "processed" do
12
- it "is initially zero" do
13
- s = Sidekiq::Stats.new
14
- assert_equal 0, s.processed
15
- end
16
-
17
- it "returns number of processed jobs" do
18
- Sidekiq.redis { |conn| conn.set("stat:processed", 5) }
19
- s = Sidekiq::Stats.new
20
- assert_equal 5, s.processed
21
- end
22
- end
23
-
24
- describe "failed" do
25
- it "is initially zero" do
26
- s = Sidekiq::Stats.new
27
- assert_equal 0, s.failed
28
- end
29
-
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
- Sidekiq.redis do |conn|
48
- assert_equal '0', conn.get('stat:processed')
49
- assert_equal '0', conn.get('stat:failed')
50
- end
51
- end
52
-
53
- it 'can reset individual stats' do
54
- Sidekiq::Stats.new.reset('failed')
55
- Sidekiq.redis do |conn|
56
- assert_equal '5', conn.get('stat:processed')
57
- assert_equal '0', conn.get('stat:failed')
58
- end
59
- end
60
-
61
- it 'can accept anything that responds to #to_s' do
62
- Sidekiq::Stats.new.reset(:failed)
63
- Sidekiq.redis do |conn|
64
- assert_equal '5', conn.get('stat:processed')
65
- assert_equal '0', conn.get('stat:failed')
66
- end
67
- end
68
-
69
- it 'ignores anything other than "failed" or "processed"' do
70
- Sidekiq::Stats.new.reset((1..10).to_a, ['failed'])
71
- Sidekiq.redis do |conn|
72
- assert_equal '5', conn.get('stat:processed')
73
- assert_equal '0', conn.get('stat:failed')
74
- end
75
- end
76
- end
77
-
78
- describe "queues" do
79
- it "returns all queues" do
80
- assert_equal Sidekiq::Stats.new.queues, Sidekiq::Stats::Queues.new.lengths
81
- end
82
-
83
- it "is initially empty" do
84
- s = Sidekiq::Stats::Queues.new
85
- assert_equal 0, s.lengths.size
86
- end
87
-
88
- it "returns a hash of queue and size in order" do
89
- Sidekiq.redis do |conn|
90
- conn.rpush 'queue:foo', '{}'
91
- conn.sadd 'queues', 'foo'
92
-
93
- 3.times { conn.rpush 'queue:bar', '{}' }
94
- conn.sadd 'queues', 'bar'
95
- end
96
-
97
- s = Sidekiq::Stats::Queues.new
98
- assert_equal ({ "foo" => 1, "bar" => 3 }), s.lengths
99
- assert_equal "bar", s.lengths.first.first
100
- end
101
- end
102
-
103
- describe "enqueued" do
104
- it "is initially empty" do
105
- s = Sidekiq::Stats.new
106
- assert_equal 0, s.enqueued
107
- end
108
-
109
- it "returns total enqueued jobs" do
110
- Sidekiq.redis do |conn|
111
- conn.rpush 'queue:foo', '{}'
112
- conn.sadd 'queues', 'foo'
113
-
114
- 3.times { conn.rpush 'queue:bar', '{}' }
115
- conn.sadd 'queues', 'bar'
116
- end
117
-
118
- s = Sidekiq::Stats.new
119
- assert_equal 4, s.enqueued
120
- end
121
- end
122
-
123
- describe "over time" do
124
- describe "processed" do
125
- it 'retrieves hash of dates' do
126
- Sidekiq.redis do |c|
127
- c.incrby("stat:processed:2012-12-24", 4)
128
- c.incrby("stat:processed:2012-12-25", 1)
129
- c.incrby("stat:processed:2012-12-26", 6)
130
- c.incrby("stat:processed:2012-12-27", 2)
131
- end
132
- Time.stub(:now, Time.parse("2012-12-26 1:00:00 -0500")) do
133
- s = Sidekiq::Stats::History.new(2)
134
- assert_equal ({ "2012-12-26" => 6, "2012-12-25" => 1 }), s.processed
135
-
136
- s = Sidekiq::Stats::History.new(3)
137
- assert_equal ({ "2012-12-26" => 6, "2012-12-25" => 1, "2012-12-24" => 4 }), s.processed
138
-
139
- s = Sidekiq::Stats::History.new(2, Date.parse("2012-12-25"))
140
- assert_equal ({ "2012-12-25" => 1, "2012-12-24" => 4 }), s.processed
141
- end
142
- end
143
- end
144
-
145
- describe "failed" do
146
- it 'retrieves hash of dates' do
147
- Sidekiq.redis do |c|
148
- c.incrby("stat:failed:2012-12-24", 4)
149
- c.incrby("stat:failed:2012-12-25", 1)
150
- c.incrby("stat:failed:2012-12-26", 6)
151
- c.incrby("stat:failed:2012-12-27", 2)
152
- end
153
- Time.stub(:now, Time.parse("2012-12-26 1:00:00 -0500")) do
154
- s = Sidekiq::Stats::History.new(2)
155
- assert_equal ({ "2012-12-26" => 6, "2012-12-25" => 1 }), s.failed
156
-
157
- s = Sidekiq::Stats::History.new(3)
158
- assert_equal ({ "2012-12-26" => 6, "2012-12-25" => 1, "2012-12-24" => 4 }), s.failed
159
-
160
- s = Sidekiq::Stats::History.new(2, Date.parse("2012-12-25"))
161
- assert_equal ({ "2012-12-25" => 1, "2012-12-24" => 4 }), s.failed
162
- end
163
- end
164
- end
165
- end
166
- end
167
-
168
- describe 'with an empty database' do
169
- include Sidekiq::Util
170
-
171
- before do
172
- Sidekiq.redis = REDIS
173
- Sidekiq.redis {|c| c.flushdb }
174
- end
175
-
176
- it 'shows queue as empty' do
177
- q = Sidekiq::Queue.new
178
- assert_equal 0, q.size
179
- assert_equal 0, q.latency
180
- end
181
-
182
- class ApiWorker
183
- include Sidekiq::Worker
184
- end
185
-
186
- it 'can enumerate jobs' do
187
- q = Sidekiq::Queue.new
188
- Time.stub(:now, Time.new(2012, 12, 26)) do
189
- ApiWorker.perform_async(1, 'mike')
190
- assert_equal ['TestApi::ApiWorker'], q.map(&:klass)
191
-
192
- job = q.first
193
- assert_equal 24, job.jid.size
194
- assert_equal [1, 'mike'], job.args
195
- assert_equal Time.new(2012, 12, 26), job.enqueued_at
196
- end
197
-
198
- assert q.latency > 10_000_000
199
-
200
- q = Sidekiq::Queue.new('other')
201
- assert_equal 0, q.size
202
- end
203
-
204
- it 'unwraps delayed jobs' do
205
- ApiWorker.delay.foo(1,2,3)
206
- q = Sidekiq::Queue.new
207
- x = q.first
208
- assert_equal "TestApi::ApiWorker.foo", x.display_class
209
- assert_equal [1,2,3], x.display_args
210
- end
211
-
212
- it 'can delete jobs' do
213
- q = Sidekiq::Queue.new
214
- ApiWorker.perform_async(1, 'mike')
215
- assert_equal 1, q.size
216
-
217
- x = q.first
218
- assert_equal "TestApi::ApiWorker", x.display_class
219
- assert_equal [1,'mike'], x.display_args
220
-
221
- assert_equal [true], q.map(&:delete)
222
- assert_equal 0, q.size
223
- end
224
-
225
- it "can move scheduled job to queue" do
226
- remain_id = ApiWorker.perform_in(100, 1, 'jason')
227
- job_id = ApiWorker.perform_in(100, 1, 'jason')
228
- job = Sidekiq::ScheduledSet.new.find_job(job_id)
229
- q = Sidekiq::Queue.new
230
- job.add_to_queue
231
- queued_job = q.find_job(job_id)
232
- refute_nil queued_job
233
- assert_equal queued_job.jid, job_id
234
- assert_nil Sidekiq::ScheduledSet.new.find_job(job_id)
235
- refute_nil Sidekiq::ScheduledSet.new.find_job(remain_id)
236
- end
237
-
238
- it "handles multiple scheduled jobs when moving to queue" do
239
- jids = Sidekiq::Client.push_bulk('class' => ApiWorker,
240
- 'args' => [[1, 'jason'], [2, 'jason']],
241
- 'at' => Time.now.to_f)
242
- assert_equal 2, jids.size
243
- (remain_id, job_id) = jids
244
- job = Sidekiq::ScheduledSet.new.find_job(job_id)
245
- q = Sidekiq::Queue.new
246
- job.add_to_queue
247
- queued_job = q.find_job(job_id)
248
- refute_nil queued_job
249
- assert_equal queued_job.jid, job_id
250
- assert_nil Sidekiq::ScheduledSet.new.find_job(job_id)
251
- refute_nil Sidekiq::ScheduledSet.new.find_job(remain_id)
252
- end
253
-
254
- it 'can find job by id in sorted sets' do
255
- job_id = ApiWorker.perform_in(100, 1, 'jason')
256
- job = Sidekiq::ScheduledSet.new.find_job(job_id)
257
- refute_nil job
258
- assert_equal job_id, job.jid
259
- assert_in_delta job.latency, 0.0, 0.1
260
- end
261
-
262
- it 'can remove jobs when iterating over a sorted set' do
263
- # scheduled jobs must be greater than SortedSet#each underlying page size
264
- 51.times do
265
- ApiWorker.perform_in(100, 'aaron')
266
- end
267
- set = Sidekiq::ScheduledSet.new
268
- set.map(&:delete)
269
- assert_equal set.size, 0
270
- end
271
-
272
- it 'can remove jobs when iterating over a queue' do
273
- # initial queue size must be greater than Queue#each underlying page size
274
- 51.times do
275
- ApiWorker.perform_async(1, 'aaron')
276
- end
277
- q = Sidekiq::Queue.new
278
- q.map(&:delete)
279
- assert_equal q.size, 0
280
- end
281
-
282
- it 'can find job by id in queues' do
283
- q = Sidekiq::Queue.new
284
- job_id = ApiWorker.perform_async(1, 'jason')
285
- job = q.find_job(job_id)
286
- refute_nil job
287
- assert_equal job_id, job.jid
288
- end
289
-
290
- it 'can clear a queue' do
291
- q = Sidekiq::Queue.new
292
- 2.times { ApiWorker.perform_async(1, 'mike') }
293
- q.clear
294
-
295
- Sidekiq.redis do |conn|
296
- refute conn.smembers('queues').include?('foo')
297
- refute conn.exists('queue:foo')
298
- end
299
- end
300
-
301
- it 'can fetch by score' do
302
- same_time = Time.now.to_f
303
- add_retry('bob1', same_time)
304
- add_retry('bob2', same_time)
305
- r = Sidekiq::RetrySet.new
306
- assert_equal 2, r.fetch(same_time).size
307
- end
308
-
309
- it 'can fetch by score and jid' do
310
- same_time = Time.now.to_f
311
- add_retry('bob1', same_time)
312
- add_retry('bob2', same_time)
313
- r = Sidekiq::RetrySet.new
314
- assert_equal 1, r.fetch(same_time, 'bob1').size
315
- end
316
-
317
- it 'shows empty retries' do
318
- r = Sidekiq::RetrySet.new
319
- assert_equal 0, r.size
320
- end
321
-
322
- it 'can enumerate retries' do
323
- add_retry
324
-
325
- r = Sidekiq::RetrySet.new
326
- assert_equal 1, r.size
327
- array = r.to_a
328
- assert_equal 1, array.size
329
-
330
- retri = array.first
331
- assert_equal 'ApiWorker', retri.klass
332
- assert_equal 'default', retri.queue
333
- assert_equal 'bob', retri.jid
334
- assert_in_delta Time.now.to_f, retri.at.to_f, 0.02
335
- end
336
-
337
- it 'can delete multiple retries from score' do
338
- same_time = Time.now.to_f
339
- add_retry('bob1', same_time)
340
- add_retry('bob2', same_time)
341
- r = Sidekiq::RetrySet.new
342
- assert_equal 2, r.size
343
- Sidekiq::RetrySet.new.delete(same_time)
344
- assert_equal 0, r.size
345
- end
346
-
347
- it 'can delete a single retry from score and jid' do
348
- same_time = Time.now.to_f
349
- add_retry('bob1', same_time)
350
- add_retry('bob2', same_time)
351
- r = Sidekiq::RetrySet.new
352
- assert_equal 2, r.size
353
- Sidekiq::RetrySet.new.delete(same_time, 'bob1')
354
- assert_equal 1, r.size
355
- end
356
-
357
- it 'can retry a retry' do
358
- add_retry
359
- r = Sidekiq::RetrySet.new
360
- assert_equal 1, r.size
361
- r.first.retry
362
- assert_equal 0, r.size
363
- assert_equal 1, Sidekiq::Queue.new('default').size
364
- job = Sidekiq::Queue.new('default').first
365
- assert_equal 'bob', job.jid
366
- assert_equal 1, job['retry_count']
367
- end
368
-
369
- it 'can clear retries' do
370
- add_retry
371
- add_retry('test')
372
- r = Sidekiq::RetrySet.new
373
- assert_equal 2, r.size
374
- r.clear
375
- assert_equal 0, r.size
376
- end
377
-
378
- it 'can enumerate processes' do
379
- identity_string = "identity_string"
380
- odata = {
381
- 'pid' => 123,
382
- 'hostname' => hostname,
383
- 'key' => identity_string,
384
- 'identity' => identity_string,
385
- 'started_at' => Time.now.to_f - 15,
386
- }
387
-
388
- time = Time.now.to_f
389
- Sidekiq.redis do |conn|
390
- conn.multi do
391
- conn.sadd('processes', odata['key'])
392
- conn.hmset(odata['key'], 'info', Sidekiq.dump_json(odata), 'busy', 10, 'beat', time)
393
- conn.sadd('processes', 'fake:pid')
394
- end
395
- end
396
-
397
- ps = Sidekiq::ProcessSet.new.to_a
398
- assert_equal 1, ps.size
399
- data = ps.first
400
- assert_equal 10, data['busy']
401
- assert_equal time, data['beat']
402
- assert_equal 123, data['pid']
403
- data.quiet!
404
- data.stop!
405
- signals_string = "#{odata['key']}-signals"
406
- assert_equal "TERM", Sidekiq.redis{|c| c.lpop(signals_string) }
407
- assert_equal "USR1", Sidekiq.redis{|c| c.lpop(signals_string) }
408
- end
409
-
410
- it 'can enumerate workers' do
411
- w = Sidekiq::Workers.new
412
- assert_equal 0, w.size
413
- w.each do
414
- assert false
415
- end
416
-
417
- key = "#{hostname}:#{$$}"
418
- pdata = { 'pid' => $$, 'hostname' => hostname, 'started_at' => Time.now.to_i }
419
- Sidekiq.redis do |conn|
420
- conn.sadd('processes', key)
421
- conn.hmset(key, 'info', Sidekiq.dump_json(pdata), 'busy', 0, 'beat', Time.now.to_f)
422
- end
423
-
424
- s = "#{key}:workers"
425
- data = Sidekiq.dump_json({ 'payload' => {}, 'queue' => 'default', 'run_at' => Time.now.to_i })
426
- Sidekiq.redis do |c|
427
- c.hmset(s, '1234', data)
428
- end
429
-
430
- w.each do |p, x, y|
431
- assert_equal key, p
432
- assert_equal "1234", x
433
- assert_equal 'default', y['queue']
434
- assert_equal Time.now.year, Time.at(y['run_at']).year
435
- end
436
-
437
- s = "#{key}:workers"
438
- data = Sidekiq.dump_json({ 'payload' => {}, 'queue' => 'default', 'run_at' => (Time.now.to_i - 2*60*60) })
439
- Sidekiq.redis do |c|
440
- c.multi do
441
- c.hmset(s, '5678', data)
442
- c.hmset("b#{s}", '5678', data)
443
- end
444
- end
445
-
446
- assert_equal ['1234', '5678'], w.map { |_, tid, _| tid }
447
- end
448
-
449
- it 'can reschedule jobs' do
450
- add_retry('foo1')
451
- add_retry('foo2')
452
-
453
- retries = Sidekiq::RetrySet.new
454
- assert_equal 2, retries.size
455
- refute(retries.map { |r| r.score > (Time.now.to_f + 9) }.any?)
456
-
457
- retries.each do |retri|
458
- retri.reschedule(Time.now.to_f + 10) if retri.jid == 'foo2'
459
- end
460
-
461
- assert_equal 2, retries.size
462
- assert(retries.map { |r| r.score > (Time.now.to_f + 9) }.any?)
463
- end
464
-
465
- it 'prunes processes which have died' do
466
- data = { 'pid' => rand(10_000), 'hostname' => "app#{rand(1_000)}", 'started_at' => Time.now.to_f }
467
- key = "#{data['hostname']}:#{data['pid']}"
468
- Sidekiq.redis do |conn|
469
- conn.sadd('processes', key)
470
- conn.hmset(key, 'info', Sidekiq.dump_json(data), 'busy', 0, 'beat', Time.now.to_f)
471
- end
472
-
473
- ps = Sidekiq::ProcessSet.new
474
- assert_equal 1, ps.size
475
- assert_equal 1, ps.to_a.size
476
-
477
- Sidekiq.redis do |conn|
478
- conn.sadd('processes', "bar:987")
479
- conn.sadd('processes', "bar:986")
480
- end
481
-
482
- ps = Sidekiq::ProcessSet.new
483
- assert_equal 1, ps.size
484
- assert_equal 1, ps.to_a.size
485
- end
486
-
487
- def add_retry(jid = 'bob', at = Time.now.to_f)
488
- payload = Sidekiq.dump_json('class' => 'ApiWorker', 'args' => [1, 'mike'], 'queue' => 'default', 'jid' => jid, 'retry_count' => 2, 'failed_at' => Time.now.to_f)
489
- Sidekiq.redis do |conn|
490
- conn.zadd('retry', at.to_s, payload)
491
- end
492
- end
493
- end
494
- end