sidekiq 4.2.10 → 7.3.10
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.
- checksums.yaml +5 -5
- data/Changes.md +932 -7
- data/LICENSE.txt +9 -0
- data/README.md +49 -50
- data/bin/multi_queue_bench +271 -0
- data/bin/sidekiq +22 -3
- data/bin/sidekiqload +218 -116
- data/bin/sidekiqmon +11 -0
- data/lib/active_job/queue_adapters/sidekiq_adapter.rb +75 -0
- data/lib/generators/sidekiq/job_generator.rb +59 -0
- data/lib/generators/sidekiq/templates/{worker.rb.erb → job.rb.erb} +2 -2
- data/lib/generators/sidekiq/templates/job_spec.rb.erb +6 -0
- data/lib/generators/sidekiq/templates/{worker_test.rb.erb → job_test.rb.erb} +1 -1
- data/lib/sidekiq/api.rb +710 -322
- data/lib/sidekiq/capsule.rb +132 -0
- data/lib/sidekiq/cli.rb +268 -248
- data/lib/sidekiq/client.rb +153 -101
- data/lib/sidekiq/component.rb +90 -0
- data/lib/sidekiq/config.rb +311 -0
- data/lib/sidekiq/deploy.rb +64 -0
- data/lib/sidekiq/embedded.rb +63 -0
- data/lib/sidekiq/fetch.rb +50 -42
- data/lib/sidekiq/iterable_job.rb +55 -0
- data/lib/sidekiq/job/interrupt_handler.rb +24 -0
- data/lib/sidekiq/job/iterable/active_record_enumerator.rb +53 -0
- data/lib/sidekiq/job/iterable/csv_enumerator.rb +47 -0
- data/lib/sidekiq/job/iterable/enumerators.rb +135 -0
- data/lib/sidekiq/job/iterable.rb +294 -0
- data/lib/sidekiq/job.rb +385 -0
- data/lib/sidekiq/job_logger.rb +52 -0
- data/lib/sidekiq/job_retry.rb +305 -0
- data/lib/sidekiq/job_util.rb +109 -0
- data/lib/sidekiq/launcher.rb +208 -108
- data/lib/sidekiq/logger.rb +131 -0
- data/lib/sidekiq/manager.rb +43 -47
- data/lib/sidekiq/metrics/query.rb +158 -0
- data/lib/sidekiq/metrics/shared.rb +106 -0
- data/lib/sidekiq/metrics/tracking.rb +148 -0
- data/lib/sidekiq/middleware/chain.rb +113 -56
- data/lib/sidekiq/middleware/current_attributes.rb +128 -0
- data/lib/sidekiq/middleware/i18n.rb +9 -7
- data/lib/sidekiq/middleware/modules.rb +23 -0
- data/lib/sidekiq/monitor.rb +147 -0
- data/lib/sidekiq/paginator.rb +33 -15
- data/lib/sidekiq/processor.rb +188 -98
- data/lib/sidekiq/rails.rb +53 -92
- data/lib/sidekiq/redis_client_adapter.rb +114 -0
- data/lib/sidekiq/redis_connection.rb +86 -77
- data/lib/sidekiq/ring_buffer.rb +32 -0
- data/lib/sidekiq/scheduled.rb +140 -51
- data/lib/sidekiq/sd_notify.rb +149 -0
- data/lib/sidekiq/systemd.rb +26 -0
- data/lib/sidekiq/testing/inline.rb +6 -5
- data/lib/sidekiq/testing.rb +95 -85
- data/lib/sidekiq/transaction_aware_client.rb +59 -0
- data/lib/sidekiq/version.rb +7 -1
- data/lib/sidekiq/web/action.rb +40 -18
- data/lib/sidekiq/web/application.rb +189 -89
- data/lib/sidekiq/web/csrf_protection.rb +183 -0
- data/lib/sidekiq/web/helpers.rb +239 -101
- data/lib/sidekiq/web/router.rb +28 -21
- data/lib/sidekiq/web.rb +123 -110
- data/lib/sidekiq/worker_compatibility_alias.rb +13 -0
- data/lib/sidekiq.rb +97 -185
- data/sidekiq.gemspec +26 -27
- data/web/assets/images/apple-touch-icon.png +0 -0
- data/web/assets/javascripts/application.js +157 -61
- data/web/assets/javascripts/base-charts.js +106 -0
- data/web/assets/javascripts/chart.min.js +13 -0
- data/web/assets/javascripts/chartjs-plugin-annotation.min.js +7 -0
- data/web/assets/javascripts/dashboard-charts.js +194 -0
- data/web/assets/javascripts/dashboard.js +43 -280
- data/web/assets/javascripts/metrics.js +298 -0
- data/web/assets/stylesheets/application-dark.css +147 -0
- data/web/assets/stylesheets/application-rtl.css +163 -0
- data/web/assets/stylesheets/application.css +176 -196
- data/web/assets/stylesheets/bootstrap-rtl.min.css +9 -0
- data/web/assets/stylesheets/bootstrap.css +2 -2
- data/web/locales/ar.yml +87 -0
- data/web/locales/cs.yml +62 -62
- data/web/locales/da.yml +60 -53
- data/web/locales/de.yml +65 -53
- data/web/locales/el.yml +43 -24
- data/web/locales/en.yml +88 -64
- data/web/locales/es.yml +70 -53
- data/web/locales/fa.yml +65 -64
- data/web/locales/fr.yml +82 -62
- data/web/locales/gd.yml +98 -0
- data/web/locales/he.yml +80 -0
- data/web/locales/hi.yml +59 -59
- data/web/locales/it.yml +85 -54
- data/web/locales/ja.yml +74 -62
- data/web/locales/ko.yml +52 -52
- data/web/locales/lt.yml +83 -0
- data/web/locales/nb.yml +61 -61
- data/web/locales/nl.yml +52 -52
- data/web/locales/pl.yml +45 -45
- data/web/locales/pt-br.yml +82 -55
- data/web/locales/pt.yml +51 -51
- data/web/locales/ru.yml +68 -63
- data/web/locales/sv.yml +53 -53
- data/web/locales/ta.yml +60 -60
- data/web/locales/tr.yml +100 -0
- data/web/locales/uk.yml +85 -61
- data/web/locales/ur.yml +80 -0
- data/web/locales/vi.yml +83 -0
- data/web/locales/zh-cn.yml +42 -16
- data/web/locales/zh-tw.yml +41 -8
- data/web/views/_footer.erb +20 -3
- data/web/views/_job_info.erb +21 -4
- data/web/views/_metrics_period_select.erb +12 -0
- data/web/views/_nav.erb +5 -19
- data/web/views/_paging.erb +3 -1
- data/web/views/_poll_link.erb +3 -6
- data/web/views/_summary.erb +7 -7
- data/web/views/busy.erb +85 -31
- data/web/views/dashboard.erb +53 -20
- data/web/views/dead.erb +3 -3
- data/web/views/filtering.erb +6 -0
- data/web/views/layout.erb +17 -6
- data/web/views/metrics.erb +90 -0
- data/web/views/metrics_for_job.erb +59 -0
- data/web/views/morgue.erb +15 -16
- data/web/views/queue.erb +35 -25
- data/web/views/queues.erb +20 -4
- data/web/views/retries.erb +19 -16
- data/web/views/retry.erb +3 -3
- data/web/views/scheduled.erb +19 -17
- metadata +103 -194
- data/.github/contributing.md +0 -32
- data/.github/issue_template.md +0 -9
- data/.gitignore +0 -12
- data/.travis.yml +0 -18
- data/3.0-Upgrade.md +0 -70
- data/4.0-Upgrade.md +0 -53
- data/COMM-LICENSE +0 -95
- data/Ent-Changes.md +0 -173
- data/Gemfile +0 -29
- data/LICENSE +0 -9
- data/Pro-2.0-Upgrade.md +0 -138
- data/Pro-3.0-Upgrade.md +0 -44
- data/Pro-Changes.md +0 -628
- data/Rakefile +0 -12
- data/bin/sidekiqctl +0 -99
- data/code_of_conduct.md +0 -50
- data/lib/generators/sidekiq/templates/worker_spec.rb.erb +0 -6
- data/lib/generators/sidekiq/worker_generator.rb +0 -49
- data/lib/sidekiq/core_ext.rb +0 -119
- data/lib/sidekiq/exception_handler.rb +0 -31
- data/lib/sidekiq/extensions/action_mailer.rb +0 -57
- data/lib/sidekiq/extensions/active_record.rb +0 -40
- data/lib/sidekiq/extensions/class_methods.rb +0 -40
- data/lib/sidekiq/extensions/generic_proxy.rb +0 -25
- data/lib/sidekiq/logging.rb +0 -106
- data/lib/sidekiq/middleware/server/active_record.rb +0 -13
- data/lib/sidekiq/middleware/server/logging.rb +0 -31
- data/lib/sidekiq/middleware/server/retry_jobs.rb +0 -205
- data/lib/sidekiq/util.rb +0 -63
- data/lib/sidekiq/worker.rb +0 -121
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
|
|
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
|
|
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
|
|
18
|
-
# include Sidekiq::
|
|
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
|
-
#
|
|
27
|
+
# ExternalJob.perform_async
|
|
27
28
|
# assert_equal 1, $external_variable
|
|
28
29
|
#
|
|
29
30
|
Sidekiq::Testing.inline!
|
data/lib/sidekiq/testing.rb
CHANGED
|
@@ -1,27 +1,46 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
require 'securerandom'
|
|
3
|
-
require 'sidekiq'
|
|
4
2
|
|
|
5
|
-
|
|
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 :
|
|
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
|
-
|
|
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.
|
|
25
|
+
self.__local_test_mode = nil
|
|
19
26
|
end
|
|
20
27
|
else
|
|
21
|
-
self.
|
|
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
|
-
|
|
57
|
+
__test_mode != :disable
|
|
39
58
|
end
|
|
40
59
|
|
|
41
60
|
def disabled?
|
|
42
|
-
|
|
61
|
+
__test_mode == :disable
|
|
43
62
|
end
|
|
44
63
|
|
|
45
64
|
def fake?
|
|
46
|
-
|
|
65
|
+
__test_mode == :fake
|
|
47
66
|
end
|
|
48
67
|
|
|
49
68
|
def inline?
|
|
50
|
-
|
|
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
|
-
|
|
67
|
-
|
|
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
|
|
74
|
-
Queues.push(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[
|
|
80
|
-
job[
|
|
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
|
-
|
|
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(
|
|
96
|
-
# to the array. Because the array was
|
|
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
|
|
101
|
-
#
|
|
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::
|
|
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
|
-
#
|
|
137
|
+
# Job-based hash:
|
|
119
138
|
#
|
|
120
139
|
# {
|
|
121
|
-
# "TestTesting::
|
|
140
|
+
# "TestTesting::HardJob"=>[
|
|
122
141
|
# {
|
|
123
|
-
# "class"=>"TestTesting::
|
|
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
|
-
#
|
|
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
|
|
161
|
+
# You can also clear all jobs:
|
|
143
162
|
#
|
|
144
163
|
# assert_equal 0, Sidekiq::Queues["default"].size
|
|
145
|
-
#
|
|
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
|
-
|
|
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
|
|
172
|
-
@
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
207
|
+
jobs_by_class.clear
|
|
188
208
|
end
|
|
189
209
|
end
|
|
190
210
|
end
|
|
191
211
|
|
|
192
|
-
module
|
|
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,
|
|
207
|
-
#
|
|
208
|
-
# assert_equal 1,
|
|
209
|
-
# assert_equal :something,
|
|
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
|
-
#
|
|
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
|
-
#
|
|
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::
|
|
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::
|
|
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
|
-
|
|
255
|
+
get_sidekiq_options["queue"]
|
|
253
256
|
end
|
|
254
257
|
|
|
255
258
|
# Jobs queued for this worker
|
|
256
259
|
def jobs
|
|
257
|
-
Queues.
|
|
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,
|
|
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"],
|
|
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,
|
|
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
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
Sidekiq::Testing.server_middleware.invoke(
|
|
287
|
-
execute_job(
|
|
286
|
+
instance = new
|
|
287
|
+
instance.jid = job["jid"]
|
|
288
|
+
instance.bid = job["bid"] if instance.respond_to?(:bid=)
|
|
289
|
+
Sidekiq::Testing.server_middleware.invoke(instance, job, job["queue"]) do
|
|
290
|
+
execute_job(instance, 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
|
|
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
|
|
309
|
+
# Drain (execute) all queued jobs
|
|
307
310
|
def drain_all
|
|
308
311
|
while jobs.any?
|
|
309
|
-
|
|
312
|
+
job_classes = jobs.map { |job| job["class"] }.uniq
|
|
310
313
|
|
|
311
|
-
|
|
312
|
-
|
|
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
|
-
|
|
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,59 @@
|
|
|
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
|
+
@transaction_backend =
|
|
11
|
+
if ActiveRecord.version >= Gem::Version.new("7.2")
|
|
12
|
+
ActiveRecord.method(:after_all_transactions_commit)
|
|
13
|
+
else
|
|
14
|
+
AfterCommitEverywhere.method(:after_commit)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def batching?
|
|
19
|
+
Thread.current[:sidekiq_batch]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def push(item)
|
|
23
|
+
# 6160 we can't support both Sidekiq::Batch and transactions.
|
|
24
|
+
return @redis_client.push(item) if batching?
|
|
25
|
+
|
|
26
|
+
# pre-allocate the JID so we can return it immediately and
|
|
27
|
+
# save it to the database as part of the transaction.
|
|
28
|
+
item["jid"] ||= SecureRandom.hex(12)
|
|
29
|
+
@transaction_backend.call { @redis_client.push(item) }
|
|
30
|
+
item["jid"]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
##
|
|
34
|
+
# We don't provide transactionality for push_bulk because we don't want
|
|
35
|
+
# to hold potentially hundreds of thousands of job records in memory due to
|
|
36
|
+
# a long running enqueue process.
|
|
37
|
+
def push_bulk(items)
|
|
38
|
+
@redis_client.push_bulk(items)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
##
|
|
44
|
+
# Use `Sidekiq.transactional_push!` in your sidekiq.rb initializer
|
|
45
|
+
module Sidekiq
|
|
46
|
+
def self.transactional_push!
|
|
47
|
+
if ActiveRecord.version < Gem::Version.new("7.2")
|
|
48
|
+
begin
|
|
49
|
+
require "after_commit_everywhere"
|
|
50
|
+
rescue LoadError
|
|
51
|
+
raise %q(You need ActiveRecord >= 7.2 or to add `gem "after_commit_everywhere"` to your Gemfile to use Sidekiq's transactional client)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
Sidekiq.default_job_options["client_class"] = Sidekiq::TransactionAwareClient
|
|
56
|
+
Sidekiq::JobUtil::TRANSIENT_ATTRIBUTES << "client_class"
|
|
57
|
+
true
|
|
58
|
+
end
|
|
59
|
+
end
|
data/lib/sidekiq/version.rb
CHANGED
data/lib/sidekiq/web/action.rb
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Sidekiq
|
|
4
4
|
class WebAction
|
|
5
|
-
RACK_SESSION =
|
|
5
|
+
RACK_SESSION = "rack.session"
|
|
6
6
|
|
|
7
7
|
attr_accessor :env, :block, :type
|
|
8
8
|
|
|
@@ -15,39 +15,61 @@ 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, {
|
|
22
|
+
throw :halt, [302, {Web::LOCATION => "#{request.base_url}#{location}"}, []]
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
def reload_page
|
|
26
|
+
current_location = request.referer.gsub(request.base_url, "")
|
|
27
|
+
redirect current_location
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# deprecated, will warn in 8.0
|
|
25
31
|
def params
|
|
26
|
-
indifferent_hash = Hash.new {|hash,key| hash[key.to_s] if Symbol === key }
|
|
32
|
+
indifferent_hash = Hash.new { |hash, key| hash[key.to_s] if Symbol === key }
|
|
27
33
|
|
|
28
34
|
indifferent_hash.merge! request.params
|
|
29
|
-
route_params.each {|k,v| indifferent_hash[k.to_s] = v }
|
|
35
|
+
route_params.each { |k, v| indifferent_hash[k.to_s] = v }
|
|
30
36
|
|
|
31
37
|
indifferent_hash
|
|
32
38
|
end
|
|
33
39
|
|
|
34
|
-
|
|
35
|
-
|
|
40
|
+
# Use like `url_params("page")` within your action blocks
|
|
41
|
+
def url_params(key)
|
|
42
|
+
request.params[key]
|
|
36
43
|
end
|
|
37
44
|
|
|
38
|
-
|
|
39
|
-
|
|
45
|
+
# Use like `route_params(:name)` within your action blocks
|
|
46
|
+
# key is required in 8.0, nil is only used for backwards compatibility
|
|
47
|
+
def route_params(key = nil)
|
|
48
|
+
if key
|
|
49
|
+
env[WebRouter::ROUTE_PARAMS][key]
|
|
50
|
+
else
|
|
51
|
+
env[WebRouter::ROUTE_PARAMS]
|
|
52
|
+
end
|
|
40
53
|
end
|
|
41
54
|
|
|
42
|
-
def
|
|
43
|
-
|
|
55
|
+
def session
|
|
56
|
+
env[RACK_SESSION]
|
|
44
57
|
end
|
|
45
58
|
|
|
46
59
|
def erb(content, options = {})
|
|
47
|
-
if content.
|
|
60
|
+
if content.is_a? Symbol
|
|
48
61
|
unless respond_to?(:"_erb_#{content}")
|
|
49
|
-
|
|
50
|
-
|
|
62
|
+
views = options[:views] || Web.settings.views
|
|
63
|
+
filename = "#{views}/#{content}.erb"
|
|
64
|
+
src = ERB.new(File.read(filename)).src
|
|
65
|
+
|
|
66
|
+
# Need to use lineno less by 1 because erb generates a
|
|
67
|
+
# comment before the source code.
|
|
68
|
+
WebAction.class_eval <<-RUBY, filename, -1 # standard:disable Style/EvalWithLocation
|
|
69
|
+
def _erb_#{content}
|
|
70
|
+
#{src}
|
|
71
|
+
end
|
|
72
|
+
RUBY
|
|
51
73
|
end
|
|
52
74
|
end
|
|
53
75
|
|
|
@@ -68,22 +90,22 @@ module Sidekiq
|
|
|
68
90
|
end
|
|
69
91
|
|
|
70
92
|
def json(payload)
|
|
71
|
-
[200, {
|
|
93
|
+
[200, {Rack::CONTENT_TYPE => "application/json", Rack::CACHE_CONTROL => "private, no-store"}, [Sidekiq.dump_json(payload)]]
|
|
72
94
|
end
|
|
73
95
|
|
|
74
96
|
def initialize(env, block)
|
|
75
97
|
@_erb = false
|
|
76
98
|
@env = env
|
|
77
99
|
@block = block
|
|
78
|
-
|
|
100
|
+
@files ||= {}
|
|
79
101
|
end
|
|
80
102
|
|
|
81
103
|
private
|
|
82
104
|
|
|
83
105
|
def _erb(file, locals)
|
|
84
|
-
locals
|
|
106
|
+
locals&.each { |k, v| define_singleton_method(k) { v } unless singleton_methods.include? k }
|
|
85
107
|
|
|
86
|
-
if file.
|
|
108
|
+
if file.is_a?(String)
|
|
87
109
|
ERB.new(file).result(binding)
|
|
88
110
|
else
|
|
89
111
|
send(:"_erb_#{file}")
|