sidekiq 4.2.10 → 7.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Changes.md +859 -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 +212 -119
- data/bin/sidekiqmon +11 -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 +680 -315
- data/lib/sidekiq/capsule.rb +132 -0
- data/lib/sidekiq/cli.rb +268 -248
- data/lib/sidekiq/client.rb +136 -101
- data/lib/sidekiq/component.rb +68 -0
- data/lib/sidekiq/config.rb +293 -0
- data/lib/sidekiq/deploy.rb +64 -0
- data/lib/sidekiq/embedded.rb +63 -0
- data/lib/sidekiq/fetch.rb +49 -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 +231 -0
- data/lib/sidekiq/job.rb +385 -0
- data/lib/sidekiq/job_logger.rb +62 -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 +97 -0
- data/lib/sidekiq/metrics/tracking.rb +148 -0
- data/lib/sidekiq/middleware/chain.rb +113 -56
- data/lib/sidekiq/middleware/current_attributes.rb +113 -0
- data/lib/sidekiq/middleware/i18n.rb +7 -7
- data/lib/sidekiq/middleware/modules.rb +23 -0
- data/lib/sidekiq/monitor.rb +147 -0
- data/lib/sidekiq/paginator.rb +28 -16
- data/lib/sidekiq/processor.rb +188 -98
- data/lib/sidekiq/rails.rb +46 -97
- data/lib/sidekiq/redis_client_adapter.rb +114 -0
- data/lib/sidekiq/redis_connection.rb +71 -73
- data/lib/sidekiq/ring_buffer.rb +31 -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 +51 -0
- data/lib/sidekiq/version.rb +3 -1
- data/lib/sidekiq/web/action.rb +22 -16
- data/lib/sidekiq/web/application.rb +230 -86
- data/lib/sidekiq/web/csrf_protection.rb +183 -0
- data/lib/sidekiq/web/helpers.rb +241 -104
- data/lib/sidekiq/web/router.rb +23 -19
- data/lib/sidekiq/web.rb +118 -110
- data/lib/sidekiq/worker_compatibility_alias.rb +13 -0
- data/lib/sidekiq.rb +96 -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 +192 -0
- data/web/assets/javascripts/dashboard.js +37 -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 +173 -198
- 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 +86 -64
- data/web/locales/es.yml +70 -53
- data/web/locales/fa.yml +65 -64
- data/web/locales/fr.yml +83 -62
- data/web/locales/gd.yml +99 -0
- data/web/locales/he.yml +80 -0
- data/web/locales/hi.yml +59 -59
- data/web/locales/it.yml +53 -53
- data/web/locales/ja.yml +75 -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 +83 -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 +101 -0
- data/web/locales/uk.yml +62 -61
- data/web/locales/ur.yml +80 -0
- data/web/locales/vi.yml +83 -0
- data/web/locales/zh-cn.yml +43 -16
- data/web/locales/zh-tw.yml +42 -8
- data/web/views/_footer.erb +21 -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 +50 -20
- data/web/views/dead.erb +3 -3
- data/web/views/filtering.erb +7 -0
- data/web/views/layout.erb +17 -6
- data/web/views/metrics.erb +91 -0
- data/web/views/metrics_for_job.erb +59 -0
- data/web/views/morgue.erb +14 -15
- data/web/views/queue.erb +34 -24
- 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 +91 -198
- 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,51 +1,59 @@
|
|
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
|
|
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
|
51
|
+
|
36
52
|
class << self
|
37
53
|
def settings
|
38
54
|
self
|
39
55
|
end
|
40
56
|
|
41
|
-
def middlewares
|
42
|
-
@middlewares ||= []
|
43
|
-
end
|
44
|
-
|
45
|
-
def use(*middleware_args, &block)
|
46
|
-
middlewares << [middleware_args, block]
|
47
|
-
end
|
48
|
-
|
49
57
|
def default_tabs
|
50
58
|
DEFAULT_TABS
|
51
59
|
end
|
@@ -55,6 +63,10 @@ module Sidekiq
|
|
55
63
|
end
|
56
64
|
alias_method :tabs, :custom_tabs
|
57
65
|
|
66
|
+
def custom_job_info_rows
|
67
|
+
@custom_job_info_rows ||= []
|
68
|
+
end
|
69
|
+
|
58
70
|
def locales
|
59
71
|
@locales ||= LOCALES
|
60
72
|
end
|
@@ -64,42 +76,48 @@ module Sidekiq
|
|
64
76
|
end
|
65
77
|
|
66
78
|
def enable(*opts)
|
67
|
-
opts.each {|key| set(key, true) }
|
79
|
+
opts.each { |key| set(key, true) }
|
68
80
|
end
|
69
81
|
|
70
82
|
def disable(*opts)
|
71
|
-
opts.each {|key| set(key, false) }
|
83
|
+
opts.each { |key| set(key, false) }
|
84
|
+
end
|
85
|
+
|
86
|
+
def middlewares
|
87
|
+
@middlewares ||= []
|
88
|
+
end
|
89
|
+
|
90
|
+
def use(*args, &block)
|
91
|
+
middlewares << [args, block]
|
72
92
|
end
|
73
93
|
|
74
|
-
# Helper for the Sinatra syntax: Sidekiq::Web.set(:session_secret, Rails.application.secrets...)
|
75
94
|
def set(attribute, value)
|
76
95
|
send(:"#{attribute}=", value)
|
77
96
|
end
|
78
97
|
|
79
|
-
attr_accessor :app_url, :
|
98
|
+
attr_accessor :app_url, :redis_pool
|
80
99
|
attr_writer :locales, :views
|
81
100
|
end
|
82
101
|
|
83
102
|
def self.inherited(child)
|
84
|
-
child.app_url =
|
85
|
-
child.
|
86
|
-
child.redis_pool = self.redis_pool
|
87
|
-
child.sessions = self.sessions
|
103
|
+
child.app_url = app_url
|
104
|
+
child.redis_pool = redis_pool
|
88
105
|
end
|
89
106
|
|
90
107
|
def settings
|
91
108
|
self.class.settings
|
92
109
|
end
|
93
110
|
|
94
|
-
def
|
95
|
-
middlewares
|
111
|
+
def middlewares
|
112
|
+
@middlewares ||= self.class.middlewares
|
96
113
|
end
|
97
114
|
|
98
|
-
def
|
99
|
-
|
115
|
+
def use(*args, &block)
|
116
|
+
middlewares << [args, block]
|
100
117
|
end
|
101
118
|
|
102
119
|
def call(env)
|
120
|
+
env[:csp_nonce] = SecureRandom.base64(16)
|
103
121
|
app.call(env)
|
104
122
|
end
|
105
123
|
|
@@ -113,81 +131,80 @@ module Sidekiq
|
|
113
131
|
end
|
114
132
|
|
115
133
|
def enable(*opts)
|
116
|
-
opts.each {|key| set(key, true) }
|
134
|
+
opts.each { |key| set(key, true) }
|
117
135
|
end
|
118
136
|
|
119
137
|
def disable(*opts)
|
120
|
-
opts.each {|key| set(key, false) }
|
138
|
+
opts.each { |key| set(key, false) }
|
121
139
|
end
|
122
140
|
|
123
141
|
def set(attribute, value)
|
124
142
|
send(:"#{attribute}=", value)
|
125
143
|
end
|
126
144
|
|
127
|
-
#
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
145
|
+
# Register a class as a Sidekiq Web UI extension. The class should
|
146
|
+
# provide one or more tabs which map to an index route. Options:
|
147
|
+
#
|
148
|
+
# @param extension [Class] Class which contains the HTTP actions, required
|
149
|
+
# @param name [String] the name of the extension, used to namespace assets
|
150
|
+
# @param tab [String | Array] labels(s) of the UI tabs
|
151
|
+
# @param index [String | Array] index route(s) for each tab
|
152
|
+
# @param root_dir [String] directory location to find assets, locales and views, typically `web/` within the gemfile
|
153
|
+
# @param asset_paths [Array] one or more directories under {root}/assets/{name} to be publicly served, e.g. ["js", "css", "img"]
|
154
|
+
# @param cache_for [Integer] amount of time to cache assets, default one day
|
155
|
+
#
|
156
|
+
# TODO name, tab and index will be mandatory in 8.0
|
157
|
+
#
|
158
|
+
# Web extensions will have a root `web/` directory with `locales/`, `assets/`
|
159
|
+
# and `views/` subdirectories.
|
160
|
+
def self.register(extension, name: nil, tab: nil, index: nil, root_dir: nil, cache_for: 86400, asset_paths: nil)
|
161
|
+
tab = Array(tab)
|
162
|
+
index = Array(index)
|
163
|
+
tab.zip(index).each do |tab, index|
|
164
|
+
tabs[tab] = index
|
165
|
+
end
|
166
|
+
if root_dir
|
167
|
+
locdir = File.join(root_dir, "locales")
|
168
|
+
locales << locdir if File.directory?(locdir)
|
169
|
+
|
170
|
+
if asset_paths && name
|
171
|
+
# if you have {root}/assets/{name}/js/scripts.js
|
172
|
+
# and {root}/assets/{name}/css/styles.css
|
173
|
+
# you would pass in:
|
174
|
+
# asset_paths: ["js", "css"]
|
175
|
+
# See script_tag and style_tag in web/helpers.rb
|
176
|
+
assdir = File.join(root_dir, "assets")
|
177
|
+
assurls = Array(asset_paths).map { |x| "/#{name}/#{x}" }
|
178
|
+
assetprops = {
|
179
|
+
urls: assurls,
|
180
|
+
root: assdir,
|
181
|
+
cascade: true
|
182
|
+
}
|
183
|
+
assetprops[:header_rules] = [[:all, {Rack::CACHE_CONTROL => "private, max-age=#{cache_for.to_i}"}]] if cache_for
|
184
|
+
middlewares << [[Rack::Static, assetprops], nil]
|
185
|
+
end
|
136
186
|
end
|
137
187
|
|
138
|
-
|
139
|
-
end
|
140
|
-
|
141
|
-
def self.register(extension)
|
188
|
+
yield self if block_given?
|
142
189
|
extension.registered(WebApplication)
|
143
190
|
end
|
144
191
|
|
145
192
|
private
|
146
193
|
|
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
194
|
def build
|
177
|
-
build_sessions
|
178
|
-
|
179
|
-
middlewares = self.middlewares
|
180
195
|
klass = self.class
|
196
|
+
m = middlewares
|
181
197
|
|
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) }
|
198
|
+
rules = []
|
199
|
+
rules = [[:all, {Rack::CACHE_CONTROL => "private, max-age=86400"}]] unless ENV["SIDEKIQ_WEB_TESTING"]
|
190
200
|
|
201
|
+
::Rack::Builder.new do
|
202
|
+
use Rack::Static, urls: ["/stylesheets", "/images", "/javascripts"],
|
203
|
+
root: ASSETS,
|
204
|
+
cascade: true,
|
205
|
+
header_rules: rules
|
206
|
+
m.each { |middleware, block| use(*middleware, &block) }
|
207
|
+
use Sidekiq::Web::CsrfProtection unless $TESTING
|
191
208
|
run WebApplication.new(klass)
|
192
209
|
end
|
193
210
|
end
|
@@ -196,18 +213,9 @@ module Sidekiq
|
|
196
213
|
Sidekiq::WebApplication.helpers WebHelpers
|
197
214
|
Sidekiq::WebApplication.helpers Sidekiq::Paginator
|
198
215
|
|
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)
|
216
|
+
Sidekiq::WebAction.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
217
|
+
def _render
|
218
|
+
#{ERB.new(File.read(Web::LAYOUT)).src}
|
211
219
|
end
|
212
|
-
|
220
|
+
RUBY
|
213
221
|
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,148 @@
|
|
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
|
197
105
|
end
|
198
106
|
|
199
|
-
#
|
107
|
+
# Creates a Sidekiq::Config instance that is more tuned for embedding
|
108
|
+
# within an arbitrary Ruby process. Notably it reduces concurrency by
|
109
|
+
# default so there is less contention for CPU time with other threads.
|
200
110
|
#
|
201
|
-
# Sidekiq.
|
202
|
-
# config.
|
111
|
+
# inst = Sidekiq.configure_embed do |config|
|
112
|
+
# config.queues = %w[critical default low]
|
203
113
|
# end
|
114
|
+
# inst.run
|
115
|
+
# sleep 10
|
116
|
+
# inst.stop
|
204
117
|
#
|
205
|
-
#
|
206
|
-
|
207
|
-
|
118
|
+
# NB: it is really easy to overload a Ruby process with threads due to the GIL.
|
119
|
+
# I do not recommend setting concurrency higher than 2-3.
|
120
|
+
#
|
121
|
+
# NB: Sidekiq only supports one instance in memory. You will get undefined behavior
|
122
|
+
# if you try to embed Sidekiq twice in the same process.
|
123
|
+
def self.configure_embed(&block)
|
124
|
+
raise "Sidekiq global configuration is frozen, you must create all embedded instances BEFORE calling `run`" if @frozen
|
125
|
+
|
126
|
+
require "sidekiq/embedded"
|
127
|
+
cfg = default_configuration
|
128
|
+
cfg.concurrency = 2
|
129
|
+
@config_blocks&.each { |block| block.call(cfg) }
|
130
|
+
yield cfg
|
131
|
+
|
132
|
+
Sidekiq::Embedded.new(cfg)
|
208
133
|
end
|
209
134
|
|
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
|
135
|
+
def self.configure_client
|
136
|
+
yield default_configuration unless server?
|
222
137
|
end
|
223
138
|
|
224
|
-
# We are shutting down Sidekiq but what about
|
139
|
+
# We are shutting down Sidekiq but what about threads that
|
225
140
|
# are working on some long job? This error is
|
226
|
-
# raised in
|
141
|
+
# raised in jobs that have not finished within the hard
|
227
142
|
# timeout limit. This is needed to rollback db transactions,
|
228
143
|
# otherwise Ruby's Thread#kill will commit. See #377.
|
229
|
-
# DO NOT RESCUE THIS ERROR IN YOUR
|
144
|
+
# DO NOT RESCUE THIS ERROR IN YOUR JOBS
|
230
145
|
class Shutdown < Interrupt; end
|
231
|
-
|
232
146
|
end
|
233
147
|
|
234
|
-
require
|
235
|
-
require 'sidekiq/extensions/action_mailer'
|
236
|
-
require 'sidekiq/extensions/active_record'
|
237
|
-
require 'sidekiq/rails' if defined?(::Rails::Engine)
|
148
|
+
require "sidekiq/rails" if defined?(::Rails::Engine)
|