sidekiq 8.0.2 → 8.0.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a2128fafa84e48bfd4cad6155e9dcddaab93bc68152b28d6c27156cf84490cf9
4
- data.tar.gz: 346e2bff46bcae590efbdab4bf4c0942994a70fd4360cb395efffaac02e9ee02
3
+ metadata.gz: 70244790b6f984dfb4da9922e5971f3072479bce2f484ca3ab3982108906e6d0
4
+ data.tar.gz: 77b5d8e952603bebfe6e703b0f92df3cf4b78be6caf7e46fb46e5376c02c45c7
5
5
  SHA512:
6
- metadata.gz: 318665d5dd278811f1ce98923fac64fbc79d78f38bde1e54c92f975f4bce24a24ef43a7c15eda03fc54caa39f1bddd1e932aa98f866a6983d4d92cf2ec587a6d
7
- data.tar.gz: 16b597d7ff91c948bd4868c85386387a4f306f6dfce260d9141db485e9252845c38c2195ee6ec7b4490e94c950d66de43a4a429feaacf37c9b06d3be4ed9ed14
6
+ metadata.gz: 5c347f189e4ed255a1de061afa5c08bf73b3d77f83d853669e09c9b7e06f430958d1db4e3aa9a6ae3a9abad5802c3872f050ae43b2db014105633c45be4cfaa0
7
+ data.tar.gz: 0fca2e77cfd25ab7ccc6be20edeb8a0c09056c8bb0bde03de5ff415a5ca15f55668e1c662a2f91c1dfe8ed074ae5d106d95b1d3a04e32fa1d86606aa35c06645
data/Changes.md CHANGED
@@ -2,6 +2,24 @@
2
2
 
3
3
  [Sidekiq Changes](https://github.com/sidekiq/sidekiq/blob/main/Changes.md) | [Sidekiq Pro Changes](https://github.com/sidekiq/sidekiq/blob/main/Pro-Changes.md) | [Sidekiq Enterprise Changes](https://github.com/sidekiq/sidekiq/blob/main/Ent-Changes.md)
4
4
 
5
+ 8.0.4
6
+ ----------
7
+
8
+ - Adjust Rails integration for various edge cases [6713]
9
+ - Flush job iteration state when an error is raised [#6704]
10
+ - Update Accept-Language parsing in Web UI [#6721]
11
+ - Remove fixed-width in Web UI [#6686]
12
+ - Adjust CSRF middleware ordering [#6688]
13
+ - Support proxies when POSTing profiles to profiler.firefox.com [#6687]
14
+ - Dont swallow NoMethodErrors in CurrentAttributes [#6685]
15
+
16
+ 8.0.3
17
+ ----------
18
+
19
+ - Configure Vernier output directory [#6674]
20
+ - Rework Rails integration [#6669]
21
+ - Implement flash messages for the Web UI [#6675]
22
+
5
23
  8.0.2
6
24
  ----------
7
25
 
@@ -1,75 +1,111 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module ActiveJob
4
- module QueueAdapters
5
- # Explicitly remove the implementation existing in older Rails.
6
- remove_const(:SidekiqAdapter) if const_defined?(:SidekiqAdapter)
3
+ begin
4
+ gem "activejob", ">= 7.0"
5
+ require "active_job"
7
6
 
8
- # Sidekiq adapter for Active Job
9
- #
10
- # To use Sidekiq set the queue_adapter config to +:sidekiq+.
11
- #
12
- # Rails.application.config.active_job.queue_adapter = :sidekiq
13
- class SidekiqAdapter
14
- # Defines whether enqueuing should happen implicitly to after commit when called
15
- # from inside a transaction.
7
+ module Sidekiq
8
+ module ActiveJob
16
9
  # @api private
17
- def enqueue_after_transaction_commit?
18
- true
19
- end
10
+ class Wrapper
11
+ include Sidekiq::Job
20
12
 
21
- # @api private
22
- def enqueue(job)
23
- job.provider_job_id = Sidekiq::ActiveJob::Wrapper.set(
24
- wrapped: job.class,
25
- queue: job.queue_name
26
- ).perform_async(job.serialize)
13
+ def perform(job_data)
14
+ ::ActiveJob::Base.execute(job_data.merge("provider_job_id" => jid))
15
+ end
27
16
  end
17
+ end
18
+ end
28
19
 
29
- # @api private
30
- def enqueue_at(job, timestamp)
31
- job.provider_job_id = Sidekiq::ActiveJob::Wrapper.set(
32
- wrapped: job.class,
33
- queue: job.queue_name
34
- ).perform_at(timestamp, job.serialize)
35
- end
20
+ unless ActiveJob::Base.respond_to?(:sidekiq_options)
21
+ # By including the Options module, we allow AJs to directly control sidekiq features
22
+ # via the *sidekiq_options* class method and, for instance, not use AJ's retry system.
23
+ # AJ retries don't show up in the Sidekiq UI Retries tab, don't save any error data, can't be
24
+ # manually retried, don't automatically die, etc.
25
+ #
26
+ # class SomeJob < ActiveJob::Base
27
+ # queue_as :default
28
+ # sidekiq_options retry: 3, backtrace: 10
29
+ # def perform
30
+ # end
31
+ # end
32
+ ActiveJob::Base.include Sidekiq::Job::Options
33
+ end
36
34
 
37
- # @api private
38
- def enqueue_all(jobs)
39
- enqueued_count = 0
40
- jobs.group_by(&:class).each do |job_class, same_class_jobs|
41
- same_class_jobs.group_by(&:queue_name).each do |queue, same_class_and_queue_jobs|
42
- immediate_jobs, scheduled_jobs = same_class_and_queue_jobs.partition { |job| job.scheduled_at.nil? }
35
+ # Patch the ActiveJob module
36
+ module ActiveJob
37
+ module QueueAdapters
38
+ # Explicitly remove the implementation existing in older Rails.
39
+ remove_const(:SidekiqAdapter) if const_defined?(:SidekiqAdapter)
43
40
 
44
- if immediate_jobs.any?
45
- jids = Sidekiq::Client.push_bulk(
46
- "class" => Sidekiq::ActiveJob::Wrapper,
47
- "wrapped" => job_class,
48
- "queue" => queue,
49
- "args" => immediate_jobs.map { |job| [job.serialize] }
50
- )
51
- enqueued_count += jids.compact.size
52
- end
41
+ # Sidekiq adapter for Active Job
42
+ #
43
+ # To use Sidekiq set the queue_adapter config to +:sidekiq+.
44
+ #
45
+ # Rails.application.config.active_job.queue_adapter = :sidekiq
46
+ class SidekiqAdapter
47
+ # Defines whether enqueuing should happen implicitly to after commit when called
48
+ # from inside a transaction.
49
+ # @api private
50
+ def enqueue_after_transaction_commit?
51
+ true
52
+ end
53
+
54
+ # @api private
55
+ def enqueue(job)
56
+ job.provider_job_id = Sidekiq::ActiveJob::Wrapper.set(
57
+ wrapped: job.class,
58
+ queue: job.queue_name
59
+ ).perform_async(job.serialize)
60
+ end
61
+
62
+ # @api private
63
+ def enqueue_at(job, timestamp)
64
+ job.provider_job_id = Sidekiq::ActiveJob::Wrapper.set(
65
+ wrapped: job.class,
66
+ queue: job.queue_name
67
+ ).perform_at(timestamp, job.serialize)
68
+ end
53
69
 
54
- if scheduled_jobs.any?
55
- jids = Sidekiq::Client.push_bulk(
56
- "class" => Sidekiq::ActiveJob::Wrapper,
57
- "wrapped" => job_class,
58
- "queue" => queue,
59
- "args" => scheduled_jobs.map { |job| [job.serialize] },
60
- "at" => scheduled_jobs.map { |job| job.scheduled_at&.to_f }
61
- )
62
- enqueued_count += jids.compact.size
70
+ # @api private
71
+ def enqueue_all(jobs)
72
+ enqueued_count = 0
73
+ jobs.group_by(&:class).each do |job_class, same_class_jobs|
74
+ same_class_jobs.group_by(&:queue_name).each do |queue, same_class_and_queue_jobs|
75
+ immediate_jobs, scheduled_jobs = same_class_and_queue_jobs.partition { |job| job.scheduled_at.nil? }
76
+
77
+ if immediate_jobs.any?
78
+ jids = Sidekiq::Client.push_bulk(
79
+ "class" => Sidekiq::ActiveJob::Wrapper,
80
+ "wrapped" => job_class,
81
+ "queue" => queue,
82
+ "args" => immediate_jobs.map { |job| [job.serialize] }
83
+ )
84
+ enqueued_count += jids.compact.size
85
+ end
86
+
87
+ if scheduled_jobs.any?
88
+ jids = Sidekiq::Client.push_bulk(
89
+ "class" => Sidekiq::ActiveJob::Wrapper,
90
+ "wrapped" => job_class,
91
+ "queue" => queue,
92
+ "args" => scheduled_jobs.map { |job| [job.serialize] },
93
+ "at" => scheduled_jobs.map { |job| job.scheduled_at&.to_f }
94
+ )
95
+ enqueued_count += jids.compact.size
96
+ end
63
97
  end
64
98
  end
99
+ enqueued_count
65
100
  end
66
- enqueued_count
67
- end
68
101
 
69
- # Defines a class alias for backwards compatibility with enqueued Active Job jobs.
70
- # @api private
71
- class JobWrapper < Sidekiq::ActiveJob::Wrapper
102
+ # Defines a class alias for backwards compatibility with enqueued Active Job jobs.
103
+ # @api private
104
+ class JobWrapper < Sidekiq::ActiveJob::Wrapper
105
+ end
72
106
  end
73
107
  end
74
108
  end
109
+ rescue Gem::LoadError
110
+ # ActiveJob not available or version requirement not met
75
111
  end
@@ -221,6 +221,9 @@ module Sidekiq
221
221
  verify_iteration_time(time_limit, object) do
222
222
  around_iteration do
223
223
  each_iteration(object, *arguments)
224
+ rescue Exception
225
+ flush_state
226
+ raise
224
227
  end
225
228
  end
226
229
  end
@@ -71,11 +71,14 @@ module Sidekiq
71
71
  retried = false
72
72
 
73
73
  begin
74
+ set_succeeded = false
74
75
  klass.set(attrs) do
76
+ set_succeeded = true
75
77
  wrap(klass_attrs, &block)
76
78
  end
77
79
  rescue NoMethodError
78
- raise if retried
80
+ # Don't retry if the no method error didn't come from current attributes
81
+ raise if retried || set_succeeded
79
82
 
80
83
  # It is possible that the `CurrentAttributes` definition
81
84
  # was changed before the job started processing.
@@ -13,6 +13,7 @@ module Sidekiq
13
13
  include Sidekiq::Component
14
14
  def initialize(config)
15
15
  @config = config
16
+ @vernier_output_dir = ENV.fetch("VERNIER_OUTPUT_DIR") { Dir.tmpdir }
16
17
  end
17
18
 
18
19
  def call(job, &block)
@@ -22,7 +23,6 @@ module Sidekiq
22
23
  type = job["class"]
23
24
  jid = job["jid"]
24
25
  started_at = Time.now
25
- options = DEFAULT_OPTIONS.merge((job["profiler_options"] || {}).transform_keys!(&:to_sym))
26
26
 
27
27
  rundata = {
28
28
  started_at: started_at.to_i,
@@ -30,13 +30,17 @@ module Sidekiq
30
30
  type: type,
31
31
  jid: jid,
32
32
  # .gz extension tells Vernier to compress the data
33
- filename: "#{token}-#{type}-#{jid}-#{started_at.strftime("%Y%m%d-%H%M%S")}.json.gz"
33
+ filename: File.join(
34
+ @vernier_output_dir,
35
+ "#{token}-#{type}-#{jid}-#{started_at.strftime("%Y%m%d-%H%M%S")}.json.gz"
36
+ )
34
37
  }
38
+ profiler_options = profiler_options(job, rundata)
35
39
 
36
40
  require "vernier"
37
41
  begin
38
42
  a = Time.now
39
- rc = Vernier.profile(**options.merge(out: rundata[:filename]), &block)
43
+ rc = Vernier.profile(**profiler_options, &block)
40
44
  b = Time.now
41
45
 
42
46
  # Failed jobs will raise an exception on previous line and skip this
@@ -55,5 +59,14 @@ module Sidekiq
55
59
  FileUtils.rm_f(rundata[:filename])
56
60
  end
57
61
  end
62
+
63
+ private
64
+
65
+ def profiler_options(job, rundata)
66
+ profiler_options = (job["profiler_options"] || {}).transform_keys(&:to_sym)
67
+ profiler_options[:mode] = profiler_options[:mode].to_sym if profiler_options[:mode]
68
+
69
+ DEFAULT_OPTIONS.merge(profiler_options, {out: rundata[:filename]})
70
+ end
58
71
  end
59
72
  end
data/lib/sidekiq/rails.rb CHANGED
@@ -1,84 +1,62 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "sidekiq/job"
4
- require "rails"
4
+ require_relative "../active_job/queue_adapters/sidekiq_adapter"
5
5
 
6
6
  module Sidekiq
7
- module ActiveJob
8
- # @api private
9
- class Wrapper
10
- include Sidekiq::Job
11
-
12
- def perform(job_data)
13
- ::ActiveJob::Base.execute(job_data.merge("provider_job_id" => jid))
14
- end
15
- end
16
- end
17
-
18
- class Rails < ::Rails::Engine
19
- class Reloader
20
- def initialize(app = ::Rails.application)
21
- @app = app
22
- end
23
-
24
- def call
25
- params = (::Rails::VERSION::STRING >= "7.1") ? {source: "job.sidekiq"} : {}
26
- @app.reloader.wrap(**params) do
27
- yield
7
+ begin
8
+ gem "railties", ">= 7.0"
9
+ require "rails"
10
+
11
+ class Rails < ::Rails::Engine
12
+ class Reloader
13
+ def initialize(app = ::Rails.application)
14
+ @app = app
28
15
  end
29
- end
30
16
 
31
- def inspect
32
- "#<Sidekiq::Rails::Reloader @app=#{@app.class.name}>"
33
- end
17
+ def call
18
+ params = (::Rails::VERSION::STRING >= "7.1") ? {source: "job.sidekiq"} : {}
19
+ @app.reloader.wrap(**params) do
20
+ yield
21
+ end
22
+ end
34
23
 
35
- def to_hash
36
- {app: @app.class.name}
37
- end
38
- end
24
+ def inspect
25
+ "#<Sidekiq::Rails::Reloader @app=#{@app.class.name}>"
26
+ end
39
27
 
40
- # By including the Options module, we allow AJs to directly control sidekiq features
41
- # via the *sidekiq_options* class method and, for instance, not use AJ's retry system.
42
- # AJ retries don't show up in the Sidekiq UI Retries tab, don't save any error data, can't be
43
- # manually retried, don't automatically die, etc.
44
- #
45
- # class SomeJob < ActiveJob::Base
46
- # queue_as :default
47
- # sidekiq_options retry: 3, backtrace: 10
48
- # def perform
49
- # end
50
- # end
51
- initializer "sidekiq.active_job_integration" do
52
- ActiveSupport.on_load(:active_job) do
53
- require_relative "../active_job/queue_adapters/sidekiq_adapter"
54
- include ::Sidekiq::Job::Options unless respond_to?(:sidekiq_options)
28
+ def to_hash
29
+ {app: @app.class.name}
30
+ end
55
31
  end
56
- end
57
32
 
58
- initializer "sidekiq.backtrace_cleaner" do
59
- Sidekiq.configure_server do |config|
60
- config[:backtrace_cleaner] = ->(backtrace) { ::Rails.backtrace_cleaner.clean(backtrace) }
33
+ initializer "sidekiq.backtrace_cleaner" do
34
+ Sidekiq.configure_server do |config|
35
+ config[:backtrace_cleaner] = ->(backtrace) { ::Rails.backtrace_cleaner.clean(backtrace) }
36
+ end
61
37
  end
62
- end
63
-
64
- # This hook happens after all initializers are run, just before returning
65
- # from config/environment.rb back to sidekiq/cli.rb.
66
- #
67
- # None of this matters on the client-side, only within the Sidekiq process itself.
68
- config.after_initialize do
69
- Sidekiq.configure_server do |config|
70
- config[:reloader] = Sidekiq::Rails::Reloader.new
71
38
 
72
- # This is the integration code necessary so that if a job uses `Rails.logger.info "Hello"`,
73
- # it will appear in the Sidekiq console with all of the job context.
74
- unless ::Rails.logger == config.logger || ::ActiveSupport::Logger.logger_outputs_to?(::Rails.logger, $stdout)
75
- if ::Rails.logger.respond_to?(:broadcast_to)
76
- ::Rails.logger.broadcast_to(config.logger)
77
- else
78
- ::Rails.logger.extend(::ActiveSupport::Logger.broadcast(config.logger))
39
+ # This hook happens after all initializers are run, just before returning
40
+ # from config/environment.rb back to sidekiq/cli.rb.
41
+ #
42
+ # None of this matters on the client-side, only within the Sidekiq process itself.
43
+ config.after_initialize do
44
+ Sidekiq.configure_server do |config|
45
+ config[:reloader] = Sidekiq::Rails::Reloader.new
46
+
47
+ # This is the integration code necessary so that if a job uses `Rails.logger.info "Hello"`,
48
+ # it will appear in the Sidekiq console with all of the job context.
49
+ unless ::Rails.logger == config.logger || ::ActiveSupport::Logger.logger_outputs_to?(::Rails.logger, $stdout)
50
+ if ::Rails.logger.respond_to?(:broadcast_to)
51
+ ::Rails.logger.broadcast_to(config.logger)
52
+ else
53
+ ::Rails.logger.extend(::ActiveSupport::Logger.broadcast(config.logger))
54
+ end
79
55
  end
80
56
  end
81
57
  end
82
58
  end
59
+ rescue Gem::LoadError
60
+ # Rails not available or version requirement not met
83
61
  end
84
62
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sidekiq
4
- VERSION = "8.0.2"
4
+ VERSION = "8.0.4"
5
5
  MAJOR = 8
6
6
 
7
7
  def self.gem_version
@@ -70,6 +70,25 @@ module Sidekiq
70
70
  env["rack.session"]
71
71
  end
72
72
 
73
+ def logger
74
+ Sidekiq.logger
75
+ end
76
+
77
+ # flash { "Some message to show on redirect" }
78
+ def flash
79
+ msg = yield
80
+ logger.info msg
81
+ session[:flash] = msg
82
+ end
83
+
84
+ def flash?
85
+ session&.[](:flash)
86
+ end
87
+
88
+ def get_flash
89
+ @flash ||= session.delete(:flash)
90
+ end
91
+
73
92
  def erb(content, options = {})
74
93
  if content.is_a? Symbol
75
94
  unless respond_to?(:"_erb_#{content}")
@@ -325,6 +325,8 @@ module Sidekiq
325
325
  get "/stats" do
326
326
  sidekiq_stats = Sidekiq::Stats.new
327
327
  redis_stats = redis_info.slice(*REDIS_KEYS)
328
+ redis_stats["store_name"] = store_name
329
+ redis_stats["store_version"] = store_version
328
330
  json(
329
331
  sidekiq: {
330
332
  processed: sidekiq_stats.processed,
@@ -360,10 +362,16 @@ module Sidekiq
360
362
  unless sid
361
363
  require "net/http"
362
364
  data = Sidekiq.redis { |c| c.hget(key, "data") }
363
- resp = Net::HTTP.post(URI(store),
364
- data,
365
- {"Accept" => "application/vnd.firefox-profiler+json;version=1.0",
366
- "User-Agent" => "Sidekiq #{Sidekiq::VERSION} job profiler"})
365
+
366
+ store_uri = URI(store)
367
+ http = Net::HTTP.new(store_uri.host, store_uri.port)
368
+ http.use_ssl = store_uri.scheme == "https"
369
+ request = Net::HTTP::Post.new(store_uri.request_uri)
370
+ request.body = data
371
+ request["Accept"] = "application/vnd.firefox-profiler+json;version=1.0"
372
+ request["User-Agent"] = "Sidekiq #{Sidekiq::VERSION} job profiler"
373
+
374
+ resp = http.request(request)
367
375
  # https://raw.githubusercontent.com/firefox-devtools/profiler-server/master/tools/decode_jwt_payload.py
368
376
  rawjson = resp.body.split(".")[1].unpack1("m")
369
377
  sid = Sidekiq.load_json(rawjson)["profileToken"]
@@ -57,7 +57,7 @@ module Sidekiq
57
57
  @locales = LOCALES
58
58
  @views = VIEWS
59
59
  @tabs = DEFAULT_TABS.dup
60
- @middlewares = [Sidekiq::Web::CsrfProtection]
60
+ @middlewares = []
61
61
  @custom_job_info_rows = []
62
62
  end
63
63
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "uri"
4
4
  require "yaml"
5
- require "cgi"
5
+ require "cgi/escape"
6
6
 
7
7
  module Sidekiq
8
8
  # These methods are available to pages within the Web UI and UI extensions.
@@ -165,7 +165,10 @@ module Sidekiq
165
165
  text_direction == "rtl"
166
166
  end
167
167
 
168
- # See https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
168
+ # See https://www.rfc-editor.org/rfc/rfc9110.html#section-12.5.4
169
+ # Returns an array of language tags ordered by their quality value
170
+ #
171
+ # Inspiration taken from https://github.com/iain/http_accept_language/blob/master/lib/http_accept_language/parser.rb
169
172
  def user_preferred_languages
170
173
  languages = env["HTTP_ACCEPT_LANGUAGE"]
171
174
  languages.to_s.gsub(/\s+/, "").split(",").map { |language|
@@ -180,28 +183,30 @@ module Sidekiq
180
183
 
181
184
  # Given an Accept-Language header like "fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4,ru;q=0.2"
182
185
  # this method will try to best match the available locales to the user's preferred languages.
183
- #
184
- # Inspiration taken from https://github.com/iain/http_accept_language/blob/master/lib/http_accept_language/parser.rb
185
186
  def locale
186
187
  # session[:locale] is set via the locale selector from the footer
187
188
  @locale ||= if (l = session&.fetch(:locale, nil)) && available_locales.include?(l)
188
189
  l
189
190
  else
191
+ matched_locale = nil
192
+ # Attempt to find a case-insensitive exact match first
193
+ user_preferred_languages.each do |preferred|
194
+ # We only care about the language and primary subtag
195
+ # "en-GB-oxendict" becomes "en-GB"
196
+ language_tag = preferred.split("-")[0..1].join("-")
197
+ matched_locale = available_locales.find { |available_locale| available_locale.casecmp?(language_tag) }
198
+ break if matched_locale
199
+ end
190
200
 
191
- # exactly match with preferred like "pt-BR, zh-CN, zh-TW..." first
192
- matched_locale = user_preferred_languages.find { |preferred|
193
- available_locales.include?(preferred) if preferred.length == 5
194
- }
195
-
196
- matched_locale ||= user_preferred_languages.map { |preferred|
197
- preferred_language = preferred.split("-", 2).first
198
-
199
- lang_group = available_locales.select { |available|
200
- preferred_language == available.split("-", 2).first
201
- }
201
+ return matched_locale if matched_locale
202
202
 
203
- lang_group.find { |lang| lang == preferred } || lang_group.min_by(&:length)
204
- }.compact.first
203
+ # Find the first base language match
204
+ # "en-US,es-MX;q=0.9" matches "en"
205
+ user_preferred_languages.each do |preferred|
206
+ base_language = preferred.split("-", 2).first
207
+ matched_locale = available_locales.find { |available_locale| available_locale.casecmp?(base_language) }
208
+ break if matched_locale
209
+ end
205
210
 
206
211
  matched_locale || "en"
207
212
  end
@@ -372,7 +377,7 @@ module Sidekiq
372
377
  elsif rss_kb < 10_000_000
373
378
  "#{number_with_delimiter((rss_kb / 1024.0).to_i)} MB"
374
379
  else
375
- "#{number_with_delimiter((rss_kb / (1024.0 * 1024.0)), precision: 1)} GB"
380
+ "#{number_with_delimiter(rss_kb / (1024.0 * 1024.0), precision: 1)} GB"
376
381
  end
377
382
  end
378
383
 
data/lib/sidekiq/web.rb CHANGED
@@ -109,6 +109,7 @@ module Sidekiq
109
109
  cascade: true,
110
110
  header_rules: rules
111
111
  m.each { |middleware, block| use(*middleware, &block) }
112
+ use CsrfProtection unless $TESTING # rubocop:disable Style/GlobalVars
112
113
  run Sidekiq::Web::Application.new(self.class)
113
114
  end
114
115
  end
@@ -11,7 +11,7 @@ var updateStatsSummary = function(data) {
11
11
  }
12
12
 
13
13
  var updateRedisStats = function(data) {
14
- document.getElementById('redis_version').innerText = data.redis_version;
14
+ document.getElementById('redis_version').innerText = data.store_version;
15
15
  document.getElementById('uptime_in_days').innerText = data.uptime_in_days;
16
16
  document.getElementById('connected_clients').innerText = data.connected_clients;
17
17
  document.getElementById('used_memory_human').innerText = data.used_memory_human;
@@ -69,7 +69,7 @@ body {
69
69
 
70
70
  .container {
71
71
  margin: 0 auto;
72
- max-width: 1440px;
72
+ /* max-width: 1440px; */
73
73
  padding: var(--space-2x);
74
74
  }
75
75
 
@@ -90,6 +90,7 @@ code {
90
90
  font-family: var(--font-mono);
91
91
  font-size: var(--font-size-small);
92
92
  padding: var(--space-1-2);
93
+ word-wrap: anywhere;
93
94
  }
94
95
 
95
96
  time { color: var(--color-text-light); }
@@ -437,7 +438,10 @@ article .count {
437
438
  }
438
439
 
439
440
  /* table */
440
- .table_container { overflow-x: auto; }
441
+ .table_container {
442
+ overflow-x: auto;
443
+ margin-bottom: var(--space-2x);
444
+ }
441
445
 
442
446
  .table_container + form,
443
447
  .table_container + input,
@@ -748,3 +752,10 @@ body > footer .nav {
748
752
  .w-50 {
749
753
  width: 50%;
750
754
  }
755
+
756
+ .flash {
757
+ width: 100%;
758
+ text-align: center;
759
+ padding: 20px;
760
+ background: var(--color-success);
761
+ }
data/web/locales/it.yml CHANGED
@@ -35,6 +35,7 @@ it:
35
35
  Jobs: Lavori
36
36
  Kill: Uccidere
37
37
  KillAll: Uccidere tutti
38
+ Language: Lingua
38
39
  LastRetry: Ultimo tentativo
39
40
  Latency: Latenza
40
41
  LivePoll: Live poll
@@ -54,6 +55,7 @@ it:
54
55
  PeakMemoryUsage: Memoria utilizzata (max.)
55
56
  Plugins: Plugins
56
57
  PollingInterval: Intervallo di polling
58
+ PollingIntervalMilliseconds: Intervallo di polling in millisecondi
57
59
  Process: Processo
58
60
  Processed: Processato
59
61
  Processes: Processi
@@ -99,3 +101,8 @@ it:
99
101
  NoJobMetricsFound: Metriche recenti di lavoro non trovate
100
102
  Filter: Filtro
101
103
  AnyJobContent: Qualsiasi contenuto di lavoro
104
+ Profiles: Profili
105
+ Data: Dati
106
+ View: Vista
107
+ Token: Token
108
+ ElapsedTime: Tempo Trascorso
data/web/views/layout.erb CHANGED
@@ -17,6 +17,7 @@
17
17
  <main id="page">
18
18
  <div class="container">
19
19
  <%= erb :_summary %>
20
+ <% if flash? %><p class="flash"><%= get_flash %></p><% end %>
20
21
  <%= yield %>
21
22
  </div>
22
23
  </main>
@@ -57,4 +57,4 @@
57
57
  <% else %>
58
58
  <div class="alert alert-success"><%= t('NoScheduledFound') %></div>
59
59
  <% end %>
60
- </div>
60
+ </section>
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.0.2
4
+ version: 8.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Perham
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-04-01 00:00:00.000000000 Z
10
+ date: 2025-05-28 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: redis-client