sidekiq 7.3.9 → 8.1.7
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 +4 -4
- data/Changes.md +225 -0
- data/README.md +34 -14
- data/bin/kiq +17 -0
- data/bin/lint-herb +13 -0
- data/bin/sidekiqload +12 -10
- data/bin/webload +69 -0
- data/lib/active_job/queue_adapters/sidekiq_adapter.rb +107 -58
- data/lib/generators/sidekiq/job_generator.rb +15 -3
- data/lib/generators/sidekiq/templates/job.rb.erb +1 -1
- data/lib/sidekiq/api.rb +310 -83
- data/lib/sidekiq/capsule.rb +10 -7
- data/lib/sidekiq/cli.rb +31 -24
- data/lib/sidekiq/client.rb +36 -18
- data/lib/sidekiq/component.rb +45 -3
- data/lib/sidekiq/config.rb +35 -30
- data/lib/sidekiq/embedded.rb +2 -1
- data/lib/sidekiq/fetch.rb +1 -0
- data/lib/sidekiq/iterable_job.rb +1 -0
- data/lib/sidekiq/job/iterable.rb +46 -18
- data/lib/sidekiq/job.rb +18 -3
- data/lib/sidekiq/job_logger.rb +8 -6
- data/lib/sidekiq/job_retry.rb +45 -18
- data/lib/sidekiq/job_util.rb +5 -1
- data/lib/sidekiq/launcher.rb +22 -12
- data/lib/sidekiq/loader.rb +57 -0
- data/lib/sidekiq/logger.rb +25 -69
- data/lib/sidekiq/manager.rb +2 -2
- data/lib/sidekiq/metrics/query.rb +77 -46
- data/lib/sidekiq/metrics/shared.rb +8 -5
- data/lib/sidekiq/metrics/tracking.rb +12 -7
- data/lib/sidekiq/middleware/current_attributes.rb +11 -19
- data/lib/sidekiq/middleware/i18n.rb +2 -0
- data/lib/sidekiq/monitor.rb +4 -8
- data/lib/sidekiq/paginator.rb +18 -2
- data/lib/sidekiq/processor.rb +26 -18
- data/lib/sidekiq/profiler.rb +73 -0
- data/lib/sidekiq/rails.rb +46 -67
- data/lib/sidekiq/redis_client_adapter.rb +6 -3
- data/lib/sidekiq/redis_connection.rb +16 -5
- data/lib/sidekiq/ring_buffer.rb +1 -0
- data/lib/sidekiq/scheduled.rb +6 -7
- data/lib/sidekiq/test_api.rb +331 -0
- data/lib/sidekiq/testing/inline.rb +2 -30
- data/lib/sidekiq/testing.rb +2 -333
- data/lib/sidekiq/transaction_aware_client.rb +13 -5
- data/lib/sidekiq/tui/controls.rb +53 -0
- data/lib/sidekiq/tui/filtering.rb +53 -0
- data/lib/sidekiq/tui/tabs/base_tab.rb +230 -0
- data/lib/sidekiq/tui/tabs/busy.rb +104 -0
- data/lib/sidekiq/tui/tabs/dead.rb +14 -0
- data/lib/sidekiq/tui/tabs/home.rb +115 -0
- data/lib/sidekiq/tui/tabs/metrics.rb +114 -0
- data/lib/sidekiq/tui/tabs/queues.rb +83 -0
- data/lib/sidekiq/tui/tabs/retries.rb +14 -0
- data/lib/sidekiq/tui/tabs/scheduled.rb +14 -0
- data/lib/sidekiq/tui/tabs/set_tab.rb +91 -0
- data/lib/sidekiq/tui/tabs.rb +15 -0
- data/lib/sidekiq/tui.rb +390 -0
- data/lib/sidekiq/version.rb +2 -2
- data/lib/sidekiq/web/action.rb +146 -83
- data/lib/sidekiq/web/application.rb +372 -328
- data/lib/sidekiq/web/config.rb +117 -0
- data/lib/sidekiq/web/helpers.rb +102 -44
- data/lib/sidekiq/web/router.rb +61 -77
- data/lib/sidekiq/web.rb +65 -151
- data/lib/sidekiq.rb +13 -1
- data/sidekiq.gemspec +9 -8
- data/web/assets/images/logo.png +0 -0
- data/web/assets/images/status.png +0 -0
- data/web/assets/javascripts/application.js +43 -27
- data/web/assets/javascripts/base-charts.js +30 -16
- data/web/assets/javascripts/chartjs-adapter-date-fns.min.js +7 -0
- data/web/assets/javascripts/dashboard.js +1 -1
- data/web/assets/javascripts/metrics.js +16 -34
- data/web/assets/stylesheets/style.css +776 -0
- data/web/locales/ar.yml +3 -1
- data/web/locales/cs.yml +2 -0
- data/web/locales/da.yml +2 -0
- data/web/locales/de.yml +2 -0
- data/web/locales/el.yml +2 -0
- data/web/locales/en.yml +8 -0
- data/web/locales/es.yml +25 -2
- data/web/locales/fa.yml +3 -1
- data/web/locales/fr.yml +3 -1
- data/web/locales/gd.yml +13 -1
- data/web/locales/he.yml +3 -1
- data/web/locales/hi.yml +36 -0
- data/web/locales/it.yml +9 -0
- data/web/locales/ja.yml +2 -0
- data/web/locales/ko.yml +2 -0
- data/web/locales/lt.yml +2 -0
- data/web/locales/nb.yml +2 -0
- data/web/locales/nl.yml +2 -0
- data/web/locales/pl.yml +2 -0
- data/web/locales/{pt-br.yml → pt-BR.yml} +3 -1
- data/web/locales/pt.yml +2 -0
- data/web/locales/ru.yml +2 -0
- data/web/locales/sv.yml +2 -0
- data/web/locales/ta.yml +83 -47
- data/web/locales/tr.yml +2 -0
- data/web/locales/uk.yml +7 -5
- data/web/locales/ur.yml +3 -1
- data/web/locales/vi.yml +2 -0
- data/web/locales/{zh-cn.yml → zh-CN.yml} +86 -73
- data/web/locales/{zh-tw.yml → zh-TW.yml} +3 -1
- data/web/views/_footer.html.erb +32 -0
- data/web/views/_job_info.html.erb +115 -0
- data/web/views/_metrics_period_select.html.erb +15 -0
- data/web/views/_nav.html.erb +45 -0
- data/web/views/_paging.html.erb +26 -0
- data/web/views/_poll_link.html.erb +4 -0
- data/web/views/{_summary.erb → _summary.html.erb} +16 -16
- data/web/views/busy.html.erb +155 -0
- data/web/views/dashboard.html.erb +104 -0
- data/web/views/dead.html.erb +38 -0
- data/web/views/filtering.html.erb +6 -0
- data/web/views/layout.html.erb +26 -0
- data/web/views/metrics.html.erb +85 -0
- data/web/views/metrics_for_job.html.erb +58 -0
- data/web/views/morgue.html.erb +69 -0
- data/web/views/profiles.html.erb +43 -0
- data/web/views/queue.html.erb +57 -0
- data/web/views/queues.html.erb +46 -0
- data/web/views/retries.html.erb +77 -0
- data/web/views/retry.html.erb +39 -0
- data/web/views/scheduled.html.erb +64 -0
- data/web/views/{scheduled_job_info.erb → scheduled_job_info.html.erb} +3 -3
- metadata +65 -47
- data/lib/sidekiq/web/csrf_protection.rb +0 -183
- data/web/assets/stylesheets/application-dark.css +0 -147
- data/web/assets/stylesheets/application-rtl.css +0 -163
- data/web/assets/stylesheets/application.css +0 -759
- data/web/assets/stylesheets/bootstrap-rtl.min.css +0 -9
- data/web/assets/stylesheets/bootstrap.css +0 -5
- data/web/views/_footer.erb +0 -34
- data/web/views/_job_info.erb +0 -105
- data/web/views/_metrics_period_select.erb +0 -12
- data/web/views/_nav.erb +0 -52
- data/web/views/_paging.erb +0 -25
- data/web/views/_poll_link.erb +0 -4
- data/web/views/_status.erb +0 -4
- data/web/views/busy.erb +0 -148
- data/web/views/dashboard.erb +0 -108
- data/web/views/dead.erb +0 -34
- data/web/views/filtering.erb +0 -6
- data/web/views/layout.erb +0 -42
- data/web/views/metrics.erb +0 -90
- data/web/views/metrics_for_job.erb +0 -59
- data/web/views/morgue.erb +0 -74
- data/web/views/queue.erb +0 -55
- data/web/views/queues.erb +0 -44
- data/web/views/retries.erb +0 -79
- data/web/views/retry.erb +0 -34
- data/web/views/scheduled.erb +0 -56
data/lib/sidekiq/web.rb
CHANGED
|
@@ -2,27 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
require "erb"
|
|
4
4
|
require "securerandom"
|
|
5
|
-
|
|
6
|
-
require "sidekiq"
|
|
7
|
-
require "sidekiq/api"
|
|
8
|
-
require "sidekiq/paginator"
|
|
9
|
-
require "sidekiq/web/helpers"
|
|
10
|
-
|
|
11
|
-
require "sidekiq/web/router"
|
|
12
|
-
require "sidekiq/web/action"
|
|
13
|
-
require "sidekiq/web/application"
|
|
14
|
-
require "sidekiq/web/csrf_protection"
|
|
15
|
-
|
|
16
|
-
require "rack/content_length"
|
|
17
5
|
require "rack/builder"
|
|
18
6
|
require "rack/static"
|
|
7
|
+
require "sidekiq"
|
|
8
|
+
require "sidekiq/api"
|
|
9
|
+
require "sidekiq/web/config"
|
|
19
10
|
|
|
20
11
|
module Sidekiq
|
|
21
12
|
class Web
|
|
22
13
|
ROOT = File.expand_path("#{File.dirname(__FILE__)}/../../web")
|
|
23
14
|
VIEWS = "#{ROOT}/views"
|
|
24
15
|
LOCALES = ["#{ROOT}/locales"]
|
|
25
|
-
LAYOUT = "#{VIEWS}/layout.erb"
|
|
16
|
+
LAYOUT = "#{VIEWS}/layout.html.erb"
|
|
26
17
|
ASSETS = "#{ROOT}/assets"
|
|
27
18
|
|
|
28
19
|
DEFAULT_TABS = {
|
|
@@ -32,195 +23,118 @@ module Sidekiq
|
|
|
32
23
|
"Retries" => "retries",
|
|
33
24
|
"Scheduled" => "scheduled",
|
|
34
25
|
"Dead" => "morgue",
|
|
35
|
-
"Metrics" => "metrics"
|
|
26
|
+
"Metrics" => "metrics",
|
|
27
|
+
"Profiles" => "profiles"
|
|
36
28
|
}
|
|
37
29
|
|
|
38
|
-
|
|
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
|
|
30
|
+
@@config = Sidekiq::Web::Config.new
|
|
51
31
|
|
|
52
32
|
class << self
|
|
53
|
-
# Forward compatibility with 8.0
|
|
54
33
|
def configure
|
|
55
|
-
|
|
34
|
+
if block_given?
|
|
35
|
+
yield @@config
|
|
36
|
+
else
|
|
37
|
+
@@config
|
|
38
|
+
end
|
|
56
39
|
end
|
|
57
40
|
|
|
58
|
-
def
|
|
59
|
-
|
|
41
|
+
def app_url=(url)
|
|
42
|
+
@@config.app_url = url
|
|
60
43
|
end
|
|
61
44
|
|
|
62
|
-
def
|
|
63
|
-
|
|
45
|
+
def assets_path=(path)
|
|
46
|
+
@@config.assets_path = path
|
|
64
47
|
end
|
|
65
48
|
|
|
66
|
-
def
|
|
67
|
-
@custom_tabs ||= {}
|
|
68
|
-
end
|
|
69
|
-
alias_method :tabs, :custom_tabs
|
|
49
|
+
def assets_path = @@config.assets_path
|
|
70
50
|
|
|
71
|
-
def
|
|
72
|
-
@custom_job_info_rows ||= []
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def locales
|
|
76
|
-
@locales ||= LOCALES
|
|
77
|
-
end
|
|
51
|
+
def tabs = @@config.tabs
|
|
78
52
|
|
|
79
|
-
def
|
|
80
|
-
@views ||= VIEWS
|
|
81
|
-
end
|
|
53
|
+
def locales = @@config.locales
|
|
82
54
|
|
|
83
|
-
def
|
|
84
|
-
opts.each { |key| set(key, true) }
|
|
85
|
-
end
|
|
55
|
+
def views = @@config.views
|
|
86
56
|
|
|
87
|
-
def
|
|
88
|
-
opts.each { |key| set(key, false) }
|
|
89
|
-
end
|
|
57
|
+
def custom_job_info_rows = @@config.custom_job_info_rows
|
|
90
58
|
|
|
91
|
-
def
|
|
92
|
-
@
|
|
59
|
+
def redis_pool
|
|
60
|
+
@pool || Sidekiq.default_configuration.redis_pool
|
|
93
61
|
end
|
|
94
62
|
|
|
95
|
-
def
|
|
96
|
-
|
|
63
|
+
def redis_pool=(pool)
|
|
64
|
+
@pool = pool
|
|
97
65
|
end
|
|
98
66
|
|
|
99
|
-
def
|
|
100
|
-
send(:"#{attribute}=", value)
|
|
101
|
-
end
|
|
67
|
+
def middlewares = @@config.middlewares
|
|
102
68
|
|
|
103
|
-
|
|
104
|
-
attr_writer :locales, :views
|
|
105
|
-
end
|
|
69
|
+
def use(*args, &block) = @@config.middlewares << [args, block]
|
|
106
70
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
def settings
|
|
113
|
-
self.class.settings
|
|
71
|
+
def register(*args, **kw, &block)
|
|
72
|
+
Sidekiq.logger.warn { "`Sidekiq::Web.register` is deprecated, use `Sidekiq::Web.configure {|cfg| cfg.register(...) }`" }
|
|
73
|
+
@@config.register(*args, **kw, &block)
|
|
74
|
+
end
|
|
114
75
|
end
|
|
115
76
|
|
|
116
|
-
|
|
117
|
-
|
|
77
|
+
# Allow user to say
|
|
78
|
+
# run Sidekiq::Web
|
|
79
|
+
# rather than:
|
|
80
|
+
# run Sidekiq::Web.new
|
|
81
|
+
def self.call(env)
|
|
82
|
+
@inst ||= new
|
|
83
|
+
@inst.call(env)
|
|
118
84
|
end
|
|
119
85
|
|
|
120
|
-
|
|
121
|
-
|
|
86
|
+
# testing, internal use only
|
|
87
|
+
def self.reset!
|
|
88
|
+
@@config.reset!
|
|
89
|
+
@inst = nil
|
|
122
90
|
end
|
|
123
91
|
|
|
124
92
|
def call(env)
|
|
125
|
-
env[:
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
def self.call(env)
|
|
130
|
-
@app ||= new
|
|
131
|
-
@app.call(env)
|
|
93
|
+
env[:web_config] = Sidekiq::Web.configure
|
|
94
|
+
env[:csp_nonce] = SecureRandom.hex(8)
|
|
95
|
+
env[:redis_pool] = self.class.redis_pool
|
|
96
|
+
safe_request?(env) ? app.call(env) : deny(env)
|
|
132
97
|
end
|
|
133
98
|
|
|
134
99
|
def app
|
|
135
|
-
@app ||= build
|
|
100
|
+
@app ||= build(@@config)
|
|
136
101
|
end
|
|
137
102
|
|
|
138
|
-
def
|
|
139
|
-
|
|
103
|
+
def safe_methods?(env)
|
|
104
|
+
%w[GET HEAD OPTIONS TRACE].include? env["REQUEST_METHOD"]
|
|
140
105
|
end
|
|
141
106
|
|
|
142
|
-
def
|
|
143
|
-
|
|
107
|
+
def safe_request?(env)
|
|
108
|
+
return true if safe_methods?(env)
|
|
109
|
+
env["HTTP_SEC_FETCH_SITE"] == "same-origin"
|
|
144
110
|
end
|
|
145
111
|
|
|
146
|
-
def
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
yield self if block_given?
|
|
194
|
-
extension.registered(WebApplication)
|
|
112
|
+
def deny(env)
|
|
113
|
+
Sidekiq.logger.warn "attack prevented by #{self.class}"
|
|
114
|
+
[403, {Rack::CONTENT_TYPE => "text/plain"}, ["Forbidden"]]
|
|
195
115
|
end
|
|
196
116
|
|
|
197
117
|
private
|
|
198
118
|
|
|
199
|
-
def build
|
|
200
|
-
|
|
201
|
-
m = middlewares
|
|
119
|
+
def build(cfg)
|
|
120
|
+
cfg.freeze
|
|
121
|
+
m = cfg.middlewares
|
|
202
122
|
|
|
203
123
|
rules = []
|
|
204
|
-
rules = [[:all, {
|
|
124
|
+
rules = [[:all, {"cache-control" => "private, max-age=86400"}]] unless ENV["SIDEKIQ_WEB_TESTING"]
|
|
205
125
|
|
|
206
126
|
::Rack::Builder.new do
|
|
207
127
|
use Rack::Static, urls: ["/stylesheets", "/images", "/javascripts"],
|
|
208
|
-
root:
|
|
128
|
+
root: cfg.assets_path,
|
|
209
129
|
cascade: true,
|
|
210
130
|
header_rules: rules
|
|
211
131
|
m.each { |middleware, block| use(*middleware, &block) }
|
|
212
|
-
|
|
213
|
-
run WebApplication.new(klass)
|
|
132
|
+
run Sidekiq::Web::Application.new(self.class)
|
|
214
133
|
end
|
|
215
134
|
end
|
|
216
135
|
end
|
|
217
|
-
|
|
218
|
-
Sidekiq::WebApplication.helpers WebHelpers
|
|
219
|
-
Sidekiq::WebApplication.helpers Sidekiq::Paginator
|
|
220
|
-
|
|
221
|
-
Sidekiq::WebAction.class_eval <<-RUBY, Web::LAYOUT, -1 # standard:disable Style/EvalWithLocation
|
|
222
|
-
def _render
|
|
223
|
-
#{ERB.new(File.read(Web::LAYOUT)).src}
|
|
224
|
-
end
|
|
225
|
-
RUBY
|
|
226
136
|
end
|
|
137
|
+
|
|
138
|
+
require "sidekiq/web/router"
|
|
139
|
+
require "sidekiq/web/action"
|
|
140
|
+
require "sidekiq/web/application"
|
data/lib/sidekiq.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "sidekiq/version"
|
|
4
|
-
fail "Sidekiq #{Sidekiq::VERSION} does not support Ruby versions below 2.
|
|
4
|
+
fail "Sidekiq #{Sidekiq::VERSION} does not support Ruby versions below 3.2.0." if RUBY_PLATFORM != "java" && Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.2.0")
|
|
5
5
|
|
|
6
6
|
begin
|
|
7
7
|
require "sidekiq-ent/version"
|
|
@@ -29,6 +29,7 @@ end
|
|
|
29
29
|
|
|
30
30
|
require "sidekiq/config"
|
|
31
31
|
require "sidekiq/logger"
|
|
32
|
+
require "sidekiq/loader"
|
|
32
33
|
require "sidekiq/client"
|
|
33
34
|
require "sidekiq/transaction_aware_client"
|
|
34
35
|
require "sidekiq/job"
|
|
@@ -46,6 +47,13 @@ module Sidekiq
|
|
|
46
47
|
puts "Take a deep breath and count to ten..."
|
|
47
48
|
end
|
|
48
49
|
|
|
50
|
+
def self.testing!(mode = :fake, &block)
|
|
51
|
+
raise "Unknown testing mode: #{mode}" unless %i[fake disable inline].include?(mode)
|
|
52
|
+
|
|
53
|
+
require "sidekiq/test_api"
|
|
54
|
+
Sidekiq::Testing.__set_test_mode(mode, &block)
|
|
55
|
+
end
|
|
56
|
+
|
|
49
57
|
def self.server?
|
|
50
58
|
defined?(Sidekiq::CLI)
|
|
51
59
|
end
|
|
@@ -94,6 +102,10 @@ module Sidekiq
|
|
|
94
102
|
default_configuration.logger
|
|
95
103
|
end
|
|
96
104
|
|
|
105
|
+
def self.loader
|
|
106
|
+
@loader ||= Loader.new
|
|
107
|
+
end
|
|
108
|
+
|
|
97
109
|
def self.configure_server(&block)
|
|
98
110
|
(@config_blocks ||= []) << block
|
|
99
111
|
yield default_configuration if server?
|
data/sidekiq.gemspec
CHANGED
|
@@ -8,11 +8,11 @@ Gem::Specification.new do |gem|
|
|
|
8
8
|
gem.homepage = "https://sidekiq.org"
|
|
9
9
|
gem.license = "LGPL-3.0"
|
|
10
10
|
|
|
11
|
-
gem.executables = ["sidekiq", "sidekiqmon"]
|
|
11
|
+
gem.executables = ["sidekiq", "sidekiqmon", "kiq"]
|
|
12
12
|
gem.files = %w[sidekiq.gemspec README.md Changes.md LICENSE.txt] + `git ls-files | grep -E '^(bin|lib|web)'`.split("\n")
|
|
13
13
|
gem.name = "sidekiq"
|
|
14
14
|
gem.version = Sidekiq::VERSION
|
|
15
|
-
gem.required_ruby_version = ">= 2.
|
|
15
|
+
gem.required_ruby_version = ">= 3.2.0"
|
|
16
16
|
|
|
17
17
|
gem.metadata = {
|
|
18
18
|
"homepage_uri" => "https://sidekiq.org",
|
|
@@ -20,12 +20,13 @@ Gem::Specification.new do |gem|
|
|
|
20
20
|
"documentation_uri" => "https://github.com/sidekiq/sidekiq/wiki",
|
|
21
21
|
"changelog_uri" => "https://github.com/sidekiq/sidekiq/blob/main/Changes.md",
|
|
22
22
|
"source_code_uri" => "https://github.com/sidekiq/sidekiq",
|
|
23
|
-
"rubygems_mfa_required" => "true"
|
|
23
|
+
"rubygems_mfa_required" => "true",
|
|
24
|
+
"mailing_list_uri" => "https://www.rubyforum.org/tag/sidekiq"
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
gem.add_dependency "redis-client", ">= 0.
|
|
27
|
-
gem.add_dependency "connection_pool", ">=
|
|
28
|
-
gem.add_dependency "rack", ">=
|
|
29
|
-
gem.add_dependency "
|
|
30
|
-
gem.add_dependency "
|
|
27
|
+
gem.add_dependency "redis-client", ">= 0.29.0"
|
|
28
|
+
gem.add_dependency "connection_pool", ">= 3.0.0"
|
|
29
|
+
gem.add_dependency "rack", ">= 3.2.0"
|
|
30
|
+
gem.add_dependency "json", ">= 2.16.0"
|
|
31
|
+
gem.add_dependency "logger", ">= 1.7.0"
|
|
31
32
|
end
|
data/web/assets/images/logo.png
CHANGED
|
File without changes
|
|
File without changes
|
|
@@ -18,20 +18,12 @@ function addListeners() {
|
|
|
18
18
|
})
|
|
19
19
|
});
|
|
20
20
|
|
|
21
|
-
document.querySelectorAll("input[data-confirm]").forEach(node => {
|
|
22
|
-
node.addEventListener("click", event => {
|
|
23
|
-
if (!window.confirm(node.getAttribute("data-confirm"))) {
|
|
24
|
-
event.preventDefault();
|
|
25
|
-
event.stopPropagation();
|
|
26
|
-
}
|
|
27
|
-
})
|
|
28
|
-
})
|
|
29
|
-
|
|
30
21
|
document.querySelectorAll("[data-toggle]").forEach(node => {
|
|
31
22
|
node.addEventListener("click", addDataToggleListeners)
|
|
32
23
|
})
|
|
33
24
|
|
|
34
|
-
|
|
25
|
+
initializeBulkToggle();
|
|
26
|
+
addShiftClickListeners();
|
|
35
27
|
updateFuzzyTimes();
|
|
36
28
|
updateNumbers();
|
|
37
29
|
updateProgressBars();
|
|
@@ -67,13 +59,24 @@ function addPollingListeners(_event) {
|
|
|
67
59
|
|
|
68
60
|
function addDataToggleListeners(event) {
|
|
69
61
|
var source = event.target || event.srcElement;
|
|
70
|
-
var targName = source.
|
|
62
|
+
var targName = source.dataset.toggle;
|
|
71
63
|
var full = document.getElementById(targName);
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
64
|
+
full.classList.toggle("is-open");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function toggleBulkButtons() {
|
|
68
|
+
const checkboxes = document.querySelectorAll('.select-item-checkbox, .check-all-items');
|
|
69
|
+
const anyChecked = Array.from(checkboxes).some(cb => cb.checked);
|
|
70
|
+
const buttons = document.querySelectorAll('.bulk-action-buttons');
|
|
71
|
+
buttons.forEach(btn => {
|
|
72
|
+
btn.style.display = anyChecked ? 'none' : 'block';
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function initializeBulkToggle(){
|
|
77
|
+
document.querySelectorAll('.check-all-items, .select-item-checkbox').forEach(cb => {
|
|
78
|
+
cb.addEventListener('change', toggleBulkButtons);
|
|
79
|
+
});
|
|
77
80
|
}
|
|
78
81
|
|
|
79
82
|
function addShiftClickListeners() {
|
|
@@ -94,7 +97,7 @@ function addShiftClickListeners() {
|
|
|
94
97
|
}
|
|
95
98
|
|
|
96
99
|
function updateFuzzyTimes() {
|
|
97
|
-
var locale = document.body.
|
|
100
|
+
var locale = document.body.dataset.locale;
|
|
98
101
|
var parts = locale.split('-');
|
|
99
102
|
if (typeof parts[1] !== 'undefined') {
|
|
100
103
|
parts[1] = parts[1].toUpperCase();
|
|
@@ -109,7 +112,7 @@ function updateFuzzyTimes() {
|
|
|
109
112
|
function updateNumbers() {
|
|
110
113
|
document.querySelectorAll("[data-nwp]").forEach(node => {
|
|
111
114
|
let number = parseFloat(node.textContent);
|
|
112
|
-
let precision = parseInt(node.dataset
|
|
115
|
+
let precision = parseInt(node.dataset.nwp || 0);
|
|
113
116
|
if (typeof number === "number") {
|
|
114
117
|
let formatted = number.toLocaleString(undefined, {
|
|
115
118
|
minimumFractionDigits: precision,
|
|
@@ -130,11 +133,11 @@ function setLivePollFromUrl() {
|
|
|
130
133
|
|
|
131
134
|
function updateLivePollButton() {
|
|
132
135
|
if (localStorage.sidekiqLivePoll == "enabled") {
|
|
133
|
-
document.querySelectorAll('.live-poll-stop').forEach(box => { box.
|
|
134
|
-
document.querySelectorAll('.live-poll-start').forEach(box => { box.
|
|
136
|
+
document.querySelectorAll('.live-poll-stop').forEach(box => { box.classList.add("active") })
|
|
137
|
+
document.querySelectorAll('.live-poll-start').forEach(box => { box.classList.remove("active") })
|
|
135
138
|
} else {
|
|
136
|
-
document.querySelectorAll('.live-poll-start').forEach(box => { box.
|
|
137
|
-
document.querySelectorAll('.live-poll-stop').forEach(box => { box.
|
|
139
|
+
document.querySelectorAll('.live-poll-start').forEach(box => { box.classList.add("active") })
|
|
140
|
+
document.querySelectorAll('.live-poll-stop').forEach(box => { box.classList.remove("active") })
|
|
138
141
|
}
|
|
139
142
|
}
|
|
140
143
|
|
|
@@ -151,7 +154,7 @@ function livePollCallback() {
|
|
|
151
154
|
|
|
152
155
|
function checkResponse(resp) {
|
|
153
156
|
if (!resp.ok) {
|
|
154
|
-
throw
|
|
157
|
+
throw resp.error();
|
|
155
158
|
}
|
|
156
159
|
return resp
|
|
157
160
|
}
|
|
@@ -169,9 +172,6 @@ function replacePage(text) {
|
|
|
169
172
|
var page = doc.querySelector('#page')
|
|
170
173
|
document.querySelector("#page").replaceWith(page)
|
|
171
174
|
|
|
172
|
-
var header_status = doc.querySelector('.status')
|
|
173
|
-
document.querySelector('.status').replaceWith(header_status)
|
|
174
|
-
|
|
175
175
|
addListeners();
|
|
176
176
|
}
|
|
177
177
|
|
|
@@ -185,4 +185,20 @@ function updateLocale(event) {
|
|
|
185
185
|
|
|
186
186
|
function updateProgressBars() {
|
|
187
187
|
document.querySelectorAll('.progress-bar').forEach(bar => { bar.style.width = bar.dataset.width + "%"})
|
|
188
|
-
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function handleConfirmDialog (event) {
|
|
191
|
+
const target = event.target
|
|
192
|
+
|
|
193
|
+
if (target.localName !== "input" && target.localName !== "button" ) { return }
|
|
194
|
+
const confirmMessage = target.dataset.confirm
|
|
195
|
+
|
|
196
|
+
if (confirmMessage === undefined) { return }
|
|
197
|
+
|
|
198
|
+
if (!window.confirm(confirmMessage)) {
|
|
199
|
+
event.preventDefault()
|
|
200
|
+
event.stopPropagation()
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
document.addEventListener("click", handleConfirmDialog)
|
|
@@ -1,27 +1,35 @@
|
|
|
1
1
|
if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
|
2
2
|
Chart.defaults.borderColor = "#333";
|
|
3
3
|
Chart.defaults.color = "#aaa";
|
|
4
|
+
// Chart.defaults.borderColor = "oklch(22% 0.01 256)";
|
|
5
|
+
// Chart.defaults.color = "oklch(65% 0.01 256)";
|
|
4
6
|
}
|
|
5
7
|
|
|
6
8
|
class Colors {
|
|
7
9
|
constructor() {
|
|
8
10
|
this.assignments = {};
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
|
12
|
+
this.light = "65%";
|
|
13
|
+
this.chroma = "0.15";
|
|
14
|
+
} else {
|
|
15
|
+
this.light = "48%";
|
|
16
|
+
this.chroma = "0.2";
|
|
17
|
+
}
|
|
18
|
+
this.success = "oklch(" + this.light + " " + this.chroma + " 179)";
|
|
19
|
+
this.failure = "oklch(" + this.light + " " + this.chroma + " 29)";
|
|
20
|
+
this.fallback = "oklch(" + this.light + " 0.02 269)";
|
|
21
|
+
this.primary = "oklch(" + this.light + " " + this.chroma + " 269)";
|
|
13
22
|
this.available = [
|
|
14
|
-
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"#991b1b",
|
|
23
|
+
"oklch(" + this.light + " " + this.chroma + " 256)",
|
|
24
|
+
"oklch(" + this.light + " " + this.chroma + " 196)",
|
|
25
|
+
"oklch(" + this.light + " " + this.chroma + " 46)",
|
|
26
|
+
"oklch(" + this.light + " " + this.chroma + " 316)",
|
|
27
|
+
"oklch(" + this.light + " " + this.chroma + " 106)",
|
|
28
|
+
"oklch(" + this.light + " " + this.chroma + " 226)",
|
|
29
|
+
"oklch(" + this.light + " " + this.chroma + " 136)",
|
|
30
|
+
"oklch(" + this.light + " 0.02 269)",
|
|
31
|
+
"oklch(" + this.light + " " + this.chroma + " 286)",
|
|
32
|
+
"oklch(" + this.light + " " + this.chroma + " 16)",
|
|
25
33
|
];
|
|
26
34
|
}
|
|
27
35
|
|
|
@@ -90,12 +98,18 @@ class BaseChart {
|
|
|
90
98
|
};
|
|
91
99
|
|
|
92
100
|
if (this.options.marks) {
|
|
101
|
+
if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
|
102
|
+
this.Borderlight = "30%";
|
|
103
|
+
} else {
|
|
104
|
+
this.Borderlight = "65%";
|
|
105
|
+
}
|
|
106
|
+
|
|
93
107
|
this.options.marks.forEach(([bucket, label], i) => {
|
|
94
108
|
chartOptions.plugins.annotation.annotations[`deploy-${i}`] = {
|
|
95
109
|
type: "line",
|
|
96
110
|
xMin: bucket,
|
|
97
111
|
xMax: bucket,
|
|
98
|
-
borderColor: "
|
|
112
|
+
borderColor: "oklch(" + this.Borderlight + " 0.01 256)",
|
|
99
113
|
borderWidth: 2,
|
|
100
114
|
};
|
|
101
115
|
});
|