sidekiq 8.0.1 → 8.0.3

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: b0775f0003b32ada04699c457af4644880f18381cff189168ca7cde5790ced21
4
- data.tar.gz: c7824fe9533b2d733cbd8f65d80cbd1bfd3216bb45ca44f158f9ab344164ad10
3
+ metadata.gz: 5862bbba5b859c1983788b6aeb49193fad724a1186426084c1e42747cb226ba2
4
+ data.tar.gz: 11fbaba14b814b87d09d809173ca59f9477c119f9ab6d556e4a9baa8e4e83d63
5
5
  SHA512:
6
- metadata.gz: ece6582faad9d3139cf7eb8e113f73ed94c983c59578d51e64caaeee52d48071b7d93f6af76942bf28735744f8047efa8d98dd571132ac3636b8509a54e36337
7
- data.tar.gz: a5d0cea61952c74b6ab862dbb3843b8c728ea9b341c43915c8c9c5d889665641fedd5e82382b783cd02be44e90451522e523b5418ce21523f475494383574101
6
+ metadata.gz: 67d640ff21778c036ba15db434bafe0582a61e1b462d1bee2502fa7a9b8978208b4099c46d8ad6bd6214f198558de8985deeb11b6e7d99f1e603b15f087f0215
7
+ data.tar.gz: 4becc4ea36c062f52667fea91d4f49b5bfb759fe43f75ef6427c1aeacdc36764408f442cafccc3595585cf13ef2ff71da98212d7db0fcb89ff198ace0cd19caa
data/Changes.md CHANGED
@@ -2,6 +2,19 @@
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
+ HEAD
6
+ ----------
7
+
8
+ - Configure Vernier output directory [#6674]
9
+ - Rework Rails integration [#6669]
10
+ - Implement flash messages for the Web UI [#6675]
11
+
12
+ 8.0.2
13
+ ----------
14
+
15
+ - Add `on(:exit)` event to run code right before the Sidekiq process exits [#6637]
16
+ - Metrics page crashes with Rack 3.1+ [#6646]
17
+
5
18
  8.0.1
6
19
  ----------
7
20
 
@@ -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
data/lib/sidekiq/api.rb CHANGED
@@ -1166,8 +1166,8 @@ module Sidekiq
1166
1166
  # works.each do |process_id, thread_id, work|
1167
1167
  # # process_id is a unique identifier per Sidekiq process
1168
1168
  # # thread_id is a unique identifier per thread
1169
- # # work is a Hash which looks like:
1170
- # # { 'queue' => name, 'run_at' => timestamp, 'payload' => job_hash }
1169
+ # # work is a `Sidekiq::Work` instance that has the following accessor methods.
1170
+ # # [work.queue, work.run_at, work.payload]
1171
1171
  # # run_at is an epoch Integer.
1172
1172
  # end
1173
1173
  #
@@ -27,6 +27,7 @@ module Sidekiq
27
27
  startup: [],
28
28
  quiet: [],
29
29
  shutdown: [],
30
+ exit: [],
30
31
  # triggers when we fire the first heartbeat on startup OR repairing a network partition
31
32
  heartbeat: [],
32
33
  # triggers on EVERY heartbeat call, every 10 seconds
@@ -258,7 +259,7 @@ module Sidekiq
258
259
  end
259
260
 
260
261
  # Register a block to run at a point in the Sidekiq lifecycle.
261
- # :startup, :quiet or :shutdown are valid events.
262
+ # :startup, :quiet, :shutdown, or :exit are valid events.
262
263
  #
263
264
  # Sidekiq.configure_server do |config|
264
265
  # config.on(:shutdown) do
@@ -43,7 +43,7 @@ module Sidekiq
43
43
  # fire startup and start multithreading.
44
44
  info = config.redis_info
45
45
  ver = Gem::Version.new(info["redis_version"])
46
- raise "You are connecting to Redis #{ver}, Sidekiq requires Redis 6.2.0 or greater" if ver < Gem::Version.new("6.2.0")
46
+ raise "You are connected to Redis #{ver}, Sidekiq requires Redis 7.0.0 or greater" if ver < Gem::Version.new("7.0.0")
47
47
 
48
48
  maxmemory_policy = info["maxmemory_policy"]
49
49
  if maxmemory_policy != "noeviction"
@@ -68,6 +68,7 @@ module Sidekiq
68
68
  stoppers.each(&:join)
69
69
 
70
70
  clear_heartbeat
71
+ fire_event(:exit, reverse: true)
71
72
  end
72
73
 
73
74
  def stopping?
@@ -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.1"
4
+ VERSION = "8.0.3"
5
5
  MAJOR = 8
6
6
 
7
7
  def self.gem_version
@@ -30,16 +30,16 @@ module Sidekiq
30
30
 
31
31
  # external redirect
32
32
  def redirect_to(url)
33
- throw :halt, [302, {"Location" => url}, []]
33
+ throw :halt, [302, {"location" => url}, []]
34
34
  end
35
35
 
36
36
  def header(key, value)
37
- env["response_headers"][key] = value
37
+ env["response_headers"][key] = value.to_s
38
38
  end
39
39
 
40
40
  # internal redirect
41
41
  def redirect(location)
42
- throw :halt, [302, {"Location" => "#{request.base_url}#{location}"}, []]
42
+ throw :halt, [302, {"location" => "#{request.base_url}#{location}"}, []]
43
43
  end
44
44
 
45
45
  def reload_page
@@ -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}")
@@ -43,9 +43,9 @@ module Sidekiq
43
43
 
44
44
  head "/" do
45
45
  # HEAD / is the cheapest heartbeat possible,
46
- # it hits Redis to ensure connectivity and returns
47
- # the size of the default queue
48
- Sidekiq.redis { |c| c.llen("queue:default") }.to_s
46
+ # it hits Redis to ensure connectivity
47
+ _ = Sidekiq.redis { |c| c.llen("queue:default") }
48
+ ""
49
49
  end
50
50
 
51
51
  get "/" do
@@ -240,8 +240,6 @@ module Sidekiq
240
240
  end
241
241
 
242
242
  post "/retries" do
243
- route_params("mike")
244
- url_params(:mike)
245
243
  redirect(request.path) unless url_params("key")
246
244
 
247
245
  url_params("key").each do |key|
data/lib/sidekiq.rb CHANGED
@@ -146,4 +146,4 @@ module Sidekiq
146
146
  class Shutdown < Interrupt; end
147
147
  end
148
148
 
149
- require "sidekiq/rails" if defined?(::Rails::Engine)
149
+ require "sidekiq/rails"
@@ -748,3 +748,10 @@ body > footer .nav {
748
748
  .w-50 {
749
749
  width: 50%;
750
750
  }
751
+
752
+ .flash {
753
+ width: 100%;
754
+ text-align: center;
755
+ padding: 20px;
756
+ background: var(--color-success);
757
+ }
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
@@ -2,15 +2,14 @@
2
2
  <html dir="<%= text_direction %>" lang="<%= locale %>">
3
3
  <head>
4
4
  <title><%= environment_title_prefix %><%= Sidekiq::NAME %></title>
5
- <meta charset="utf-8" />
6
- <meta name="viewport" content="width=device-width,initial-scale=1.0" />
7
-
8
- <link href="<%= root_path %>stylesheets/style.css" media="screen" rel="stylesheet" type="text/css" nonce="<%= csp_nonce %>" />
9
-
10
- <link rel="apple-touch-icon" href="<%= root_path %>images/apple-touch-icon.png">
11
- <link rel="shortcut icon" type="image/ico" href="<%= root_path %>images/favicon.ico" />
5
+ <meta charset="utf-8"/>
6
+ <meta name="viewport" content="width=device-width,initial-scale=1.0"/>
7
+ <meta name="color-scheme" content="light dark"/>
8
+ <link href="<%= root_path %>stylesheets/style.css" media="screen" rel="stylesheet" type="text/css" nonce="<%= csp_nonce %>"/>
9
+ <link rel="apple-touch-icon" href="<%= root_path %>images/apple-touch-icon.png"/>
10
+ <link rel="shortcut icon" type="image/ico" href="<%= root_path %>images/favicon.ico"/>
12
11
  <script type="text/javascript" src="<%= root_path %>javascripts/application.js" nonce="<%= csp_nonce %>"></script>
13
- <meta name="google" content="notranslate" />
12
+ <meta name="google" content="notranslate"/>
14
13
  <%= display_custom_head %>
15
14
  </head>
16
15
  <body class="admin" data-locale="<%= locale %>">
@@ -18,6 +17,7 @@
18
17
  <main id="page">
19
18
  <div class="container">
20
19
  <%= erb :_summary %>
20
+ <% if flash? %><p class="flash"><%= get_flash %></p><% end %>
21
21
  <%= yield %>
22
22
  </div>
23
23
  </main>
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.1
4
+ version: 8.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Perham
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-03-06 00:00:00.000000000 Z
10
+ date: 2025-04-24 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: redis-client