sidekiq 4.2.10 → 7.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. checksums.yaml +5 -5
  2. data/Changes.md +859 -7
  3. data/LICENSE.txt +9 -0
  4. data/README.md +49 -50
  5. data/bin/multi_queue_bench +271 -0
  6. data/bin/sidekiq +22 -3
  7. data/bin/sidekiqload +212 -119
  8. data/bin/sidekiqmon +11 -0
  9. data/lib/generators/sidekiq/job_generator.rb +59 -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/{worker_test.rb.erb → job_test.rb.erb} +1 -1
  13. data/lib/sidekiq/api.rb +680 -315
  14. data/lib/sidekiq/capsule.rb +132 -0
  15. data/lib/sidekiq/cli.rb +268 -248
  16. data/lib/sidekiq/client.rb +136 -101
  17. data/lib/sidekiq/component.rb +68 -0
  18. data/lib/sidekiq/config.rb +293 -0
  19. data/lib/sidekiq/deploy.rb +64 -0
  20. data/lib/sidekiq/embedded.rb +63 -0
  21. data/lib/sidekiq/fetch.rb +49 -42
  22. data/lib/sidekiq/iterable_job.rb +55 -0
  23. data/lib/sidekiq/job/interrupt_handler.rb +24 -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 +62 -0
  30. data/lib/sidekiq/job_retry.rb +305 -0
  31. data/lib/sidekiq/job_util.rb +109 -0
  32. data/lib/sidekiq/launcher.rb +208 -108
  33. data/lib/sidekiq/logger.rb +131 -0
  34. data/lib/sidekiq/manager.rb +43 -47
  35. data/lib/sidekiq/metrics/query.rb +158 -0
  36. data/lib/sidekiq/metrics/shared.rb +97 -0
  37. data/lib/sidekiq/metrics/tracking.rb +148 -0
  38. data/lib/sidekiq/middleware/chain.rb +113 -56
  39. data/lib/sidekiq/middleware/current_attributes.rb +113 -0
  40. data/lib/sidekiq/middleware/i18n.rb +7 -7
  41. data/lib/sidekiq/middleware/modules.rb +23 -0
  42. data/lib/sidekiq/monitor.rb +147 -0
  43. data/lib/sidekiq/paginator.rb +28 -16
  44. data/lib/sidekiq/processor.rb +188 -98
  45. data/lib/sidekiq/rails.rb +46 -97
  46. data/lib/sidekiq/redis_client_adapter.rb +114 -0
  47. data/lib/sidekiq/redis_connection.rb +71 -73
  48. data/lib/sidekiq/ring_buffer.rb +31 -0
  49. data/lib/sidekiq/scheduled.rb +140 -51
  50. data/lib/sidekiq/sd_notify.rb +149 -0
  51. data/lib/sidekiq/systemd.rb +26 -0
  52. data/lib/sidekiq/testing/inline.rb +6 -5
  53. data/lib/sidekiq/testing.rb +95 -85
  54. data/lib/sidekiq/transaction_aware_client.rb +51 -0
  55. data/lib/sidekiq/version.rb +3 -1
  56. data/lib/sidekiq/web/action.rb +22 -16
  57. data/lib/sidekiq/web/application.rb +230 -86
  58. data/lib/sidekiq/web/csrf_protection.rb +183 -0
  59. data/lib/sidekiq/web/helpers.rb +241 -104
  60. data/lib/sidekiq/web/router.rb +23 -19
  61. data/lib/sidekiq/web.rb +118 -110
  62. data/lib/sidekiq/worker_compatibility_alias.rb +13 -0
  63. data/lib/sidekiq.rb +96 -185
  64. data/sidekiq.gemspec +26 -27
  65. data/web/assets/images/apple-touch-icon.png +0 -0
  66. data/web/assets/javascripts/application.js +157 -61
  67. data/web/assets/javascripts/base-charts.js +106 -0
  68. data/web/assets/javascripts/chart.min.js +13 -0
  69. data/web/assets/javascripts/chartjs-plugin-annotation.min.js +7 -0
  70. data/web/assets/javascripts/dashboard-charts.js +192 -0
  71. data/web/assets/javascripts/dashboard.js +37 -280
  72. data/web/assets/javascripts/metrics.js +298 -0
  73. data/web/assets/stylesheets/application-dark.css +147 -0
  74. data/web/assets/stylesheets/application-rtl.css +163 -0
  75. data/web/assets/stylesheets/application.css +173 -198
  76. data/web/assets/stylesheets/bootstrap-rtl.min.css +9 -0
  77. data/web/assets/stylesheets/bootstrap.css +2 -2
  78. data/web/locales/ar.yml +87 -0
  79. data/web/locales/cs.yml +62 -62
  80. data/web/locales/da.yml +60 -53
  81. data/web/locales/de.yml +65 -53
  82. data/web/locales/el.yml +43 -24
  83. data/web/locales/en.yml +86 -64
  84. data/web/locales/es.yml +70 -53
  85. data/web/locales/fa.yml +65 -64
  86. data/web/locales/fr.yml +83 -62
  87. data/web/locales/gd.yml +99 -0
  88. data/web/locales/he.yml +80 -0
  89. data/web/locales/hi.yml +59 -59
  90. data/web/locales/it.yml +53 -53
  91. data/web/locales/ja.yml +75 -62
  92. data/web/locales/ko.yml +52 -52
  93. data/web/locales/lt.yml +83 -0
  94. data/web/locales/nb.yml +61 -61
  95. data/web/locales/nl.yml +52 -52
  96. data/web/locales/pl.yml +45 -45
  97. data/web/locales/pt-br.yml +83 -55
  98. data/web/locales/pt.yml +51 -51
  99. data/web/locales/ru.yml +68 -63
  100. data/web/locales/sv.yml +53 -53
  101. data/web/locales/ta.yml +60 -60
  102. data/web/locales/tr.yml +101 -0
  103. data/web/locales/uk.yml +62 -61
  104. data/web/locales/ur.yml +80 -0
  105. data/web/locales/vi.yml +83 -0
  106. data/web/locales/zh-cn.yml +43 -16
  107. data/web/locales/zh-tw.yml +42 -8
  108. data/web/views/_footer.erb +21 -3
  109. data/web/views/_job_info.erb +21 -4
  110. data/web/views/_metrics_period_select.erb +12 -0
  111. data/web/views/_nav.erb +5 -19
  112. data/web/views/_paging.erb +3 -1
  113. data/web/views/_poll_link.erb +3 -6
  114. data/web/views/_summary.erb +7 -7
  115. data/web/views/busy.erb +85 -31
  116. data/web/views/dashboard.erb +50 -20
  117. data/web/views/dead.erb +3 -3
  118. data/web/views/filtering.erb +7 -0
  119. data/web/views/layout.erb +17 -6
  120. data/web/views/metrics.erb +91 -0
  121. data/web/views/metrics_for_job.erb +59 -0
  122. data/web/views/morgue.erb +14 -15
  123. data/web/views/queue.erb +34 -24
  124. data/web/views/queues.erb +20 -4
  125. data/web/views/retries.erb +19 -16
  126. data/web/views/retry.erb +3 -3
  127. data/web/views/scheduled.erb +19 -17
  128. metadata +91 -198
  129. data/.github/contributing.md +0 -32
  130. data/.github/issue_template.md +0 -9
  131. data/.gitignore +0 -12
  132. data/.travis.yml +0 -18
  133. data/3.0-Upgrade.md +0 -70
  134. data/4.0-Upgrade.md +0 -53
  135. data/COMM-LICENSE +0 -95
  136. data/Ent-Changes.md +0 -173
  137. data/Gemfile +0 -29
  138. data/LICENSE +0 -9
  139. data/Pro-2.0-Upgrade.md +0 -138
  140. data/Pro-3.0-Upgrade.md +0 -44
  141. data/Pro-Changes.md +0 -628
  142. data/Rakefile +0 -12
  143. data/bin/sidekiqctl +0 -99
  144. data/code_of_conduct.md +0 -50
  145. data/lib/generators/sidekiq/templates/worker_spec.rb.erb +0 -6
  146. data/lib/generators/sidekiq/worker_generator.rb +0 -49
  147. data/lib/sidekiq/core_ext.rb +0 -119
  148. data/lib/sidekiq/exception_handler.rb +0 -31
  149. data/lib/sidekiq/extensions/action_mailer.rb +0 -57
  150. data/lib/sidekiq/extensions/active_record.rb +0 -40
  151. data/lib/sidekiq/extensions/class_methods.rb +0 -40
  152. data/lib/sidekiq/extensions/generic_proxy.rb +0 -25
  153. data/lib/sidekiq/logging.rb +0 -106
  154. data/lib/sidekiq/middleware/server/active_record.rb +0 -13
  155. data/lib/sidekiq/middleware/server/logging.rb +0 -31
  156. data/lib/sidekiq/middleware/server/retry_jobs.rb +0 -205
  157. data/lib/sidekiq/util.rb +0 -63
  158. data/lib/sidekiq/worker.rb +0 -121
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
- require 'sidekiq/testing'
2
+
3
+ require "sidekiq/testing"
3
4
 
4
5
  ##
5
6
  # The Sidekiq inline infrastructure overrides perform_async so that it
6
- # actually calls perform instead. This allows workers to be run inline in a
7
+ # actually calls perform instead. This allows jobs to be run inline in a
7
8
  # testing environment.
8
9
  #
9
10
  # This is similar to `Resque.inline = true` functionality.
@@ -14,8 +15,8 @@ require 'sidekiq/testing'
14
15
  #
15
16
  # $external_variable = 0
16
17
  #
17
- # class ExternalWorker
18
- # include Sidekiq::Worker
18
+ # class ExternalJob
19
+ # include Sidekiq::Job
19
20
  #
20
21
  # def perform
21
22
  # $external_variable = 1
@@ -23,7 +24,7 @@ require 'sidekiq/testing'
23
24
  # end
24
25
  #
25
26
  # assert_equal 0, $external_variable
26
- # ExternalWorker.perform_async
27
+ # ExternalJob.perform_async
27
28
  # assert_equal 1, $external_variable
28
29
  #
29
30
  Sidekiq::Testing.inline!
@@ -1,27 +1,46 @@
1
1
  # frozen_string_literal: true
2
- require 'securerandom'
3
- require 'sidekiq'
4
2
 
5
- module Sidekiq
3
+ require "securerandom"
4
+ require "sidekiq"
6
5
 
6
+ module Sidekiq
7
7
  class Testing
8
+ class TestModeAlreadySetError < RuntimeError; end
8
9
  class << self
9
- attr_accessor :__test_mode
10
+ attr_accessor :__global_test_mode
10
11
 
12
+ # Calling without a block sets the global test mode, affecting
13
+ # all threads. Calling with a block only affects the current Thread.
11
14
  def __set_test_mode(mode)
12
15
  if block_given?
13
- current_mode = self.__test_mode
16
+ # Reentrant testing modes will lead to a rat's nest of code which is
17
+ # hard to reason about. You can set the testing mode once globally and
18
+ # you can override that global setting once per-thread.
19
+ raise TestModeAlreadySetError, "Nesting test modes is not supported" if __local_test_mode
20
+
21
+ self.__local_test_mode = mode
14
22
  begin
15
- self.__test_mode = mode
16
23
  yield
17
24
  ensure
18
- self.__test_mode = current_mode
25
+ self.__local_test_mode = nil
19
26
  end
20
27
  else
21
- self.__test_mode = mode
28
+ self.__global_test_mode = mode
22
29
  end
23
30
  end
24
31
 
32
+ def __test_mode
33
+ __local_test_mode || __global_test_mode
34
+ end
35
+
36
+ def __local_test_mode
37
+ Thread.current[:__sidekiq_test_mode]
38
+ end
39
+
40
+ def __local_test_mode=(value)
41
+ Thread.current[:__sidekiq_test_mode] = value
42
+ end
43
+
25
44
  def disable!(&block)
26
45
  __set_test_mode(:disable, &block)
27
46
  end
@@ -35,23 +54,23 @@ module Sidekiq
35
54
  end
36
55
 
37
56
  def enabled?
38
- self.__test_mode != :disable
57
+ __test_mode != :disable
39
58
  end
40
59
 
41
60
  def disabled?
42
- self.__test_mode == :disable
61
+ __test_mode == :disable
43
62
  end
44
63
 
45
64
  def fake?
46
- self.__test_mode == :fake
65
+ __test_mode == :fake
47
66
  end
48
67
 
49
68
  def inline?
50
- self.__test_mode == :inline
69
+ __test_mode == :inline
51
70
  end
52
71
 
53
72
  def server_middleware
54
- @server_chain ||= Middleware::Chain.new
73
+ @server_chain ||= Middleware::Chain.new(Sidekiq.default_configuration)
55
74
  yield @server_chain if block_given?
56
75
  @server_chain
57
76
  end
@@ -63,49 +82,49 @@ module Sidekiq
63
82
 
64
83
  class EmptyQueueError < RuntimeError; end
65
84
 
66
- class Client
67
- alias_method :raw_push_real, :raw_push
68
-
69
- def raw_push(payloads)
85
+ module TestingClient
86
+ def atomic_push(conn, payloads)
70
87
  if Sidekiq::Testing.fake?
71
88
  payloads.each do |job|
72
89
  job = Sidekiq.load_json(Sidekiq.dump_json(job))
73
- job.merge!('enqueued_at' => Time.now.to_f) unless job['at']
74
- Queues.push(job['queue'], job['class'], job)
90
+ job["enqueued_at"] = Time.now.to_f unless job["at"]
91
+ Queues.push(job["queue"], job["class"], job)
75
92
  end
76
93
  true
77
94
  elsif Sidekiq::Testing.inline?
78
95
  payloads.each do |job|
79
- klass = job['class'].constantize
80
- job['id'] ||= SecureRandom.hex(12)
96
+ klass = Object.const_get(job["class"])
97
+ job["id"] ||= SecureRandom.hex(12)
81
98
  job_hash = Sidekiq.load_json(Sidekiq.dump_json(job))
82
99
  klass.process_job(job_hash)
83
100
  end
84
101
  true
85
102
  else
86
- raw_push_real(payloads)
103
+ super
87
104
  end
88
105
  end
89
106
  end
90
107
 
108
+ Sidekiq::Client.prepend TestingClient
109
+
91
110
  module Queues
92
111
  ##
93
112
  # The Queues class is only for testing the fake queue implementation.
94
113
  # There are 2 data structures involved in tandem. This is due to the
95
- # Rspec syntax of change(QueueWorker.jobs, :size). It keeps a reference
96
- # to the array. Because the array was dervied from a filter of the total
114
+ # Rspec syntax of change(HardJob.jobs, :size). It keeps a reference
115
+ # to the array. Because the array was derived from a filter of the total
97
116
  # jobs enqueued, it appeared as though the array didn't change.
98
117
  #
99
118
  # To solve this, we'll keep 2 hashes containing the jobs. One with keys based
100
- # on the queue, and another with keys of the worker names, so the array for
101
- # QueueWorker.jobs is a straight reference to a real array.
119
+ # on the queue, and another with keys of the job type, so the array for
120
+ # HardJob.jobs is a straight reference to a real array.
102
121
  #
103
122
  # Queue-based hash:
104
123
  #
105
124
  # {
106
125
  # "default"=>[
107
126
  # {
108
- # "class"=>"TestTesting::QueueWorker",
127
+ # "class"=>"TestTesting::HardJob",
109
128
  # "args"=>[1, 2],
110
129
  # "retry"=>true,
111
130
  # "queue"=>"default",
@@ -115,12 +134,12 @@ module Sidekiq
115
134
  # ]
116
135
  # }
117
136
  #
118
- # Worker-based hash:
137
+ # Job-based hash:
119
138
  #
120
139
  # {
121
- # "TestTesting::QueueWorker"=>[
140
+ # "TestTesting::HardJob"=>[
122
141
  # {
123
- # "class"=>"TestTesting::QueueWorker",
142
+ # "class"=>"TestTesting::HardJob",
124
143
  # "args"=>[1, 2],
125
144
  # "retry"=>true,
126
145
  # "queue"=>"default",
@@ -135,14 +154,14 @@ module Sidekiq
135
154
  # require 'sidekiq/testing'
136
155
  #
137
156
  # assert_equal 0, Sidekiq::Queues["default"].size
138
- # HardWorker.perform_async(:something)
157
+ # HardJob.perform_async(:something)
139
158
  # assert_equal 1, Sidekiq::Queues["default"].size
140
159
  # assert_equal :something, Sidekiq::Queues["default"].first['args'][0]
141
160
  #
142
- # You can also clear all workers' jobs:
161
+ # You can also clear all jobs:
143
162
  #
144
163
  # assert_equal 0, Sidekiq::Queues["default"].size
145
- # HardWorker.perform_async(:something)
164
+ # HardJob.perform_async(:something)
146
165
  # Sidekiq::Queues.clear_all
147
166
  # assert_equal 0, Sidekiq::Queues["default"].size
148
167
  #
@@ -161,35 +180,36 @@ module Sidekiq
161
180
 
162
181
  def push(queue, klass, job)
163
182
  jobs_by_queue[queue] << job
164
- jobs_by_worker[klass] << job
183
+ jobs_by_class[klass] << job
165
184
  end
166
185
 
167
186
  def jobs_by_queue
168
187
  @jobs_by_queue ||= Hash.new { |hash, key| hash[key] = [] }
169
188
  end
170
189
 
171
- def jobs_by_worker
172
- @jobs_by_worker ||= Hash.new { |hash, key| hash[key] = [] }
190
+ def jobs_by_class
191
+ @jobs_by_class ||= Hash.new { |hash, key| hash[key] = [] }
173
192
  end
193
+ alias_method :jobs_by_worker, :jobs_by_class
174
194
 
175
195
  def delete_for(jid, queue, klass)
176
196
  jobs_by_queue[queue.to_s].delete_if { |job| job["jid"] == jid }
177
- jobs_by_worker[klass].delete_if { |job| job["jid"] == jid }
197
+ jobs_by_class[klass].delete_if { |job| job["jid"] == jid }
178
198
  end
179
199
 
180
200
  def clear_for(queue, klass)
181
- jobs_by_queue[queue].clear
182
- jobs_by_worker[klass].clear
201
+ jobs_by_queue[queue.to_s].clear
202
+ jobs_by_class[klass].clear
183
203
  end
184
204
 
185
205
  def clear_all
186
206
  jobs_by_queue.clear
187
- jobs_by_worker.clear
207
+ jobs_by_class.clear
188
208
  end
189
209
  end
190
210
  end
191
211
 
192
- module Worker
212
+ module Job
193
213
  ##
194
214
  # The Sidekiq testing infrastructure overrides perform_async
195
215
  # so that it does not actually touch the network. Instead it
@@ -203,70 +223,53 @@ module Sidekiq
203
223
  #
204
224
  # require 'sidekiq/testing'
205
225
  #
206
- # assert_equal 0, HardWorker.jobs.size
207
- # HardWorker.perform_async(:something)
208
- # assert_equal 1, HardWorker.jobs.size
209
- # assert_equal :something, HardWorker.jobs[0]['args'][0]
226
+ # assert_equal 0, HardJob.jobs.size
227
+ # HardJob.perform_async(:something)
228
+ # assert_equal 1, HardJob.jobs.size
229
+ # assert_equal :something, HardJob.jobs[0]['args'][0]
210
230
  #
211
- # assert_equal 0, Sidekiq::Extensions::DelayedMailer.jobs.size
212
- # MyMailer.delay.send_welcome_email('foo@example.com')
213
- # assert_equal 1, Sidekiq::Extensions::DelayedMailer.jobs.size
231
+ # You can also clear and drain all job types:
214
232
  #
215
- # You can also clear and drain all workers' jobs:
216
- #
217
- # assert_equal 0, Sidekiq::Extensions::DelayedMailer.jobs.size
218
- # assert_equal 0, Sidekiq::Extensions::DelayedModel.jobs.size
219
- #
220
- # MyMailer.delay.send_welcome_email('foo@example.com')
221
- # MyModel.delay.do_something_hard
222
- #
223
- # assert_equal 1, Sidekiq::Extensions::DelayedMailer.jobs.size
224
- # assert_equal 1, Sidekiq::Extensions::DelayedModel.jobs.size
225
- #
226
- # Sidekiq::Worker.clear_all # or .drain_all
227
- #
228
- # assert_equal 0, Sidekiq::Extensions::DelayedMailer.jobs.size
229
- # assert_equal 0, Sidekiq::Extensions::DelayedModel.jobs.size
233
+ # Sidekiq::Job.clear_all # or .drain_all
230
234
  #
231
235
  # This can be useful to make sure jobs don't linger between tests:
232
236
  #
233
237
  # RSpec.configure do |config|
234
238
  # config.before(:each) do
235
- # Sidekiq::Worker.clear_all
239
+ # Sidekiq::Job.clear_all
236
240
  # end
237
241
  # end
238
242
  #
239
243
  # or for acceptance testing, i.e. with cucumber:
240
244
  #
241
245
  # AfterStep do
242
- # Sidekiq::Worker.drain_all
246
+ # Sidekiq::Job.drain_all
243
247
  # end
244
248
  #
245
249
  # When I sign up as "foo@example.com"
246
250
  # Then I should receive a welcome email to "foo@example.com"
247
251
  #
248
252
  module ClassMethods
249
-
250
253
  # Queue for this worker
251
254
  def queue
252
- self.sidekiq_options["queue"]
255
+ get_sidekiq_options["queue"]
253
256
  end
254
257
 
255
258
  # Jobs queued for this worker
256
259
  def jobs
257
- Queues.jobs_by_worker[self.to_s]
260
+ Queues.jobs_by_class[to_s]
258
261
  end
259
262
 
260
263
  # Clear all jobs for this worker
261
264
  def clear
262
- Queues.clear_for(queue, self.to_s)
265
+ Queues.clear_for(queue, to_s)
263
266
  end
264
267
 
265
268
  # Drain and run all jobs for this worker
266
269
  def drain
267
270
  while jobs.any?
268
271
  next_job = jobs.first
269
- Queues.delete_for(next_job["jid"], next_job["queue"], self.to_s)
272
+ Queues.delete_for(next_job["jid"], next_job["queue"], to_s)
270
273
  process_job(next_job)
271
274
  end
272
275
  end
@@ -275,16 +278,16 @@ module Sidekiq
275
278
  def perform_one
276
279
  raise(EmptyQueueError, "perform_one called with empty job queue") if jobs.empty?
277
280
  next_job = jobs.first
278
- Queues.delete_for(next_job["jid"], queue, self.to_s)
281
+ Queues.delete_for(next_job["jid"], next_job["queue"], to_s)
279
282
  process_job(next_job)
280
283
  end
281
284
 
282
285
  def process_job(job)
283
- worker = new
284
- worker.jid = job['jid']
285
- worker.bid = job['bid'] if worker.respond_to?(:bid=)
286
- Sidekiq::Testing.server_middleware.invoke(worker, job, job['queue']) do
287
- execute_job(worker, job['args'])
286
+ inst = new
287
+ inst.jid = job["jid"]
288
+ inst.bid = job["bid"] if inst.respond_to?(:bid=)
289
+ Sidekiq::Testing.server_middleware.invoke(inst, job, job["queue"]) do
290
+ execute_job(inst, job["args"])
288
291
  end
289
292
  end
290
293
 
@@ -298,27 +301,34 @@ module Sidekiq
298
301
  Queues.jobs_by_queue.values.flatten
299
302
  end
300
303
 
301
- # Clear all queued jobs across all workers
304
+ # Clear all queued jobs
302
305
  def clear_all
303
306
  Queues.clear_all
304
307
  end
305
308
 
306
- # Drain all queued jobs across all workers
309
+ # Drain (execute) all queued jobs
307
310
  def drain_all
308
311
  while jobs.any?
309
- worker_classes = jobs.map { |job| job["class"] }.uniq
312
+ job_classes = jobs.map { |job| job["class"] }.uniq
310
313
 
311
- worker_classes.each do |worker_class|
312
- worker_class.constantize.drain
314
+ job_classes.each do |job_class|
315
+ Object.const_get(job_class).drain
313
316
  end
314
317
  end
315
318
  end
316
319
  end
317
320
  end
321
+
322
+ module TestingExtensions
323
+ def jobs_for(klass)
324
+ jobs.select do |job|
325
+ marshalled = job["args"][0]
326
+ marshalled.index(klass.to_s) && YAML.safe_load(marshalled)[0] == klass
327
+ end
328
+ end
329
+ end
318
330
  end
319
331
 
320
- if defined?(::Rails) && !Rails.env.test?
321
- puts("**************************************************")
322
- puts("⛔️ WARNING: Sidekiq testing API enabled, but this is not the test environment. Your jobs will not go to Redis.")
323
- puts("**************************************************")
332
+ if defined?(::Rails) && Rails.respond_to?(:env) && !Rails.env.test? && !$TESTING
333
+ warn("⛔️ WARNING: Sidekiq testing API enabled, but this is not the test environment. Your jobs will not go to Redis.", uplevel: 1)
324
334
  end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "securerandom"
4
+ require "sidekiq/client"
5
+
6
+ module Sidekiq
7
+ class TransactionAwareClient
8
+ def initialize(pool: nil, config: nil)
9
+ @redis_client = Client.new(pool: pool, config: config)
10
+ end
11
+
12
+ def batching?
13
+ Thread.current[:sidekiq_batch]
14
+ end
15
+
16
+ def push(item)
17
+ # 6160 we can't support both Sidekiq::Batch and transactions.
18
+ return @redis_client.push(item) if batching?
19
+
20
+ # pre-allocate the JID so we can return it immediately and
21
+ # save it to the database as part of the transaction.
22
+ item["jid"] ||= SecureRandom.hex(12)
23
+ AfterCommitEverywhere.after_commit { @redis_client.push(item) }
24
+ item["jid"]
25
+ end
26
+
27
+ ##
28
+ # We don't provide transactionality for push_bulk because we don't want
29
+ # to hold potentially hundreds of thousands of job records in memory due to
30
+ # a long running enqueue process.
31
+ def push_bulk(items)
32
+ @redis_client.push_bulk(items)
33
+ end
34
+ end
35
+ end
36
+
37
+ ##
38
+ # Use `Sidekiq.transactional_push!` in your sidekiq.rb initializer
39
+ module Sidekiq
40
+ def self.transactional_push!
41
+ begin
42
+ require "after_commit_everywhere"
43
+ rescue LoadError
44
+ raise %q(You need to add `gem "after_commit_everywhere"` to your Gemfile to use Sidekiq's transactional client)
45
+ end
46
+
47
+ Sidekiq.default_job_options["client_class"] = Sidekiq::TransactionAwareClient
48
+ Sidekiq::JobUtil::TRANSIENT_ATTRIBUTES << "client_class"
49
+ true
50
+ end
51
+ end
@@ -1,4 +1,6 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Sidekiq
3
- VERSION = "4.2.10"
4
+ VERSION = "7.3.2"
5
+ MAJOR = 7
4
6
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Sidekiq
4
4
  class WebAction
5
- RACK_SESSION = 'rack.session'.freeze
5
+ RACK_SESSION = "rack.session"
6
6
 
7
7
  attr_accessor :env, :block, :type
8
8
 
@@ -15,18 +15,23 @@ module Sidekiq
15
15
  end
16
16
 
17
17
  def halt(res)
18
- throw :halt, res
18
+ throw :halt, [res, {Rack::CONTENT_TYPE => "text/plain"}, [res.to_s]]
19
19
  end
20
20
 
21
21
  def redirect(location)
22
- throw :halt, [302, { "Location" => "#{request.base_url}#{location}" }, []]
22
+ throw :halt, [302, {Web::LOCATION => "#{request.base_url}#{location}"}, []]
23
+ end
24
+
25
+ def reload_page
26
+ current_location = request.referer.gsub(request.base_url, "")
27
+ redirect current_location
23
28
  end
24
29
 
25
30
  def params
26
- indifferent_hash = Hash.new {|hash,key| hash[key.to_s] if Symbol === key }
31
+ indifferent_hash = Hash.new { |hash, key| hash[key.to_s] if Symbol === key }
27
32
 
28
33
  indifferent_hash.merge! request.params
29
- route_params.each {|k,v| indifferent_hash[k.to_s] = v }
34
+ route_params.each { |k, v| indifferent_hash[k.to_s] = v }
30
35
 
31
36
  indifferent_hash
32
37
  end
@@ -39,15 +44,16 @@ module Sidekiq
39
44
  env[RACK_SESSION]
40
45
  end
41
46
 
42
- def content_type(type)
43
- @type = type
44
- end
45
-
46
47
  def erb(content, options = {})
47
- if content.kind_of? Symbol
48
+ if content.is_a? Symbol
48
49
  unless respond_to?(:"_erb_#{content}")
49
- src = ERB.new(File.read("#{Web.settings.views}/#{content}.erb")).src
50
- WebAction.class_eval("def _erb_#{content}\n#{src}\n end")
50
+ views = options[:views] || Web.settings.views
51
+ src = ERB.new(File.read("#{views}/#{content}.erb")).src
52
+ WebAction.class_eval <<-RUBY, __FILE__, __LINE__ + 1
53
+ def _erb_#{content}
54
+ #{src}
55
+ end
56
+ RUBY
51
57
  end
52
58
  end
53
59
 
@@ -68,22 +74,22 @@ module Sidekiq
68
74
  end
69
75
 
70
76
  def json(payload)
71
- [200, { "Content-Type" => "application/json", "Cache-Control" => "no-cache" }, [Sidekiq.dump_json(payload)]]
77
+ [200, {Rack::CONTENT_TYPE => "application/json", Rack::CACHE_CONTROL => "private, no-store"}, [Sidekiq.dump_json(payload)]]
72
78
  end
73
79
 
74
80
  def initialize(env, block)
75
81
  @_erb = false
76
82
  @env = env
77
83
  @block = block
78
- @@files ||= {}
84
+ @files ||= {}
79
85
  end
80
86
 
81
87
  private
82
88
 
83
89
  def _erb(file, locals)
84
- locals.each {|k, v| define_singleton_method(k){ v } } if locals
90
+ locals&.each { |k, v| define_singleton_method(k) { v } unless singleton_methods.include? k }
85
91
 
86
- if file.kind_of?(String)
92
+ if file.is_a?(String)
87
93
  ERB.new(file).result(binding)
88
94
  else
89
95
  send(:"_erb_#{file}")