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
data/lib/sidekiq/web.rb
CHANGED
|
@@ -1,49 +1,62 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
require 'erb'
|
|
3
2
|
|
|
4
|
-
require
|
|
5
|
-
require
|
|
6
|
-
require 'sidekiq/paginator'
|
|
7
|
-
require 'sidekiq/web/helpers'
|
|
3
|
+
require "erb"
|
|
4
|
+
require "securerandom"
|
|
8
5
|
|
|
9
|
-
require
|
|
10
|
-
require
|
|
11
|
-
require
|
|
6
|
+
require "sidekiq"
|
|
7
|
+
require "sidekiq/api"
|
|
8
|
+
require "sidekiq/paginator"
|
|
9
|
+
require "sidekiq/web/helpers"
|
|
12
10
|
|
|
13
|
-
require
|
|
11
|
+
require "sidekiq/web/router"
|
|
12
|
+
require "sidekiq/web/action"
|
|
13
|
+
require "sidekiq/web/application"
|
|
14
|
+
require "sidekiq/web/csrf_protection"
|
|
14
15
|
|
|
15
|
-
require
|
|
16
|
-
require
|
|
17
|
-
require
|
|
16
|
+
require "rack/content_length"
|
|
17
|
+
require "rack/builder"
|
|
18
|
+
require "rack/static"
|
|
18
19
|
|
|
19
20
|
module Sidekiq
|
|
20
21
|
class Web
|
|
21
22
|
ROOT = File.expand_path("#{File.dirname(__FILE__)}/../../web")
|
|
22
|
-
VIEWS = "#{ROOT}/views"
|
|
23
|
-
LOCALES = ["#{ROOT}/locales"
|
|
24
|
-
LAYOUT = "#{VIEWS}/layout.erb"
|
|
25
|
-
ASSETS = "#{ROOT}/assets"
|
|
23
|
+
VIEWS = "#{ROOT}/views"
|
|
24
|
+
LOCALES = ["#{ROOT}/locales"]
|
|
25
|
+
LAYOUT = "#{VIEWS}/layout.erb"
|
|
26
|
+
ASSETS = "#{ROOT}/assets"
|
|
26
27
|
|
|
27
28
|
DEFAULT_TABS = {
|
|
28
|
-
"Dashboard" =>
|
|
29
|
-
"Busy"
|
|
30
|
-
"Queues"
|
|
31
|
-
"Retries"
|
|
32
|
-
"Scheduled" =>
|
|
33
|
-
"Dead"
|
|
29
|
+
"Dashboard" => "",
|
|
30
|
+
"Busy" => "busy",
|
|
31
|
+
"Queues" => "queues",
|
|
32
|
+
"Retries" => "retries",
|
|
33
|
+
"Scheduled" => "scheduled",
|
|
34
|
+
"Dead" => "morgue",
|
|
35
|
+
"Metrics" => "metrics"
|
|
34
36
|
}
|
|
35
37
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
if Gem::Version.new(Rack::RELEASE) < Gem::Version.new("3")
|
|
39
|
+
CONTENT_LANGUAGE = "Content-Language"
|
|
40
|
+
CONTENT_SECURITY_POLICY = "Content-Security-Policy"
|
|
41
|
+
LOCATION = "Location"
|
|
42
|
+
X_CASCADE = "X-Cascade"
|
|
43
|
+
X_CONTENT_TYPE_OPTIONS = "X-Content-Type-Options"
|
|
44
|
+
else
|
|
45
|
+
CONTENT_LANGUAGE = "content-language"
|
|
46
|
+
CONTENT_SECURITY_POLICY = "content-security-policy"
|
|
47
|
+
LOCATION = "location"
|
|
48
|
+
X_CASCADE = "x-cascade"
|
|
49
|
+
X_CONTENT_TYPE_OPTIONS = "x-content-type-options"
|
|
50
|
+
end
|
|
40
51
|
|
|
41
|
-
|
|
42
|
-
|
|
52
|
+
class << self
|
|
53
|
+
# Forward compatibility with 8.0
|
|
54
|
+
def configure
|
|
55
|
+
yield self
|
|
43
56
|
end
|
|
44
57
|
|
|
45
|
-
def
|
|
46
|
-
|
|
58
|
+
def settings
|
|
59
|
+
self
|
|
47
60
|
end
|
|
48
61
|
|
|
49
62
|
def default_tabs
|
|
@@ -55,6 +68,10 @@ module Sidekiq
|
|
|
55
68
|
end
|
|
56
69
|
alias_method :tabs, :custom_tabs
|
|
57
70
|
|
|
71
|
+
def custom_job_info_rows
|
|
72
|
+
@custom_job_info_rows ||= []
|
|
73
|
+
end
|
|
74
|
+
|
|
58
75
|
def locales
|
|
59
76
|
@locales ||= LOCALES
|
|
60
77
|
end
|
|
@@ -64,42 +81,48 @@ module Sidekiq
|
|
|
64
81
|
end
|
|
65
82
|
|
|
66
83
|
def enable(*opts)
|
|
67
|
-
opts.each {|key| set(key, true) }
|
|
84
|
+
opts.each { |key| set(key, true) }
|
|
68
85
|
end
|
|
69
86
|
|
|
70
87
|
def disable(*opts)
|
|
71
|
-
opts.each {|key| set(key, false) }
|
|
88
|
+
opts.each { |key| set(key, false) }
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def middlewares
|
|
92
|
+
@middlewares ||= []
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def use(*args, &block)
|
|
96
|
+
middlewares << [args, block]
|
|
72
97
|
end
|
|
73
98
|
|
|
74
|
-
# Helper for the Sinatra syntax: Sidekiq::Web.set(:session_secret, Rails.application.secrets...)
|
|
75
99
|
def set(attribute, value)
|
|
76
100
|
send(:"#{attribute}=", value)
|
|
77
101
|
end
|
|
78
102
|
|
|
79
|
-
attr_accessor :app_url, :
|
|
103
|
+
attr_accessor :app_url, :redis_pool
|
|
80
104
|
attr_writer :locales, :views
|
|
81
105
|
end
|
|
82
106
|
|
|
83
107
|
def self.inherited(child)
|
|
84
|
-
child.app_url =
|
|
85
|
-
child.
|
|
86
|
-
child.redis_pool = self.redis_pool
|
|
87
|
-
child.sessions = self.sessions
|
|
108
|
+
child.app_url = app_url
|
|
109
|
+
child.redis_pool = redis_pool
|
|
88
110
|
end
|
|
89
111
|
|
|
90
112
|
def settings
|
|
91
113
|
self.class.settings
|
|
92
114
|
end
|
|
93
115
|
|
|
94
|
-
def
|
|
95
|
-
middlewares
|
|
116
|
+
def middlewares
|
|
117
|
+
@middlewares ||= self.class.middlewares
|
|
96
118
|
end
|
|
97
119
|
|
|
98
|
-
def
|
|
99
|
-
|
|
120
|
+
def use(*args, &block)
|
|
121
|
+
middlewares << [args, block]
|
|
100
122
|
end
|
|
101
123
|
|
|
102
124
|
def call(env)
|
|
125
|
+
env[:csp_nonce] = SecureRandom.base64(16)
|
|
103
126
|
app.call(env)
|
|
104
127
|
end
|
|
105
128
|
|
|
@@ -113,81 +136,80 @@ module Sidekiq
|
|
|
113
136
|
end
|
|
114
137
|
|
|
115
138
|
def enable(*opts)
|
|
116
|
-
opts.each {|key| set(key, true) }
|
|
139
|
+
opts.each { |key| set(key, true) }
|
|
117
140
|
end
|
|
118
141
|
|
|
119
142
|
def disable(*opts)
|
|
120
|
-
opts.each {|key| set(key, false) }
|
|
143
|
+
opts.each { |key| set(key, false) }
|
|
121
144
|
end
|
|
122
145
|
|
|
123
146
|
def set(attribute, value)
|
|
124
147
|
send(:"#{attribute}=", value)
|
|
125
148
|
end
|
|
126
149
|
|
|
127
|
-
#
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
150
|
+
# Register a class as a Sidekiq Web UI extension. The class should
|
|
151
|
+
# provide one or more tabs which map to an index route. Options:
|
|
152
|
+
#
|
|
153
|
+
# @param extension [Class] Class which contains the HTTP actions, required
|
|
154
|
+
# @param name [String] the name of the extension, used to namespace assets
|
|
155
|
+
# @param tab [String | Array] labels(s) of the UI tabs
|
|
156
|
+
# @param index [String | Array] index route(s) for each tab
|
|
157
|
+
# @param root_dir [String] directory location to find assets, locales and views, typically `web/` within the gemfile
|
|
158
|
+
# @param asset_paths [Array] one or more directories under {root}/assets/{name} to be publicly served, e.g. ["js", "css", "img"]
|
|
159
|
+
# @param cache_for [Integer] amount of time to cache assets, default one day
|
|
160
|
+
#
|
|
161
|
+
# TODO name, tab and index will be mandatory in 8.0
|
|
162
|
+
#
|
|
163
|
+
# Web extensions will have a root `web/` directory with `locales/`, `assets/`
|
|
164
|
+
# and `views/` subdirectories.
|
|
165
|
+
def self.register(extension, name: nil, tab: nil, index: nil, root_dir: nil, cache_for: 86400, asset_paths: nil)
|
|
166
|
+
tab = Array(tab)
|
|
167
|
+
index = Array(index)
|
|
168
|
+
tab.zip(index).each do |tab, index|
|
|
169
|
+
tabs[tab] = index
|
|
170
|
+
end
|
|
171
|
+
if root_dir
|
|
172
|
+
locdir = File.join(root_dir, "locales")
|
|
173
|
+
locales << locdir if File.directory?(locdir)
|
|
174
|
+
|
|
175
|
+
if asset_paths && name
|
|
176
|
+
# if you have {root}/assets/{name}/js/scripts.js
|
|
177
|
+
# and {root}/assets/{name}/css/styles.css
|
|
178
|
+
# you would pass in:
|
|
179
|
+
# asset_paths: ["js", "css"]
|
|
180
|
+
# See script_tag and style_tag in web/helpers.rb
|
|
181
|
+
assdir = File.join(root_dir, "assets")
|
|
182
|
+
assurls = Array(asset_paths).map { |x| "/#{name}/#{x}" }
|
|
183
|
+
assetprops = {
|
|
184
|
+
urls: assurls,
|
|
185
|
+
root: assdir,
|
|
186
|
+
cascade: true
|
|
187
|
+
}
|
|
188
|
+
assetprops[:header_rules] = [[:all, {Rack::CACHE_CONTROL => "private, max-age=#{cache_for.to_i}"}]] if cache_for
|
|
189
|
+
middlewares << [[Rack::Static, assetprops], nil]
|
|
190
|
+
end
|
|
136
191
|
end
|
|
137
192
|
|
|
138
|
-
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
def self.register(extension)
|
|
193
|
+
yield self if block_given?
|
|
142
194
|
extension.registered(WebApplication)
|
|
143
195
|
end
|
|
144
196
|
|
|
145
197
|
private
|
|
146
198
|
|
|
147
|
-
def using?(middleware)
|
|
148
|
-
middlewares.any? do |(m,_)|
|
|
149
|
-
m.kind_of?(Array) && (m[0] == middleware || m[0].kind_of?(middleware))
|
|
150
|
-
end
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
def build_sessions
|
|
154
|
-
middlewares = self.middlewares
|
|
155
|
-
|
|
156
|
-
unless using?(::Rack::Protection) || ENV['RACK_ENV'] == 'test'
|
|
157
|
-
middlewares.unshift [[::Rack::Protection, { use: :authenticity_token }], nil]
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
s = sessions
|
|
161
|
-
return unless s
|
|
162
|
-
|
|
163
|
-
unless using? ::Rack::Session::Cookie
|
|
164
|
-
unless secret = Web.session_secret
|
|
165
|
-
require 'securerandom'
|
|
166
|
-
secret = SecureRandom.hex(64)
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
options = { secret: secret }
|
|
170
|
-
options = options.merge(s.to_hash) if s.respond_to? :to_hash
|
|
171
|
-
|
|
172
|
-
middlewares.unshift [[::Rack::Session::Cookie, options], nil]
|
|
173
|
-
end
|
|
174
|
-
end
|
|
175
|
-
|
|
176
199
|
def build
|
|
177
|
-
build_sessions
|
|
178
|
-
|
|
179
|
-
middlewares = self.middlewares
|
|
180
200
|
klass = self.class
|
|
201
|
+
m = middlewares
|
|
181
202
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
map "/#{asset_dir}" do
|
|
185
|
-
run ::Rack::File.new("#{ASSETS}/#{asset_dir}", { 'Cache-Control' => 'public, max-age=86400' })
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
middlewares.each {|middleware, block| use(*middleware, &block) }
|
|
203
|
+
rules = []
|
|
204
|
+
rules = [[:all, {Rack::CACHE_CONTROL => "private, max-age=86400"}]] unless ENV["SIDEKIQ_WEB_TESTING"]
|
|
190
205
|
|
|
206
|
+
::Rack::Builder.new do
|
|
207
|
+
use Rack::Static, urls: ["/stylesheets", "/images", "/javascripts"],
|
|
208
|
+
root: ASSETS,
|
|
209
|
+
cascade: true,
|
|
210
|
+
header_rules: rules
|
|
211
|
+
m.each { |middleware, block| use(*middleware, &block) }
|
|
212
|
+
use Sidekiq::Web::CsrfProtection unless $TESTING
|
|
191
213
|
run WebApplication.new(klass)
|
|
192
214
|
end
|
|
193
215
|
end
|
|
@@ -196,18 +218,9 @@ module Sidekiq
|
|
|
196
218
|
Sidekiq::WebApplication.helpers WebHelpers
|
|
197
219
|
Sidekiq::WebApplication.helpers Sidekiq::Paginator
|
|
198
220
|
|
|
199
|
-
Sidekiq::WebAction.class_eval
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
if defined?(::ActionDispatch::Request::Session) &&
|
|
203
|
-
!::ActionDispatch::Request::Session.method_defined?(:each)
|
|
204
|
-
# mperham/sidekiq#2460
|
|
205
|
-
# Rack apps can't reuse the Rails session store without
|
|
206
|
-
# this monkeypatch, fixed in Rails 5.
|
|
207
|
-
class ActionDispatch::Request::Session
|
|
208
|
-
def each(&block)
|
|
209
|
-
hash = self.to_hash
|
|
210
|
-
hash.each(&block)
|
|
221
|
+
Sidekiq::WebAction.class_eval <<-RUBY, Web::LAYOUT, -1 # standard:disable Style/EvalWithLocation
|
|
222
|
+
def _render
|
|
223
|
+
#{ERB.new(File.read(Web::LAYOUT)).src}
|
|
211
224
|
end
|
|
212
|
-
|
|
225
|
+
RUBY
|
|
213
226
|
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sidekiq
|
|
4
|
+
# Sidekiq::Job is a new alias for Sidekiq::Worker as of Sidekiq 6.3.0.
|
|
5
|
+
# Use `include Sidekiq::Job` rather than `include Sidekiq::Worker`.
|
|
6
|
+
#
|
|
7
|
+
# The term "worker" is too generic and overly confusing, used in several
|
|
8
|
+
# different contexts meaning different things. Many people call a Sidekiq
|
|
9
|
+
# process a "worker". Some people call the thread that executes jobs a
|
|
10
|
+
# "worker". This change brings Sidekiq closer to ActiveJob where your job
|
|
11
|
+
# classes extend ApplicationJob.
|
|
12
|
+
Worker = Job
|
|
13
|
+
end
|
data/lib/sidekiq.rb
CHANGED
|
@@ -1,237 +1,149 @@
|
|
|
1
|
-
# encoding: utf-8
|
|
2
1
|
# frozen_string_literal: true
|
|
3
|
-
require 'sidekiq/version'
|
|
4
|
-
fail "Sidekiq #{Sidekiq::VERSION} does not support Ruby versions below 2.0.0." if RUBY_PLATFORM != 'java' && RUBY_VERSION < '2.0.0'
|
|
5
2
|
|
|
6
|
-
require
|
|
7
|
-
|
|
8
|
-
require 'sidekiq/worker'
|
|
9
|
-
require 'sidekiq/redis_connection'
|
|
3
|
+
require "sidekiq/version"
|
|
4
|
+
fail "Sidekiq #{Sidekiq::VERSION} does not support Ruby versions below 2.7.0." if RUBY_PLATFORM != "java" && Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.7.0")
|
|
10
5
|
|
|
11
|
-
|
|
6
|
+
begin
|
|
7
|
+
require "sidekiq-ent/version"
|
|
8
|
+
fail <<~EOM if Gem::Version.new(Sidekiq::Enterprise::VERSION).segments[0] != Sidekiq::MAJOR
|
|
12
9
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
DEFAULTS = {
|
|
18
|
-
queues: [],
|
|
19
|
-
labels: [],
|
|
20
|
-
concurrency: 25,
|
|
21
|
-
require: '.',
|
|
22
|
-
environment: nil,
|
|
23
|
-
timeout: 8,
|
|
24
|
-
poll_interval_average: nil,
|
|
25
|
-
average_scheduled_poll_interval: 15,
|
|
26
|
-
error_handlers: [],
|
|
27
|
-
lifecycle_events: {
|
|
28
|
-
startup: [],
|
|
29
|
-
quiet: [],
|
|
30
|
-
shutdown: [],
|
|
31
|
-
heartbeat: [],
|
|
32
|
-
},
|
|
33
|
-
dead_max_jobs: 10_000,
|
|
34
|
-
dead_timeout_in_seconds: 180 * 24 * 60 * 60, # 6 months
|
|
35
|
-
reloader: proc { |&block| block.call },
|
|
36
|
-
executor: proc { |&block| block.call },
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
DEFAULT_WORKER_OPTIONS = {
|
|
40
|
-
'retry' => true,
|
|
41
|
-
'queue' => 'default'
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
FAKE_INFO = {
|
|
45
|
-
"redis_version" => "9.9.9",
|
|
46
|
-
"uptime_in_days" => "9999",
|
|
47
|
-
"connected_clients" => "9999",
|
|
48
|
-
"used_memory_human" => "9P",
|
|
49
|
-
"used_memory_peak_human" => "9P"
|
|
50
|
-
}.freeze
|
|
10
|
+
Sidekiq Enterprise #{Sidekiq::Enterprise::VERSION} does not work with Sidekiq #{Sidekiq::VERSION}.
|
|
11
|
+
Starting with Sidekiq 7, major versions are synchronized so Sidekiq Enterprise 7 works with Sidekiq 7.
|
|
12
|
+
Use `bundle up sidekiq-ent` to upgrade.
|
|
51
13
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
14
|
+
EOM
|
|
15
|
+
rescue LoadError
|
|
16
|
+
end
|
|
55
17
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
def self.options=(opts)
|
|
60
|
-
@options = opts
|
|
61
|
-
end
|
|
18
|
+
begin
|
|
19
|
+
require "sidekiq/pro/version"
|
|
20
|
+
fail <<~EOM if Gem::Version.new(Sidekiq::Pro::VERSION).segments[0] != Sidekiq::MAJOR
|
|
62
21
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
# Sidekiq.configure_server do |config|
|
|
67
|
-
# config.redis = { :namespace => 'myapp', :size => 25, :url => 'redis://myhost:8877/0' }
|
|
68
|
-
# config.server_middleware do |chain|
|
|
69
|
-
# chain.add MyServerHook
|
|
70
|
-
# end
|
|
71
|
-
# end
|
|
72
|
-
def self.configure_server
|
|
73
|
-
yield self if server?
|
|
74
|
-
end
|
|
22
|
+
Sidekiq Pro #{Sidekiq::Pro::VERSION} does not work with Sidekiq #{Sidekiq::VERSION}.
|
|
23
|
+
Starting with Sidekiq 7, major versions are synchronized so Sidekiq Pro 7 works with Sidekiq 7.
|
|
24
|
+
Use `bundle up sidekiq-pro` to upgrade.
|
|
75
25
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
26
|
+
EOM
|
|
27
|
+
rescue LoadError
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
require "sidekiq/config"
|
|
31
|
+
require "sidekiq/logger"
|
|
32
|
+
require "sidekiq/client"
|
|
33
|
+
require "sidekiq/transaction_aware_client"
|
|
34
|
+
require "sidekiq/job"
|
|
35
|
+
require "sidekiq/iterable_job"
|
|
36
|
+
require "sidekiq/worker_compatibility_alias"
|
|
37
|
+
require "sidekiq/redis_client_adapter"
|
|
38
|
+
|
|
39
|
+
require "json"
|
|
40
|
+
|
|
41
|
+
module Sidekiq
|
|
42
|
+
NAME = "Sidekiq"
|
|
43
|
+
LICENSE = "See LICENSE and the LGPL-3.0 for licensing details."
|
|
44
|
+
|
|
45
|
+
def self.❨╯°□°❩╯︵┻━┻
|
|
46
|
+
puts "Take a deep breath and count to ten..."
|
|
84
47
|
end
|
|
85
48
|
|
|
86
49
|
def self.server?
|
|
87
50
|
defined?(Sidekiq::CLI)
|
|
88
51
|
end
|
|
89
52
|
|
|
90
|
-
def self.
|
|
91
|
-
|
|
92
|
-
redis_pool.with do |conn|
|
|
93
|
-
retryable = true
|
|
94
|
-
begin
|
|
95
|
-
yield conn
|
|
96
|
-
rescue Redis::CommandError => ex
|
|
97
|
-
#2550 Failover can cause the server to become a slave, need
|
|
98
|
-
# to disconnect and reopen the socket to get back to the master.
|
|
99
|
-
(conn.disconnect!; retryable = false; retry) if retryable && ex.message =~ /READONLY/
|
|
100
|
-
raise
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def self.redis_info
|
|
106
|
-
redis do |conn|
|
|
107
|
-
begin
|
|
108
|
-
# admin commands can't go through redis-namespace starting
|
|
109
|
-
# in redis-namespace 2.0
|
|
110
|
-
if conn.respond_to?(:namespace)
|
|
111
|
-
conn.redis.info
|
|
112
|
-
else
|
|
113
|
-
conn.info
|
|
114
|
-
end
|
|
115
|
-
rescue Redis::CommandError => ex
|
|
116
|
-
#2850 return fake version when INFO command has (probably) been renamed
|
|
117
|
-
raise unless ex.message =~ /unknown command/
|
|
118
|
-
FAKE_INFO
|
|
119
|
-
end
|
|
120
|
-
end
|
|
53
|
+
def self.load_json(string)
|
|
54
|
+
JSON.parse(string)
|
|
121
55
|
end
|
|
122
56
|
|
|
123
|
-
def self.
|
|
124
|
-
|
|
57
|
+
def self.dump_json(object)
|
|
58
|
+
JSON.generate(object)
|
|
125
59
|
end
|
|
126
60
|
|
|
127
|
-
def self.
|
|
128
|
-
|
|
129
|
-
hash
|
|
130
|
-
else
|
|
131
|
-
Sidekiq::RedisConnection.create(hash)
|
|
132
|
-
end
|
|
61
|
+
def self.pro?
|
|
62
|
+
defined?(Sidekiq::Pro)
|
|
133
63
|
end
|
|
134
64
|
|
|
135
|
-
def self.
|
|
136
|
-
|
|
137
|
-
yield @client_chain if block_given?
|
|
138
|
-
@client_chain
|
|
65
|
+
def self.ent?
|
|
66
|
+
defined?(Sidekiq::Enterprise)
|
|
139
67
|
end
|
|
140
68
|
|
|
141
|
-
def self.
|
|
142
|
-
|
|
143
|
-
yield @server_chain if block_given?
|
|
144
|
-
@server_chain
|
|
69
|
+
def self.redis_pool
|
|
70
|
+
(Thread.current[:sidekiq_capsule] || default_configuration).redis_pool
|
|
145
71
|
end
|
|
146
72
|
|
|
147
|
-
def self.
|
|
148
|
-
|
|
149
|
-
require 'sidekiq/middleware/server/logging'
|
|
150
|
-
|
|
151
|
-
Middleware::Chain.new do |m|
|
|
152
|
-
m.add Middleware::Server::RetryJobs
|
|
153
|
-
m.add Middleware::Server::Logging
|
|
154
|
-
end
|
|
73
|
+
def self.redis(&block)
|
|
74
|
+
(Thread.current[:sidekiq_capsule] || default_configuration).redis(&block)
|
|
155
75
|
end
|
|
156
76
|
|
|
157
|
-
def self.
|
|
158
|
-
|
|
159
|
-
end
|
|
160
|
-
def self.default_worker_options
|
|
161
|
-
defined?(@default_worker_options) ? @default_worker_options : DEFAULT_WORKER_OPTIONS
|
|
77
|
+
def self.strict_args!(mode = :raise)
|
|
78
|
+
Sidekiq::Config::DEFAULTS[:on_complex_arguments] = mode
|
|
162
79
|
end
|
|
163
80
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
# end
|
|
167
|
-
# end
|
|
168
|
-
def self.default_retries_exhausted=(prok)
|
|
169
|
-
@default_retries_exhausted = prok
|
|
170
|
-
end
|
|
171
|
-
@default_retries_exhausted = ->(job, ex) { }
|
|
172
|
-
def self.default_retries_exhausted
|
|
173
|
-
@default_retries_exhausted
|
|
81
|
+
def self.default_job_options=(hash)
|
|
82
|
+
@default_job_options = default_job_options.merge(hash.transform_keys(&:to_s))
|
|
174
83
|
end
|
|
175
84
|
|
|
176
|
-
def self.
|
|
177
|
-
|
|
85
|
+
def self.default_job_options
|
|
86
|
+
@default_job_options ||= {"retry" => true, "queue" => "default"}
|
|
178
87
|
end
|
|
179
|
-
|
|
180
|
-
|
|
88
|
+
|
|
89
|
+
def self.default_configuration
|
|
90
|
+
@config ||= Sidekiq::Config.new
|
|
181
91
|
end
|
|
182
92
|
|
|
183
93
|
def self.logger
|
|
184
|
-
|
|
94
|
+
default_configuration.logger
|
|
185
95
|
end
|
|
186
|
-
|
|
187
|
-
|
|
96
|
+
|
|
97
|
+
def self.configure_server(&block)
|
|
98
|
+
(@config_blocks ||= []) << block
|
|
99
|
+
yield default_configuration if server?
|
|
188
100
|
end
|
|
189
101
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
# See sidekiq/scheduled.rb for an in-depth explanation of this value
|
|
195
|
-
def self.average_scheduled_poll_interval=(interval)
|
|
196
|
-
self.options[:average_scheduled_poll_interval] = interval
|
|
102
|
+
def self.freeze!
|
|
103
|
+
@frozen = true
|
|
104
|
+
@config_blocks = nil
|
|
105
|
+
default_configuration.freeze!
|
|
197
106
|
end
|
|
198
107
|
|
|
199
|
-
#
|
|
108
|
+
# Creates a Sidekiq::Config instance that is more tuned for embedding
|
|
109
|
+
# within an arbitrary Ruby process. Notably it reduces concurrency by
|
|
110
|
+
# default so there is less contention for CPU time with other threads.
|
|
200
111
|
#
|
|
201
|
-
# Sidekiq.
|
|
202
|
-
# config.
|
|
112
|
+
# instance = Sidekiq.configure_embed do |config|
|
|
113
|
+
# config.queues = %w[critical default low]
|
|
203
114
|
# end
|
|
115
|
+
# instance.run
|
|
116
|
+
# sleep 10
|
|
117
|
+
# instance.stop
|
|
204
118
|
#
|
|
205
|
-
#
|
|
206
|
-
|
|
207
|
-
|
|
119
|
+
# NB: it is really easy to overload a Ruby process with threads due to the GIL.
|
|
120
|
+
# I do not recommend setting concurrency higher than 2-3.
|
|
121
|
+
#
|
|
122
|
+
# NB: Sidekiq only supports one instance in memory. You will get undefined behavior
|
|
123
|
+
# if you try to embed Sidekiq twice in the same process.
|
|
124
|
+
def self.configure_embed(&block)
|
|
125
|
+
raise "Sidekiq global configuration is frozen, you must create all embedded instances BEFORE calling `run`" if @frozen
|
|
126
|
+
|
|
127
|
+
require "sidekiq/embedded"
|
|
128
|
+
cfg = default_configuration
|
|
129
|
+
cfg.concurrency = 2
|
|
130
|
+
@config_blocks&.each { |block| block.call(cfg) }
|
|
131
|
+
yield cfg
|
|
132
|
+
|
|
133
|
+
Sidekiq::Embedded.new(cfg)
|
|
208
134
|
end
|
|
209
135
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
#
|
|
213
|
-
# Sidekiq.configure_server do |config|
|
|
214
|
-
# config.on(:shutdown) do
|
|
215
|
-
# puts "Goodbye cruel world!"
|
|
216
|
-
# end
|
|
217
|
-
# end
|
|
218
|
-
def self.on(event, &block)
|
|
219
|
-
raise ArgumentError, "Symbols only please: #{event}" unless event.is_a?(Symbol)
|
|
220
|
-
raise ArgumentError, "Invalid event name: #{event}" unless options[:lifecycle_events].key?(event)
|
|
221
|
-
options[:lifecycle_events][event] << block
|
|
136
|
+
def self.configure_client
|
|
137
|
+
yield default_configuration unless server?
|
|
222
138
|
end
|
|
223
139
|
|
|
224
|
-
# We are shutting down Sidekiq but what about
|
|
140
|
+
# We are shutting down Sidekiq but what about threads that
|
|
225
141
|
# are working on some long job? This error is
|
|
226
|
-
# raised in
|
|
142
|
+
# raised in jobs that have not finished within the hard
|
|
227
143
|
# timeout limit. This is needed to rollback db transactions,
|
|
228
144
|
# otherwise Ruby's Thread#kill will commit. See #377.
|
|
229
|
-
# DO NOT RESCUE THIS ERROR IN YOUR
|
|
145
|
+
# DO NOT RESCUE THIS ERROR IN YOUR JOBS
|
|
230
146
|
class Shutdown < Interrupt; end
|
|
231
|
-
|
|
232
147
|
end
|
|
233
148
|
|
|
234
|
-
require
|
|
235
|
-
require 'sidekiq/extensions/action_mailer'
|
|
236
|
-
require 'sidekiq/extensions/active_record'
|
|
237
|
-
require 'sidekiq/rails' if defined?(::Rails::Engine)
|
|
149
|
+
require "sidekiq/rails" if defined?(::Rails::Engine)
|