diff --git a/.gitlab/ci/vendored-gems.gitlab-ci.yml b/.gitlab/ci/vendored-gems.gitlab-ci.yml
index 9f6c028a7e8a03df84275b4b6226e62124519f8f..c0e0f91f0f5a420175f7e1960c81723e78a9fb5c 100644
--- a/.gitlab/ci/vendored-gems.gitlab-ci.yml
+++ b/.gitlab/ci/vendored-gems.gitlab-ci.yml
@@ -53,5 +53,5 @@ include:
       gem_path_prefix: "vendor/gems/"
   - local: .gitlab/ci/templates/gem.gitlab-ci.yml
     inputs:
-      gem_name: "sidekiq-7.1.6"
+      gem_name: "sidekiq-7.2.4"
       gem_path_prefix: "vendor/gems/"
diff --git a/Gemfile b/Gemfile
index bbd4996705099d5523e833b5dbddaf22e72abe02..a18aba328ca3d95185498dcaf097c14c3d9bc2f6 100644
--- a/Gemfile
+++ b/Gemfile
@@ -279,7 +279,7 @@ end
 gem 'state_machines-activerecord', '~> 0.8.0' # rubocop:todo Gemfile/MissingFeatureCategory
 
 # Background jobs
-gem 'sidekiq', path: 'vendor/gems/sidekiq-7.1.6', require: 'sidekiq', feature_category: :scalability
+gem 'sidekiq', path: 'vendor/gems/sidekiq-7.2.4', require: 'sidekiq', feature_category: :scalability
 gem 'sidekiq-cron', '~> 1.12.0', feature_category: :scalability
 gem 'gitlab-sidekiq-fetcher',
   path: 'vendor/gems/sidekiq-reliable-fetch',
diff --git a/Gemfile.lock b/Gemfile.lock
index a35dcdb033cd3ce4bcc918080fab30ff501ba16d..4c9c966aeb6f3eb33f3065883bcf82a0c8590c54 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -194,13 +194,13 @@ PATH
       omniauth (~> 2.0)
 
 PATH
-  remote: vendor/gems/sidekiq-7.1.6
+  remote: vendor/gems/sidekiq-7.2.4
   specs:
-    sidekiq (7.1.6)
+    sidekiq (7.2.4)
       concurrent-ruby (< 2)
       connection_pool (>= 2.3.0)
       rack (>= 2.2.4)
-      redis-client (>= 0.14.0)
+      redis-client (>= 0.19.0)
 
 PATH
   remote: vendor/gems/sidekiq-reliable-fetch
diff --git a/Gemfile.next.lock b/Gemfile.next.lock
index 899fa89dfda9f5a21fe61ed7367af91a0a9e804d..27c56721d799cbc0d10f86ff3c74de333f234ae7 100644
--- a/Gemfile.next.lock
+++ b/Gemfile.next.lock
@@ -194,13 +194,13 @@ PATH
       omniauth (~> 2.0)
 
 PATH
-  remote: vendor/gems/sidekiq-7.1.6
+  remote: vendor/gems/sidekiq-7.2.4
   specs:
-    sidekiq (7.1.6)
+    sidekiq (7.2.4)
       concurrent-ruby (< 2)
       connection_pool (>= 2.3.0)
       rack (>= 2.2.4)
-      redis-client (>= 0.14.0)
+      redis-client (>= 0.19.0)
 
 PATH
   remote: vendor/gems/sidekiq-reliable-fetch
diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb
index 343b033989de2022f153bd00a637d8e5a0744e47..c156d54e41ff148e9f305a8354419201b417b93f 100644
--- a/config/initializers/sidekiq.rb
+++ b/config/initializers/sidekiq.rb
@@ -38,7 +38,7 @@ def load_cron_jobs!
 Sidekiq.strict_args!(strict_args_mode)
 
 # Perform version check before configuring server with the custome scheduled job enqueue class
-unless Gem::Version.new(Sidekiq::VERSION) == Gem::Version.new('7.1.6')
+unless Gem::Version.new(Sidekiq::VERSION) == Gem::Version.new('7.2.4')
   raise 'New version of Sidekiq detected, please either update the version for this check ' \
         'and update Gitlab::SidekiqSharding::ScheduledEnq is compatible.'
 end
diff --git a/lib/gitlab/patch/sidekiq_cron_poller.rb b/lib/gitlab/patch/sidekiq_cron_poller.rb
index 8c2d1181611b8969b70a090fff8a0cf3d73b7823..a40ebae4789a67d58187a63f7b7ff871f6dadfb1 100644
--- a/lib/gitlab/patch/sidekiq_cron_poller.rb
+++ b/lib/gitlab/patch/sidekiq_cron_poller.rb
@@ -7,7 +7,7 @@
 require 'sidekiq/version'
 require 'sidekiq/cron/version'
 
-if Gem::Version.new(Sidekiq::VERSION) != Gem::Version.new('7.1.6')
+if Gem::Version.new(Sidekiq::VERSION) != Gem::Version.new('7.2.4')
   raise 'New version of sidekiq detected, please remove or update this patch'
 end
 
diff --git a/lib/gitlab/patch/sidekiq_job_setter.rb b/lib/gitlab/patch/sidekiq_job_setter.rb
index b5f80c9884f1b54e01242da461c3e88f367fff33..c16218c7cded4950172b26141deec3ab2878e826 100644
--- a/lib/gitlab/patch/sidekiq_job_setter.rb
+++ b/lib/gitlab/patch/sidekiq_job_setter.rb
@@ -1,6 +1,6 @@
 # frozen_string_literal: true
 
-if Gem::Version.new(Sidekiq::VERSION) != Gem::Version.new('7.1.6')
+if Gem::Version.new(Sidekiq::VERSION) != Gem::Version.new('7.2.4')
   raise 'New version of sidekiq detected, please remove or update this patch'
 end
 
diff --git a/lib/gitlab/sidekiq_sharding/validator.rb b/lib/gitlab/sidekiq_sharding/validator.rb
index 38c1960d6311a63198c7fd2f815447ee0cf6540e..894fd3173b869e96b9bd14803774531514078e02 100644
--- a/lib/gitlab/sidekiq_sharding/validator.rb
+++ b/lib/gitlab/sidekiq_sharding/validator.rb
@@ -45,6 +45,14 @@ def enabled
         end
       end
 
+      Sidekiq::RedisClientAdapter::CompatMethods::USED_COMMANDS.each do |name|
+        define_method(name) do |*args, **kwargs|
+          validate! if Thread.current[:validate_sidekiq_shard_awareness]
+
+          super(*args, **kwargs)
+        end
+      end
+
       # This is used to patch the Sidekiq::RedisClientAdapter to validate all Redis commands are routed
       # rubocop:disable Style/MissingRespondToMissing -- already defined in the module we are patching
       def method_missing(*args, &block)
diff --git a/vendor/gems/sidekiq-7.1.6/Gemfile.lock b/vendor/gems/sidekiq-7.1.6/Gemfile.lock
deleted file mode 100644
index 6e994afa16a673eddc0b0fe6bab00b20b5cd8b03..0000000000000000000000000000000000000000
--- a/vendor/gems/sidekiq-7.1.6/Gemfile.lock
+++ /dev/null
@@ -1,195 +0,0 @@
-PATH
-  remote: .
-  specs:
-    sidekiq (7.1.6)
-      concurrent-ruby (< 2)
-      connection_pool (>= 2.3.0)
-      rack (>= 2.2.4)
-      redis-client (>= 0.14.0)
-
-GEM
-  remote: https://rubygems.org/
-  specs:
-    actionmailer (7.0.8)
-      actionpack (= 7.0.8)
-      actionview (= 7.0.8)
-      activejob (= 7.0.8)
-      activesupport (= 7.0.8)
-      mail (~> 2.5, >= 2.5.4)
-      net-imap
-      net-pop
-      net-smtp
-      rails-dom-testing (~> 2.0)
-    actionpack (7.0.8)
-      actionview (= 7.0.8)
-      activesupport (= 7.0.8)
-      rack (~> 2.0, >= 2.2.4)
-      rack-test (>= 0.6.3)
-      rails-dom-testing (~> 2.0)
-      rails-html-sanitizer (~> 1.0, >= 1.2.0)
-    actionview (7.0.8)
-      activesupport (= 7.0.8)
-      builder (~> 3.1)
-      erubi (~> 1.4)
-      rails-dom-testing (~> 2.0)
-      rails-html-sanitizer (~> 1.1, >= 1.2.0)
-    activejob (7.0.8)
-      activesupport (= 7.0.8)
-      globalid (>= 0.3.6)
-    activemodel (7.0.8)
-      activesupport (= 7.0.8)
-    activerecord (7.0.8)
-      activemodel (= 7.0.8)
-      activesupport (= 7.0.8)
-    activesupport (7.0.8)
-      concurrent-ruby (~> 1.0, >= 1.0.2)
-      i18n (>= 1.6, < 2)
-      minitest (>= 5.1)
-      tzinfo (~> 2.0)
-    after_commit_everywhere (1.3.1)
-      activerecord (>= 4.2)
-      activesupport
-    ast (2.4.2)
-    builder (3.2.4)
-    concurrent-ruby (1.2.3)
-    connection_pool (2.4.1)
-    crass (1.0.6)
-    date (3.3.4)
-    docile (1.4.0)
-    erubi (1.12.0)
-    globalid (1.2.1)
-      activesupport (>= 6.1)
-    i18n (1.14.1)
-      concurrent-ruby (~> 1.0)
-    json (2.7.1)
-    language_server-protocol (3.17.0.3)
-    lint_roller (1.1.0)
-    loofah (2.22.0)
-      crass (~> 1.0.2)
-      nokogiri (>= 1.12.0)
-    mail (2.8.1)
-      mini_mime (>= 0.1.1)
-      net-imap
-      net-pop
-      net-smtp
-    maxitest (5.4.0)
-      minitest (>= 5.14.0, < 5.21.0)
-    method_source (1.0.0)
-    mini_mime (1.1.5)
-    mini_portile2 (2.8.5)
-    minitest (5.20.0)
-    net-imap (0.4.9.1)
-      date
-      net-protocol
-    net-pop (0.1.2)
-      net-protocol
-    net-protocol (0.2.2)
-      timeout
-    net-smtp (0.4.0.1)
-      net-protocol
-    nokogiri (1.16.0)
-      mini_portile2 (~> 2.8.2)
-      racc (~> 1.4)
-    nokogiri (1.16.0-arm64-darwin)
-      racc (~> 1.4)
-    parallel (1.24.0)
-    parser (3.3.0.5)
-      ast (~> 2.4.1)
-      racc
-    racc (1.7.3)
-    rack (2.2.8)
-    rack-test (2.1.0)
-      rack (>= 1.3)
-    rails-dom-testing (2.2.0)
-      activesupport (>= 5.0.0)
-      minitest
-      nokogiri (>= 1.6)
-    rails-html-sanitizer (1.6.0)
-      loofah (~> 2.21)
-      nokogiri (~> 1.14)
-    railties (7.0.8)
-      actionpack (= 7.0.8)
-      activesupport (= 7.0.8)
-      method_source
-      rake (>= 12.2)
-      thor (~> 1.0)
-      zeitwerk (~> 2.5)
-    rainbow (3.1.1)
-    rake (13.1.0)
-    redis-client (0.19.1)
-      connection_pool
-    regexp_parser (2.9.0)
-    rexml (3.2.6)
-    rubocop (1.59.0)
-      json (~> 2.3)
-      language_server-protocol (>= 3.17.0)
-      parallel (~> 1.10)
-      parser (>= 3.2.2.4)
-      rainbow (>= 2.2.2, < 4.0)
-      regexp_parser (>= 1.8, < 3.0)
-      rexml (>= 3.2.5, < 4.0)
-      rubocop-ast (>= 1.30.0, < 2.0)
-      ruby-progressbar (~> 1.7)
-      unicode-display_width (>= 2.4.0, < 3.0)
-    rubocop-ast (1.30.0)
-      parser (>= 3.2.1.0)
-    rubocop-performance (1.20.2)
-      rubocop (>= 1.48.1, < 2.0)
-      rubocop-ast (>= 1.30.0, < 2.0)
-    ruby-prof (1.7.0)
-    ruby-progressbar (1.13.0)
-    simplecov (0.22.0)
-      docile (~> 1.1)
-      simplecov-html (~> 0.11)
-      simplecov_json_formatter (~> 0.1)
-    simplecov-html (0.12.3)
-    simplecov_json_formatter (0.1.4)
-    sqlite3 (1.7.1)
-      mini_portile2 (~> 2.8.0)
-    sqlite3 (1.7.1-arm64-darwin)
-    standard (1.33.0)
-      language_server-protocol (~> 3.17.0.2)
-      lint_roller (~> 1.0)
-      rubocop (~> 1.59.0)
-      standard-custom (~> 1.0.0)
-      standard-performance (~> 1.3)
-    standard-custom (1.0.2)
-      lint_roller (~> 1.0)
-      rubocop (~> 1.50)
-    standard-performance (1.3.1)
-      lint_roller (~> 1.1)
-      rubocop-performance (~> 1.20.2)
-    thor (1.3.0)
-    timeout (0.4.1)
-    toxiproxy (2.0.2)
-    tzinfo (2.0.6)
-      concurrent-ruby (~> 1.0)
-    unicode-display_width (2.5.0)
-    yard (0.9.34)
-    zeitwerk (2.6.12)
-
-PLATFORMS
-  arm64-darwin-23
-  ruby
-
-DEPENDENCIES
-  actionmailer (~> 7.0.4)
-  actionpack (~> 7.0.4)
-  activejob (~> 7.0.4)
-  activerecord (~> 7.0.4)
-  activerecord-jdbcsqlite3-adapter
-  after_commit_everywhere
-  maxitest
-  railties (~> 7.0.4)
-  rake
-  redis-client
-  ruby-prof
-  sidekiq!
-  simplecov
-  sqlite3
-  standard
-  toxiproxy
-  yard
-
-BUNDLED WITH
-   2.5.5
diff --git a/vendor/gems/sidekiq-7.1.6/test/exception_handler_test.rb b/vendor/gems/sidekiq-7.1.6/test/exception_handler_test.rb
deleted file mode 100644
index 9468f4b02d25a62b9ded447a7f75f8cc950a9ccb..0000000000000000000000000000000000000000
--- a/vendor/gems/sidekiq-7.1.6/test/exception_handler_test.rb
+++ /dev/null
@@ -1,99 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "helper"
-require "sidekiq/component"
-require "sidekiq/rails"
-require "stringio"
-require "logger"
-
-ExceptionHandlerTestException = Class.new(StandardError)
-TEST_EXCEPTION = ExceptionHandlerTestException.new("Something didn't work!")
-
-class Thing
-  include Sidekiq::Component
-  attr_reader :config
-
-  def initialize(config)
-    @config = config
-  end
-
-  def invoke_exception(args)
-    raise TEST_EXCEPTION
-  rescue ExceptionHandlerTestException => e
-    handle_exception(e, args)
-  end
-end
-
-class SErrorHandler
-  def call(x, y)
-    raise SystemStackError
-  end
-end
-
-describe Sidekiq::Component do
-  describe "with mock logger" do
-    before do
-      @config = reset!
-    end
-
-    it "logs the exception to Sidekiq.logger" do
-      @config[:reloader] = Sidekiq::Rails::Reloader.new
-      output = capture_logging(@config) do
-        Thing.new(@config).invoke_exception(a: 1)
-      end
-      assert_match(/"a":1/, output, "didn't include the context")
-      assert_match(/Something didn't work!/, output, "didn't include the exception message")
-      assert_match(/test\/exception_handler_test.rb/, output, "didn't include the backtrace")
-    end
-
-    it "handles exceptions in classy error handlers" do
-      test_handler = SErrorHandler.new
-      @config[:error_handlers] << test_handler
-      output = capture_logging(@config) do
-        Thing.new(@config).invoke_exception(a: 1)
-      end
-
-      assert_match(/DEPRECATION/, output, "didn't include the deprecation warning")
-      assert_match(/SystemStackError/, output, "didn't include the exception")
-      assert_match(/Something didn't work!/, output, "didn't include the exception message")
-      assert_match(/!!! ERROR HANDLER THREW AN ERROR !!!/, output, "didn't include error handler problem message")
-    ensure
-      @config[:error_handlers].delete(test_handler)
-    end
-
-    it "handles exceptions in error handlers" do
-      test_handler = ->(_ex, _ctx) { raise SystemStackError }
-      @config[:error_handlers] << test_handler
-      output = capture_logging(@config) do
-        Thing.new(@config).invoke_exception(a: 1)
-      end
-
-      assert_match(/DEPRECATION/, output, "didn't include the deprecation warning")
-      assert_match(/SystemStackError/, output, "didn't include the exception")
-      assert_match(/Something didn't work!/, output, "didn't include the exception message")
-      assert_match(/!!! ERROR HANDLER THREW AN ERROR !!!/, output, "didn't include error handler problem message")
-    ensure
-      @config[:error_handlers].delete(test_handler)
-    end
-
-    it "cleans a backtrace if there is a cleaner" do
-      @config[:backtrace_cleaner] = ->(backtrace) { backtrace.take(1) }
-      output = capture_logging(@config) do
-        Thing.new(@config).invoke_exception(a: 1)
-      end
-
-      assert_equal 1, output.lines.count { |line| line.match?(/\d+:in/) }
-    ensure
-      @config[:backtrace_cleaner] = Sidekiq::Config::DEFAULTS[:backtrace_cleaner]
-    end
-
-    describe "when the exception does not have a backtrace" do
-      it "does not fail" do
-        exception = ExceptionHandlerTestException.new
-        assert_nil exception.backtrace
-
-        Thing.new(@config).handle_exception exception
-      end
-    end
-  end
-end
diff --git a/vendor/gems/sidekiq-7.1.6/web/views/filtering.erb b/vendor/gems/sidekiq-7.1.6/web/views/filtering.erb
deleted file mode 100644
index 139fff108340bcca72c3e9ef9bc8d2d6c18e9222..0000000000000000000000000000000000000000
--- a/vendor/gems/sidekiq-7.1.6/web/views/filtering.erb
+++ /dev/null
@@ -1,7 +0,0 @@
-<div class="sm-col-3 pull-right" style="display: inline; margin: 25px 15px 0 0;">
-  <%= t('Filter') %>:
-  <form method="POST" action='<%= root_path %>filter/<%= which %>' style="display: inline-block">
-    <%= csrf_tag %>
-    <input class="search" type="search" name="substr" value="<%= h params[:substr] %>" placeholder="<%= t('AnyJobContent') %>"/>
-  </form>
-</div>
diff --git a/vendor/gems/sidekiq-7.1.6/.gitlab-ci.yml b/vendor/gems/sidekiq-7.2.4/.gitlab-ci.yml
similarity index 92%
rename from vendor/gems/sidekiq-7.1.6/.gitlab-ci.yml
rename to vendor/gems/sidekiq-7.2.4/.gitlab-ci.yml
index 1bb1431d60069e1ede25226fb634aaf95e156ce0..ff9efb306ca8ddb5acfd5ebbd42de14845210547 100644
--- a/vendor/gems/sidekiq-7.1.6/.gitlab-ci.yml
+++ b/vendor/gems/sidekiq-7.2.4/.gitlab-ci.yml
@@ -1,7 +1,7 @@
 include:
   - local: gems/gem.gitlab-ci.yml
     inputs:
-      gem_name: "sidekiq-7.1.6"
+      gem_name: "sidekiq-7.2.4"
       gem_path_prefix: "vendor/gems/"
 
 rspec:
diff --git a/vendor/gems/sidekiq-7.1.6/Changes.md b/vendor/gems/sidekiq-7.2.4/Changes.md
similarity index 97%
rename from vendor/gems/sidekiq-7.1.6/Changes.md
rename to vendor/gems/sidekiq-7.2.4/Changes.md
index 574b3d37edaa9c8025ab2b809c3cc50355601cad..34fdca72989e40dc9a028707895beee5eb191426 100644
--- a/vendor/gems/sidekiq-7.1.6/Changes.md
+++ b/vendor/gems/sidekiq-7.2.4/Changes.md
@@ -2,6 +2,69 @@
 
 [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)
 
+7.2.4
+----------
+
+- Fix XSS in metrics filtering introduced in 7.2.0, CVE-2024-32887
+  Thanks to @UmerAdeemCheema for the security report.
+
+7.2.3
+----------
+
+- [Support Dragonfly.io](https://www.mikeperham.com/2024/02/01/supporting-dragonfly/) as an alternative Redis implementation
+- Fix error unpacking some compressed error backtraces [#6241]
+- Fix potential heartbeat data leak [#6227]
+- Add ability to find a currently running work by jid [#6212, fatkodima]
+
+7.2.2
+----------
+
+- Add `Process.warmup` call in Ruby 3.3+
+- Batch jobs now skip transactional push [#6160]
+
+7.2.1
+----------
+
+- Add `Sidekiq::Work` type which replaces the raw Hash as the third parameter in
+  `Sidekiq::WorkSet#each { |pid, tid, hash| ... }` [#6145]
+- **DEPRECATED**: direct access to the attributes within the `hash` block parameter above.
+  The `Sidekiq::Work` instance contains accessor methods to get at the same data, e.g.
+```ruby
+work["queue"] # Old
+work.queue # New
+```
+- Fix Ruby 3.3 warnings around `base64` gem [#6151, earlopain]
+
+7.2.0
+----------
+
+- `sidekiq_retries_exhausted` can return `:discard` to avoid the deadset
+  and all death handlers [#6091]
+- Metrics filtering by job class in Web UI [#5974]
+- Better readability and formatting for numbers within the Web UI [#6080]
+- Add explicit error if user code tries to nest test modes [#6078]
+```ruby
+Sidekiq::Testing.inline! # global setting
+Sidekiq::Testing.fake! do # override within block
+  # ok
+  Sidekiq::Testing.inline! do # can't override the override
+    # not ok, nested
+  end
+end
+```
+- **SECURITY** Forbid inline JavaScript execution in Web UI [#6074]
+- Adjust redis-client adapter to avoid `method_missing` [#6083]
+  This can result in app code breaking if your app's Redis API usage was
+  depending on Sidekiq's adapter to correct invalid redis-client API usage.
+  One example:
+```ruby
+# bad, not redis-client native
+# Unsupported command argument type: TrueClass (TypeError)
+Sidekiq.redis { |c| c.set("key", "value", nx: true, ex: 15) }
+# good
+Sidekiq.redis { |c| c.set("key", "value", "nx", "ex", 15) }
+```
+
 7.1.6
 ----------
 
@@ -150,6 +213,11 @@ end
 - Job Execution metrics!!!
 - See `docs/7.0-Upgrade.md` for release notes
 
+6.5.{10,11,12}
+----------
+
+- Fixes for Rails 7.1 [#6067, #6070]
+
 6.5.9
 ----------
 
diff --git a/vendor/gems/sidekiq-7.1.6/Gemfile b/vendor/gems/sidekiq-7.2.4/Gemfile
similarity index 86%
rename from vendor/gems/sidekiq-7.1.6/Gemfile
rename to vendor/gems/sidekiq-7.2.4/Gemfile
index 7f2bd8549e8dbb5d33b8b70c7022066799052a45..a66875e8228600bdf5974550462a447dee0d948b 100644
--- a/vendor/gems/sidekiq-7.1.6/Gemfile
+++ b/vendor/gems/sidekiq-7.2.4/Gemfile
@@ -1,11 +1,9 @@
-# frozen_string_literal: true
-
 source "https://rubygems.org"
 
 gemspec
 
 gem "rake"
-RAILS_VERSION = "~> 7.0.4"
+RAILS_VERSION = "~> 7.1"
 gem "actionmailer", RAILS_VERSION
 gem "actionpack", RAILS_VERSION
 gem "activejob", RAILS_VERSION
@@ -15,7 +13,7 @@ gem "redis-client"
 # gem "bumbler"
 # gem "debug"
 
-gem "sqlite3", platforms: :ruby
+gem "sqlite3", "~> 1.4", platforms: :ruby
 gem "activerecord-jdbcsqlite3-adapter", platforms: :jruby
 gem "after_commit_everywhere", require: false
 gem "yard"
diff --git a/vendor/gems/sidekiq-7.2.4/Gemfile.lock b/vendor/gems/sidekiq-7.2.4/Gemfile.lock
new file mode 100644
index 0000000000000000000000000000000000000000..d80acea98bb40529b6fb39d48f191003119ce244
--- /dev/null
+++ b/vendor/gems/sidekiq-7.2.4/Gemfile.lock
@@ -0,0 +1,241 @@
+PATH
+  remote: .
+  specs:
+    sidekiq (7.2.4)
+      concurrent-ruby (< 2)
+      connection_pool (>= 2.3.0)
+      rack (>= 2.2.4)
+      redis-client (>= 0.19.0)
+
+GEM
+  remote: https://rubygems.org/
+  specs:
+    actionmailer (7.2.0)
+      actionpack (= 7.2.0)
+      actionview (= 7.2.0)
+      activejob (= 7.2.0)
+      activesupport (= 7.2.0)
+      mail (>= 2.8.0)
+      rails-dom-testing (~> 2.2)
+    actionpack (7.2.0)
+      actionview (= 7.2.0)
+      activesupport (= 7.2.0)
+      nokogiri (>= 1.8.5)
+      racc
+      rack (>= 2.2.4, < 3.2)
+      rack-session (>= 1.0.1)
+      rack-test (>= 0.6.3)
+      rails-dom-testing (~> 2.2)
+      rails-html-sanitizer (~> 1.6)
+      useragent (~> 0.16)
+    actionview (7.2.0)
+      activesupport (= 7.2.0)
+      builder (~> 3.1)
+      erubi (~> 1.11)
+      rails-dom-testing (~> 2.2)
+      rails-html-sanitizer (~> 1.6)
+    activejob (7.2.0)
+      activesupport (= 7.2.0)
+      globalid (>= 0.3.6)
+    activemodel (7.2.0)
+      activesupport (= 7.2.0)
+    activerecord (7.2.0)
+      activemodel (= 7.2.0)
+      activesupport (= 7.2.0)
+      timeout (>= 0.4.0)
+    activesupport (7.2.0)
+      base64
+      bigdecimal
+      concurrent-ruby (~> 1.0, >= 1.3.1)
+      connection_pool (>= 2.2.5)
+      drb
+      i18n (>= 1.6, < 2)
+      logger (>= 1.4.2)
+      minitest (>= 5.1)
+      securerandom (>= 0.3)
+      tzinfo (~> 2.0, >= 2.0.5)
+    after_commit_everywhere (1.4.0)
+      activerecord (>= 4.2)
+      activesupport
+    ast (2.4.2)
+    base64 (0.2.0)
+    bigdecimal (3.1.8)
+    builder (3.3.0)
+    concurrent-ruby (1.3.4)
+    connection_pool (2.4.1)
+    crass (1.0.6)
+    date (3.3.4)
+    docile (1.4.1)
+    drb (2.2.1)
+    erubi (1.13.0)
+    globalid (1.2.1)
+      activesupport (>= 6.1)
+    i18n (1.14.5)
+      concurrent-ruby (~> 1.0)
+    io-console (0.7.2)
+    irb (1.14.0)
+      rdoc (>= 4.0.0)
+      reline (>= 0.4.2)
+    json (2.7.2)
+    language_server-protocol (3.17.0.3)
+    lint_roller (1.1.0)
+    logger (1.6.0)
+    loofah (2.22.0)
+      crass (~> 1.0.2)
+      nokogiri (>= 1.12.0)
+    mail (2.8.1)
+      mini_mime (>= 0.1.1)
+      net-imap
+      net-pop
+      net-smtp
+    maxitest (5.6.0)
+      minitest (>= 5.14.0, < 5.25.0)
+    mini_mime (1.1.5)
+    minitest (5.24.1)
+    net-imap (0.4.14)
+      date
+      net-protocol
+    net-pop (0.1.2)
+      net-protocol
+    net-protocol (0.2.2)
+      timeout
+    net-smtp (0.5.0)
+      net-protocol
+    nokogiri (1.16.7-aarch64-linux)
+      racc (~> 1.4)
+    nokogiri (1.16.7-arm-linux)
+      racc (~> 1.4)
+    nokogiri (1.16.7-arm64-darwin)
+      racc (~> 1.4)
+    nokogiri (1.16.7-x86-linux)
+      racc (~> 1.4)
+    nokogiri (1.16.7-x86_64-darwin)
+      racc (~> 1.4)
+    nokogiri (1.16.7-x86_64-linux)
+      racc (~> 1.4)
+    parallel (1.26.3)
+    parser (3.3.4.2)
+      ast (~> 2.4.1)
+      racc
+    psych (5.1.2)
+      stringio
+    racc (1.8.1)
+    rack (3.1.7)
+    rack-session (2.0.0)
+      rack (>= 3.0.0)
+    rack-test (2.1.0)
+      rack (>= 1.3)
+    rackup (2.1.0)
+      rack (>= 3)
+      webrick (~> 1.8)
+    rails-dom-testing (2.2.0)
+      activesupport (>= 5.0.0)
+      minitest
+      nokogiri (>= 1.6)
+    rails-html-sanitizer (1.6.0)
+      loofah (~> 2.21)
+      nokogiri (~> 1.14)
+    railties (7.2.0)
+      actionpack (= 7.2.0)
+      activesupport (= 7.2.0)
+      irb (~> 1.13)
+      rackup (>= 1.0.0)
+      rake (>= 12.2)
+      thor (~> 1.0, >= 1.2.2)
+      zeitwerk (~> 2.6)
+    rainbow (3.1.1)
+    rake (13.2.1)
+    rdoc (6.7.0)
+      psych (>= 4.0.0)
+    redis-client (0.22.2)
+      connection_pool
+    regexp_parser (2.9.2)
+    reline (0.5.9)
+      io-console (~> 0.5)
+    rexml (3.3.6)
+      strscan
+    rubocop (1.65.1)
+      json (~> 2.3)
+      language_server-protocol (>= 3.17.0)
+      parallel (~> 1.10)
+      parser (>= 3.3.0.2)
+      rainbow (>= 2.2.2, < 4.0)
+      regexp_parser (>= 2.4, < 3.0)
+      rexml (>= 3.2.5, < 4.0)
+      rubocop-ast (>= 1.31.1, < 2.0)
+      ruby-progressbar (~> 1.7)
+      unicode-display_width (>= 2.4.0, < 3.0)
+    rubocop-ast (1.32.1)
+      parser (>= 3.3.1.0)
+    rubocop-performance (1.21.1)
+      rubocop (>= 1.48.1, < 2.0)
+      rubocop-ast (>= 1.31.1, < 2.0)
+    ruby-prof (1.7.0)
+    ruby-progressbar (1.13.0)
+    securerandom (0.3.1)
+    simplecov (0.22.0)
+      docile (~> 1.1)
+      simplecov-html (~> 0.11)
+      simplecov_json_formatter (~> 0.1)
+    simplecov-html (0.12.3)
+    simplecov_json_formatter (0.1.4)
+    sqlite3 (1.7.3-aarch64-linux)
+    sqlite3 (1.7.3-arm-linux)
+    sqlite3 (1.7.3-arm64-darwin)
+    sqlite3 (1.7.3-x86-linux)
+    sqlite3 (1.7.3-x86_64-darwin)
+    sqlite3 (1.7.3-x86_64-linux)
+    standard (1.40.0)
+      language_server-protocol (~> 3.17.0.2)
+      lint_roller (~> 1.0)
+      rubocop (~> 1.65.0)
+      standard-custom (~> 1.0.0)
+      standard-performance (~> 1.4)
+    standard-custom (1.0.2)
+      lint_roller (~> 1.0)
+      rubocop (~> 1.50)
+    standard-performance (1.4.0)
+      lint_roller (~> 1.1)
+      rubocop-performance (~> 1.21.0)
+    stringio (3.1.1)
+    strscan (3.1.0)
+    thor (1.3.1)
+    timeout (0.4.1)
+    toxiproxy (2.0.2)
+    tzinfo (2.0.6)
+      concurrent-ruby (~> 1.0)
+    unicode-display_width (2.5.0)
+    useragent (0.16.10)
+    webrick (1.8.1)
+    yard (0.9.36)
+    zeitwerk (2.6.17)
+
+PLATFORMS
+  aarch64-linux
+  arm-linux
+  arm64-darwin
+  x86-linux
+  x86_64-darwin
+  x86_64-linux
+
+DEPENDENCIES
+  actionmailer (~> 7.1)
+  actionpack (~> 7.1)
+  activejob (~> 7.1)
+  activerecord (~> 7.1)
+  activerecord-jdbcsqlite3-adapter
+  after_commit_everywhere
+  maxitest
+  railties (~> 7.1)
+  rake
+  redis-client
+  ruby-prof
+  sidekiq!
+  simplecov
+  sqlite3 (~> 1.4)
+  standard
+  toxiproxy
+  yard
+
+BUNDLED WITH
+   2.5.17
diff --git a/vendor/gems/sidekiq-7.1.6/LICENSE.txt b/vendor/gems/sidekiq-7.2.4/LICENSE.txt
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/LICENSE.txt
rename to vendor/gems/sidekiq-7.2.4/LICENSE.txt
diff --git a/vendor/gems/sidekiq-7.1.6/NOTICE.txt b/vendor/gems/sidekiq-7.2.4/NOTICE.txt
similarity index 72%
rename from vendor/gems/sidekiq-7.1.6/NOTICE.txt
rename to vendor/gems/sidekiq-7.2.4/NOTICE.txt
index 195d15dcf89d6fe582ac665c4fc8e6ec3e7c2712..9b389b6bea301406497af90d353b695b09ec1d46 100644
--- a/vendor/gems/sidekiq-7.1.6/NOTICE.txt
+++ b/vendor/gems/sidekiq-7.2.4/NOTICE.txt
@@ -3,11 +3,11 @@ Copyright (c) Contributed Systems LLC
 This product includes software developed at
 Contributed Systems LLC(https://contribsys.com/).
 
-Modifications to the following files were made on 30 Jan 2024 by GitLab:
-- sidekiq.gemspec
+Modifications to the following files were made on 2024-08-22 by GitLab:
 - lib/sidekiq/redis_client_adapter.rb
-- lib/sidekiq/redis_connection.rb
 - lib/sidekiq/api.rb
 - lib/sidekiq/cli.rb
 - lib/sidekiq/paginator.rb
 - lib/sidekiq/scheduled.rb
+- sidekiq.gemspec
+- test/web_test.rb
diff --git a/vendor/gems/sidekiq-7.1.6/README.md b/vendor/gems/sidekiq-7.2.4/README.md
similarity index 97%
rename from vendor/gems/sidekiq-7.1.6/README.md
rename to vendor/gems/sidekiq-7.2.4/README.md
index 0a007a1deba55edf376dd94eb30143916de07ca3..2e047d4a181a1b0da8a0c30d2f7d263902c8fcad 100644
--- a/vendor/gems/sidekiq-7.1.6/README.md
+++ b/vendor/gems/sidekiq-7.2.4/README.md
@@ -14,11 +14,11 @@ Rails to make background processing dead simple.
 Requirements
 -----------------
 
-- Redis: 6.2+
+- Redis: Redis 6.2+ or Dragonfly 1.13+
 - Ruby: MRI 2.7+ or JRuby 9.3+.
 
 Sidekiq 7.0 supports Rails 6.0+ but does not require it.
-
+As of 7.2, Sidekiq supports Dragonfly as an alternative to Redis for data storage.
 
 Installation
 -----------------
diff --git a/vendor/gems/sidekiq-7.1.6/Rakefile b/vendor/gems/sidekiq-7.2.4/Rakefile
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/Rakefile
rename to vendor/gems/sidekiq-7.2.4/Rakefile
diff --git a/vendor/gems/sidekiq-7.2.4/bin/multi_queue_bench b/vendor/gems/sidekiq-7.2.4/bin/multi_queue_bench
new file mode 100755
index 0000000000000000000000000000000000000000..f67897d784aa35885ac1311dc1d62cb942714cd2
--- /dev/null
+++ b/vendor/gems/sidekiq-7.2.4/bin/multi_queue_bench
@@ -0,0 +1,271 @@
+#!/usr/bin/env ruby
+
+#
+# bin/bench is a helpful script to load test and
+# performance tune Sidekiq's core. It's a configurable script,
+# which accepts the following parameters as ENV variables.
+#
+# QUEUES
+# Number of queues to consume from. Default is 8
+#
+# PROCESSES
+# The number of processes this benchmark will create. Each process, consumes
+# from one of the available queues. When processes are more than the number of
+# queues, they are distributed to processes in round robin. Default is 8
+#
+# ELEMENTS
+# Number of jobs to push to each queue. Default is 1000
+#
+# ITERATIONS
+# Each queue pushes ITERATIONS times ELEMENTS jobs. Default is 1000
+#
+# PORT
+# The port of the Dragonfly instance. Default is 6379
+#
+# IP
+# The ip of the Dragonfly instance. Default is 127.0.0.1
+#
+# Example Usage:
+#
+# > RUBY_YJIT_ENABLE=1 THREADS=10 PROCESSES=8 QUEUES=8 bin/multi_queue_bench
+#
+# None of this script is considered a public API and may change over time.
+#
+
+# Quiet some warnings we see when running in warning mode:
+# RUBYOPT=-w bundle exec sidekiq
+$TESTING = false
+puts RUBY_DESCRIPTION
+
+require "bundler/setup"
+Bundler.require(:default, :load_test)
+
+class LoadWorker
+  include Sidekiq::Job
+  sidekiq_options retry: 1
+  sidekiq_retry_in do |x|
+    1
+  end
+
+  def perform(idx, ts = nil)
+    puts(Time.now.to_f - ts) if !ts.nil?
+    # raise idx.to_s if idx % 100 == 1
+  end
+end
+
+def Process.rss
+  `ps -o rss= -p #{Process.pid}`.chomp.to_i
+end
+
+$iterations = ENV["ITERATIONS"] ? Integer(ENV["ITERATIONS"]) : 1_000
+$elements = ENV["ELEMENTS"] ? Integer(ENV["ELEMENTS"]) : 1_000
+$port = ENV["PORT"] ? Integer(ENV["PORT"]) : 6379
+$ip = ENV["IP"] ? String(ENV["IP"]) : "127.0.0.1"
+
+class Loader
+  def initialize
+    @iter =  $iterations
+    @count = $elements
+  end
+
+  def configure(queue)
+    @x = Sidekiq.configure_embed do |config|
+      config.redis = {db: 0, host: $ip, port: $port}
+      config.concurrency = Integer(ENV.fetch("THREADS", "30"))
+      config.queues = queue
+      config.logger.level = Logger::WARN
+      config.average_scheduled_poll_interval = 2
+      config.reliable! if defined?(Sidekiq::Pro)
+    end
+
+    @self_read, @self_write = IO.pipe
+    %w[INT TERM TSTP TTIN].each do |sig|
+      trap sig do
+        @self_write.puts(sig)
+      end
+    rescue ArgumentError
+      puts "Signal #{sig} not supported"
+    end
+  end
+
+  def handle_signal(sig)
+    launcher = @x
+    Sidekiq.logger.debug "Got #{sig} signal"
+    case sig
+    when "INT"
+      # Handle Ctrl-C in JRuby like MRI
+      # http://jira.codehaus.org/browse/JRUBY-4637
+      raise Interrupt
+    when "TERM"
+      # Heroku sends TERM and then waits 30 seconds for process to exit.
+      raise Interrupt
+    when "TSTP"
+      Sidekiq.logger.info "Received TSTP, no longer accepting new work"
+      launcher.quiet
+    when "TTIN"
+      Thread.list.each do |thread|
+        Sidekiq.logger.warn "Thread TID-#{(thread.object_id ^ ::Process.pid).to_s(36)} #{thread["label"]}"
+        if thread.backtrace
+          Sidekiq.logger.warn thread.backtrace.join("\n")
+        else
+          Sidekiq.logger.warn "<no backtrace available>"
+        end
+      end
+    end
+  end
+
+  def setup(queue)
+    Sidekiq.logger.error("Setup RSS: #{Process.rss}")
+    Sidekiq.logger.error("Pushing work to queue: #{queue}")
+    start = Time.now
+    @iter.times do
+      arr = Array.new(@count) { |idx| [idx] }
+      # Sidekiq always prepends "queue:" to the queue name,
+      # that's why we pass 'q1', 'q2', etc instead of 'queue:q1'
+      Sidekiq::Client.push_bulk("class" => LoadWorker, "args" => arr, "queue" => queue)
+      $stdout.write "."
+    end
+    puts "Done"
+  end
+
+  def monitor_single(queue)
+    q = "queue:#{queue}"
+    @monitor_single = Thread.new do
+      GC.start
+      loop do
+        sleep 0.2
+        total = Sidekiq.redis do |conn|
+          conn.llen q
+        end
+
+        if total == 0
+          sleep 0.1
+          @x.stop
+          Process.kill("INT", $$)
+          break
+        end
+
+      end
+    end
+  end
+
+  def monitor_all(queues)
+    @monitor_all = Thread.new do
+      GC.start
+      loop do
+        sleep 0.2
+        qsize = 0
+        queues.each do |q|
+          tmp = Sidekiq.redis do |conn|
+            conn.llen q
+          end
+          qsize = qsize + tmp
+        end
+        total = qsize
+
+        if total == 0
+          ending = Time.now - @start
+          size = @iter * @count * queues.length()
+          Sidekiq.logger.error("Done, #{size} jobs in #{ending} sec, #{(size / ending).to_i} jobs/sec")
+          Sidekiq.logger.error("Ending RSS: #{Process.rss}")
+
+          sleep 0.1
+          @x.stop
+          Process.kill("INT", $$)
+          break
+        end
+      end
+    end
+  end
+
+  def run(queues, queue, monitor_all_queues)
+    Sidekiq.logger.warn("Consuming from #{queue}")
+    if monitor_all_queues
+      monitor_all(queues)
+    else
+      monitor_single(queue)
+    end
+
+    @start = Time.now
+    @x.run
+
+    while (readable_io = IO.select([@self_read]))
+      signal = readable_io.first[0].gets.strip
+      handle_signal(signal)
+    end
+    # normal
+  rescue Interrupt
+  rescue => e
+    raise e if $DEBUG
+    warn e.message
+    warn e.backtrace.join("\n")
+    exit 1
+  ensure
+    @x.stop
+  end
+end
+
+def setup(queue)
+  ll = Loader.new
+  ll.configure(queue)
+  ll.setup(queue)
+end
+
+def consume(queues, queue, monitor_all_queues)
+  ll = Loader.new
+  ll.configure(queue)
+  ll.run(queues, queue, monitor_all_queues)
+end
+
+# We assign one queue to each sidekiq process
+def run(number_of_processes, total_queues)
+  read_stream, write_stream = IO.pipe
+
+  queues = []
+  (0..total_queues-1).each do |idx|
+    queues.push("queue:q#{idx}")
+  end
+
+  Sidekiq.logger.info("Queues are: #{queues}")
+
+  # Produce
+  start = Time.now
+  (0..total_queues-1).each do |idx|
+    Process.fork do
+      queue_num = "q#{idx}"
+      setup(queue_num)
+    end
+  end
+
+  queue_sz = $iterations * $elements * total_queues
+  Process.waitall
+
+  ending = Time.now - start
+  #Sidekiq.logger.info("Pushed #{queue_sz} in #{ending} secs")
+
+  # Consume
+  (0..number_of_processes-1).each do |idx|
+    Process.fork do
+      # First process only consumes from it's own queue but monitors all queues.
+      # It works as a synchronization point. Once all processes finish
+      # (that is, when all queues are emptied) it prints the the stats.
+      if idx == 0
+        queue = "q#{idx}"
+        consume(queues, queue, true)
+      else
+        queue = "q#{idx % total_queues}"
+        consume(queues, queue, false)
+      end
+    end
+  end
+
+  Process.waitall
+  write_stream.close
+  results = read_stream.read
+  read_stream.close
+end
+
+$total_processes = ENV["PROCESSES"] ? Integer(ENV["PROCESSES"]) : 8;
+$total_queues = ENV["QUEUES"] ? Integer(ENV["QUEUES"]) : 8;
+
+run($total_processes, $total_queues)
diff --git a/vendor/gems/sidekiq-7.1.6/bin/sidekiq b/vendor/gems/sidekiq-7.2.4/bin/sidekiq
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/bin/sidekiq
rename to vendor/gems/sidekiq-7.2.4/bin/sidekiq
diff --git a/vendor/gems/sidekiq-7.1.6/bin/sidekiqload b/vendor/gems/sidekiq-7.2.4/bin/sidekiqload
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/bin/sidekiqload
rename to vendor/gems/sidekiq-7.2.4/bin/sidekiqload
diff --git a/vendor/gems/sidekiq-7.1.6/bin/sidekiqmon b/vendor/gems/sidekiq-7.2.4/bin/sidekiqmon
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/bin/sidekiqmon
rename to vendor/gems/sidekiq-7.2.4/bin/sidekiqmon
diff --git a/vendor/gems/sidekiq-7.1.6/lib/generators/sidekiq/job_generator.rb b/vendor/gems/sidekiq-7.2.4/lib/generators/sidekiq/job_generator.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/lib/generators/sidekiq/job_generator.rb
rename to vendor/gems/sidekiq-7.2.4/lib/generators/sidekiq/job_generator.rb
diff --git a/vendor/gems/sidekiq-7.1.6/lib/generators/sidekiq/templates/job.rb.erb b/vendor/gems/sidekiq-7.2.4/lib/generators/sidekiq/templates/job.rb.erb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/lib/generators/sidekiq/templates/job.rb.erb
rename to vendor/gems/sidekiq-7.2.4/lib/generators/sidekiq/templates/job.rb.erb
diff --git a/vendor/gems/sidekiq-7.1.6/lib/generators/sidekiq/templates/job_spec.rb.erb b/vendor/gems/sidekiq-7.2.4/lib/generators/sidekiq/templates/job_spec.rb.erb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/lib/generators/sidekiq/templates/job_spec.rb.erb
rename to vendor/gems/sidekiq-7.2.4/lib/generators/sidekiq/templates/job_spec.rb.erb
diff --git a/vendor/gems/sidekiq-7.1.6/lib/generators/sidekiq/templates/job_test.rb.erb b/vendor/gems/sidekiq-7.2.4/lib/generators/sidekiq/templates/job_test.rb.erb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/lib/generators/sidekiq/templates/job_test.rb.erb
rename to vendor/gems/sidekiq-7.2.4/lib/generators/sidekiq/templates/job_test.rb.erb
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq.rb
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/api.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/api.rb
similarity index 94%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/api.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/api.rb
index a71e76ce6da00956e6b65dbd2db2f188e22923de..0739044faae28e7a440f6c729b43b4670a3e6ccc 100644
--- a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/api.rb
+++ b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/api.rb
@@ -4,7 +4,6 @@
 
 require "zlib"
 require "set"
-require "base64"
 
 require "sidekiq/metrics/query"
 
@@ -491,8 +490,8 @@ def serialized_global_id?(hash)
     end
 
     def uncompress_backtrace(backtrace)
-      decoded = Base64.decode64(backtrace)
-      uncompressed = Zlib::Inflate.inflate(decoded)
+      strict_base64_decoded = backtrace.unpack1("m")
+      uncompressed = Zlib::Inflate.inflate(strict_base64_decoded)
       Sidekiq.load_json(uncompressed)
     end
   end
@@ -679,7 +678,7 @@ def each
         range_start = page * page_size + offset_size
         range_end = range_start + page_size - 1
         elements = Sidekiq.redis { |conn|
-          conn.zrange name, range_start, range_end, withscores: true
+          conn.zrange name, range_start, range_end, "withscores"
         }
         break if elements.empty?
         page -= 1
@@ -774,7 +773,7 @@ def delete_by_jid(score, jid)
   #
   class ScheduledSet < JobSet
     def initialize
-      super "schedule"
+      super("schedule")
     end
   end
 
@@ -788,7 +787,7 @@ def initialize
   #
   class RetrySet < JobSet
     def initialize
-      super "retry"
+      super("retry")
     end
 
     # Enqueues all jobs pending within the retry set.
@@ -809,7 +808,7 @@ def kill_all
   #
   class DeadSet < JobSet
     def initialize
-      super "dead"
+      super("dead")
     end
 
     # Add the given job to the Dead set.
@@ -881,7 +880,7 @@ def initialize(clean_plz = true)
     # @api private
     def cleanup
       # dont run cleanup more than once per minute
-      return 0 unless Sidekiq.redis { |conn| conn.set("process_cleanup", "1", nx: true, ex: 60) }
+      return 0 unless Sidekiq.redis { |conn| conn.set("process_cleanup", "1", "NX", "EX", "60") }
 
       count = 0
       Sidekiq.redis do |conn|
@@ -1110,11 +1109,11 @@ def each(&block)
 
       procs.zip(all_works).each do |key, workers|
         workers.each_pair do |tid, json|
-          results << [key, tid, Sidekiq.load_json(json)] unless json.empty?
+          results << [key, tid, Sidekiq::Work.new(key, tid, Sidekiq.load_json(json))] unless json.empty?
         end
       end
 
-      results.sort_by { |(_, _, hsh)| hsh["run_at"] }.each(&block)
+      results.sort_by { |(_, _, hsh)| hsh.raw("run_at") }.each(&block)
     end
 
     # Note that #size is only as accurate as Sidekiq's heartbeat,
@@ -1137,7 +1136,74 @@ def size
         end
       end
     end
+
+    ##
+    # Find the work which represents a job with the given JID.
+    # *This is a slow O(n) operation*.  Do not use for app logic.
+    #
+    # @param jid [String] the job identifier
+    # @return [Sidekiq::Work] the work or nil
+    def find_work_by_jid(jid)
+      each do |_process_id, _thread_id, work|
+        job = work.job
+        return work if job.jid == jid
+      end
+      nil
+    end
   end
+
+  # Sidekiq::Work represents a job which is currently executing.
+  class Work
+    attr_reader :process_id
+    attr_reader :thread_id
+
+    def initialize(pid, tid, hsh)
+      @process_id = pid
+      @thread_id = tid
+      @hsh = hsh
+      @job = nil
+    end
+
+    def queue
+      @hsh["queue"]
+    end
+
+    def run_at
+      Time.at(@hsh["run_at"])
+    end
+
+    def job
+      @job ||= Sidekiq::JobRecord.new(@hsh["payload"])
+    end
+
+    def payload
+      @hsh["payload"]
+    end
+
+    # deprecated
+    def [](key)
+      kwargs = {uplevel: 1}
+      kwargs[:category] = :deprecated if RUBY_VERSION > "3.0" # TODO
+      warn("Direct access to `Sidekiq::Work` attributes is deprecated, please use `#payload`, `#queue`, `#run_at` or `#job` instead", **kwargs)
+
+      @hsh[key]
+    end
+
+    # :nodoc:
+    # @api private
+    def raw(name)
+      @hsh[name]
+    end
+
+    def method_missing(*all)
+      @hsh.send(*all)
+    end
+
+    def respond_to_missing?(name)
+      @hsh.respond_to?(name)
+    end
+  end
+
   # Since "worker" is a nebulous term, we've deprecated the use of this class name.
   # Is "worker" a process, a type of job, a thread? Undefined!
   # WorkSet better describes the data.
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/capsule.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/capsule.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/capsule.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/capsule.rb
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/cli.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/cli.rb
similarity index 99%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/cli.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/cli.rb
index 6985dc35b34188809366d27acd70ef9830b77747..8dcf97473480d44380a18440c199c44055ccb605 100644
--- a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/cli.rb
+++ b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/cli.rb
@@ -38,7 +38,7 @@ def jruby?
     # Code within this method is not tested because it alters
     # global process state irreversibly.  PRs which improve the
     # test coverage of Sidekiq::CLI are welcomed.
-    def run(boot_app: true)
+    def run(boot_app: true, warmup: true)
       boot_application if boot_app
 
       if environment == "development" && $stdout.tty? && @config.logger.formatter.is_a?(Sidekiq::Logger::Formatters::Pretty)
@@ -101,6 +101,8 @@ def run(boot_app: true)
       # Touch middleware so it isn't lazy loaded by multiple threads, #3043
       @config.server_middleware
 
+      ::Process.warmup if warmup && ::Process.respond_to?(:warmup)
+
       # Before this point, the process is initializing with just the main thread.
       # Starting here the process will now have multiple threads running.
       fire_event(:startup, reverse: false, reraise: true)
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/client.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/client.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/client.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/client.rb
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/component.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/component.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/component.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/component.rb
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/config.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/config.rb
similarity index 98%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/config.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/config.rb
index 3e44a74cce83885fbaffefa3f43e40d30737571e..7c41f58ee89977f15a3f69bfd8364b9ff529ce13 100644
--- a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/config.rb
+++ b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/config.rb
@@ -258,9 +258,9 @@ def logger=(logger)
       @logger = logger
     end
 
-    private def arity(handler)
-      return handler.arity if handler.is_a?(Proc)
-      handler.method(:call).arity
+    private def parameter_size(handler)
+      target = handler.is_a?(Proc) ? handler : handler.method(:call)
+      target.parameters.size
     end
 
     # INTERNAL USE ONLY
@@ -269,7 +269,7 @@ def handle_exception(ex, ctx = {})
         p ["!!!!!", ex]
       end
       @options[:error_handlers].each do |handler|
-        if arity(handler) == 2
+        if parameter_size(handler) == 2
           # TODO Remove in 8.0
           logger.info { "DEPRECATION: Sidekiq exception handlers now take three arguments, see #{handler}" }
           handler.call(ex, {_config: self}.merge(ctx))
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/deploy.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/deploy.rb
similarity index 92%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/deploy.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/deploy.rb
index 805d571c5233187601c25cf639989815b3fc7f8b..56cc96760905c16a1d9370663c6e73eb3299eb03 100644
--- a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/deploy.rb
+++ b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/deploy.rb
@@ -34,7 +34,7 @@ def mark!(at: Time.now, label: nil)
       # handle an very common error in marking deploys:
       # having every process mark its deploy, leading
       # to N marks for each deploy. Instead we round the time
-      # to the minute so that multple marks within that minute
+      # to the minute so that multiple marks within that minute
       # will all naturally rollup into one mark per minute.
       whence = at.utc
       floor = Time.utc(whence.year, whence.month, whence.mday, whence.hour, whence.min, 0)
@@ -44,7 +44,7 @@ def mark!(at: Time.now, label: nil)
 
       @pool.with do |c|
         # only allow one deploy mark for a given label for the next minute
-        lock = c.set("deploylock-#{label}", stamp, nx: true, ex: 60)
+        lock = c.set("deploylock-#{label}", stamp, "nx", "ex", "60")
         if lock
           c.multi do |pipe|
             pipe.hsetnx(key, stamp, label)
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/embedded.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/embedded.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/embedded.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/embedded.rb
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/fetch.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/fetch.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/fetch.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/fetch.rb
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/job.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/job.rb
similarity index 99%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/job.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/job.rb
index 3e6fada9c013b5fb7bb9ef1bfa99f030d748c226..31db39add58c3880deaf68a2af682e4c86ff739d 100644
--- a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/job.rb
+++ b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/job.rb
@@ -109,7 +109,7 @@ def sidekiq_class_attribute(*attrs)
               m = "#{name}="
               undef_method(m) if method_defined?(m) || private_method_defined?(m)
             end
-            define_singleton_method("#{name}=") do |val|
+            define_singleton_method(:"#{name}=") do |val|
               singleton_class.class_eval do
                 ACCESSOR_MUTEX.synchronize do
                   undef_method(synchronized_getter) if method_defined?(synchronized_getter) || private_method_defined?(synchronized_getter)
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/job_logger.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/job_logger.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/job_logger.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/job_logger.rb
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/job_retry.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/job_retry.rb
similarity index 98%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/job_retry.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/job_retry.rb
index 5c07af7d110a5fc203ac592454608aba9c43015f..923874fdc35f5c44a48458d67b5381add5116ebb 100644
--- a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/job_retry.rb
+++ b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/job_retry.rb
@@ -1,7 +1,6 @@
 # frozen_string_literal: true
 
 require "zlib"
-require "base64"
 require "sidekiq/component"
 
 module Sidekiq
@@ -226,7 +225,7 @@ def delay_for(jobinst, count, exception, msg)
     end
 
     def retries_exhausted(jobinst, msg, exception)
-      begin
+      rv = begin
         block = jobinst&.sidekiq_retries_exhausted_block
 
         # the sidekiq_retries_exhausted_block can be defined in a wrapped class (ActiveJob for instance)
@@ -239,6 +238,7 @@ def retries_exhausted(jobinst, msg, exception)
         handle_exception(e, {context: "Error calling retries_exhausted", job: msg})
       end
 
+      return if rv == :discard # poof!
       send_to_morgue(msg) unless msg["dead"] == false
 
       @capsule.config.death_handlers.each do |handler|
@@ -294,7 +294,7 @@ def exception_message(exception)
     def compress_backtrace(backtrace)
       serialized = Sidekiq.dump_json(backtrace)
       compressed = Zlib::Deflate.deflate(serialized)
-      Base64.encode64(compressed)
+      [compressed].pack("m0") # Base64.strict_encode64
     end
   end
 end
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/job_util.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/job_util.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/job_util.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/job_util.rb
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/launcher.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/launcher.rb
similarity index 96%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/launcher.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/launcher.rb
index 6f439a0e2350ae541ea42745e54305880da88714..91b54a786ef43af93ec02555c13c699baaf933c2 100644
--- a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/launcher.rb
+++ b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/launcher.rb
@@ -145,15 +145,17 @@ def ❤
         flush_stats
 
         curstate = Processor::WORK_STATE.dup
+        curstate.transform_values! { |val| Sidekiq.dump_json(val) }
+
         redis do |conn|
           # work is the current set of executing jobs
           work_key = "#{key}:work"
-          conn.pipelined do |transaction|
+          conn.multi do |transaction|
             transaction.unlink(work_key)
-            curstate.each_pair do |tid, hash|
-              transaction.hset(work_key, tid, Sidekiq.dump_json(hash))
+            if curstate.size > 0
+              transaction.hset(work_key, curstate)
+              transaction.expire(work_key, 60)
             end
-            transaction.expire(work_key, 60)
           end
         end
 
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/logger.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/logger.rb
similarity index 98%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/logger.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/logger.rb
index 6794c6a8f2126ab74c7e1b2ad8bca1ad8ed26e40..f522ed2bf6cac3f88727a710858f21b996d52ec0 100644
--- a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/logger.rb
+++ b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/logger.rb
@@ -36,7 +36,7 @@ module LoggingUtils
     end
 
     LEVELS.each do |level, numeric_level|
-      define_method("#{level}?") do
+      define_method(:"#{level}?") do
         local_level.nil? ? super() : local_level <= numeric_level
       end
     end
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/manager.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/manager.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/manager.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/manager.rb
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/metrics/query.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/metrics/query.rb
similarity index 95%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/metrics/query.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/metrics/query.rb
index caeda76314872bc341108bba1a1b9dcaaa1c1488..a357c8dbc628aab2ef94a9a4f79e9c0b9580e69d 100644
--- a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/metrics/query.rb
+++ b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/metrics/query.rb
@@ -20,7 +20,8 @@ def initialize(pool: nil, now: Time.now)
       end
 
       # Get metric data for all jobs from the last hour
-      def top_jobs(minutes: 60)
+      #  +class_filter+: return only results for classes matching filter
+      def top_jobs(class_filter: nil, minutes: 60)
         result = Result.new
 
         time = @time
@@ -39,6 +40,7 @@ def top_jobs(minutes: 60)
         redis_results.each do |hash|
           hash.each do |k, v|
             kls, metric = k.split("|")
+            next if class_filter && !class_filter.match?(kls)
             result.job_results[kls].add_metric metric, time, v.to_i
           end
           time -= 60
@@ -117,6 +119,7 @@ def add_hist(time, hist_result)
 
         def total_avg(metric = "ms")
           completed = totals["p"] - totals["f"]
+          return 0 if completed.zero?
           totals[metric].to_f / completed
         end
 
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/metrics/shared.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/metrics/shared.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/metrics/shared.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/metrics/shared.rb
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/metrics/tracking.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/metrics/tracking.rb
similarity index 94%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/metrics/tracking.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/metrics/tracking.rb
index 9b723c5ebfd62508ecd2a616a5cee57f91a76505..c48dd8bcdfb4cf7612082be0c6552c223d88200c 100644
--- a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/metrics/tracking.rb
+++ b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/metrics/tracking.rb
@@ -103,12 +103,16 @@ def flush(time = Time.now)
       def reset
         @lock.synchronize {
           array = [@totals, @jobs, @grams]
-          @totals = Hash.new(0)
-          @jobs = Hash.new(0)
-          @grams = Hash.new { |hash, key| hash[key] = Histogram.new(key) }
+          reset_instance_variables
           array
         }
       end
+
+      def reset_instance_variables
+        @totals = Hash.new(0)
+        @jobs = Hash.new(0)
+        @grams = Hash.new { |hash, key| hash[key] = Histogram.new(key) }
+      end
     end
 
     class Middleware
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/middleware/chain.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/middleware/chain.rb
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/current_attributes.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/middleware/current_attributes.rb
similarity index 97%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/current_attributes.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/middleware/current_attributes.rb
index 2af9877fdc6036f6be3612fbade641c91cd072ff..80cbe9590ecd14bc215967176b009aff445f04b9 100644
--- a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/current_attributes.rb
+++ b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/middleware/current_attributes.rb
@@ -54,7 +54,7 @@ def call(_, job, _, &block)
             cattrs_to_reset << constklass
 
             job[key].each do |(attribute, value)|
-              constklass.public_send("#{attribute}=", value)
+              constklass.public_send(:"#{attribute}=", value)
             end
           end
         end
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/i18n.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/middleware/i18n.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/i18n.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/middleware/i18n.rb
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/modules.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/middleware/modules.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/modules.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/middleware/modules.rb
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/monitor.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/monitor.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/monitor.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/monitor.rb
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/paginator.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/paginator.rb
similarity index 95%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/paginator.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/paginator.rb
index 8f66d4011fcf4b2b6bd9d8d03159c0202de08982..e895fee519b35fbeb943bcaeadad84c8b2c157f4 100644
--- a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/paginator.rb
+++ b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/paginator.rb
@@ -21,7 +21,7 @@ def page(key, pageidx = 1, page_size = 25, opts = nil)
             if rev
               transaction.zrevrange(key, starting, ending, withscores: true)
             else
-              transaction.zrange(key, starting, ending, withscores: true)
+              transaction.zrange(key, starting, ending, "withscores")
             end
           }
           [current_page, total_size, items]
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/processor.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/processor.rb
similarity index 99%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/processor.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/processor.rb
index a614201facc2a3946da64165aa4dcf42c7f9ad34..764fd66def1d758c6757c44502c151a362b7928b 100644
--- a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/processor.rb
+++ b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/processor.rb
@@ -187,7 +187,7 @@ def process(uow)
           # we didn't properly finish it.
         rescue Sidekiq::JobRetry::Handled => h
           # this is the common case: job raised error and Sidekiq::JobRetry::Handled
-          # signals that we created a retry successfully.  We can acknowlege the job.
+          # signals that we created a retry successfully.  We can acknowledge the job.
           ack = true
           e = h.cause || h
           handle_exception(e, {context: "Job raised exception", job: job_hash})
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/rails.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/rails.rb
similarity index 95%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/rails.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/rails.rb
index 7fde99f5676ea04e3401571c4c39986df8c72fa9..4a3f6244cf6a8df8f296a5cb6a849f76faa2233d 100644
--- a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/rails.rb
+++ b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/rails.rb
@@ -20,6 +20,10 @@ def call
       def inspect
         "#<Sidekiq::Rails::Reloader @app=#{@app.class.name}>"
       end
+
+      def to_hash
+        {app: @app.class.name}
+      end
     end
 
     # By including the Options module, we allow AJs to directly control sidekiq features
@@ -56,10 +60,10 @@ def inspect
         # This is the integration code necessary so that if a job uses `Rails.logger.info "Hello"`,
         # it will appear in the Sidekiq console with all of the job context.
         unless ::Rails.logger == config.logger || ::ActiveSupport::Logger.logger_outputs_to?(::Rails.logger, $stdout)
-          if ::Rails::VERSION::STRING < "7.1"
-            ::Rails.logger.extend(::ActiveSupport::Logger.broadcast(config.logger))
-          else
+          if ::Rails.logger.respond_to?(:broadcast_to)
             ::Rails.logger.broadcast_to(config.logger)
+          else
+            ::Rails.logger.extend(::ActiveSupport::Logger.broadcast(config.logger))
           end
         end
       end
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/redis_client_adapter.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/redis_client_adapter.rb
similarity index 79%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/redis_client_adapter.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/redis_client_adapter.rb
index 74c68d094f6b347e6fd174e8f035d341f89c3431..ea4f35c51ff45e5ea49ff597ebd85eda7019d79c 100644
--- a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/redis_client_adapter.rb
+++ b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/redis_client_adapter.rb
@@ -21,6 +21,22 @@ def evalsha(sha, keys, argv)
         @client.call("EVALSHA", sha, keys.size, *keys, *argv)
       end
 
+      # this is the set of Redis commands used by Sidekiq. Not guaranteed
+      # to be comprehensive, we use this as a performance enhancement to
+      # avoid calling method_missing on most commands
+      USED_COMMANDS = %w[bitfield bitfield_ro del exists expire flushdb
+        get hdel hget hgetall hincrby hlen hmget hset hsetnx incr incrby
+        lindex llen lmove lpop lpush lrange lrem mget mset ping pttl
+        publish rpop rpush sadd scard script set sismember smembers
+        srem ttl type unlink zadd zcard zincrby zrange zrem
+        zremrangebyrank zremrangebyscore]
+
+      USED_COMMANDS.each do |name|
+        define_method(name) do |*args, **kwargs|
+          @client.call(name, *args, **kwargs)
+        end
+      end
+
       private
 
       # this allows us to use methods like `conn.hmset(...)` instead of having to use
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/redis_connection.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/redis_connection.rb
similarity index 93%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/redis_connection.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/redis_connection.rb
index 56237c5bae73cb965b56a50fcbaab6a52d7cd326..0433324fc0cc4ee31d2e286b544e88c22939a191 100644
--- a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/redis_connection.rb
+++ b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/redis_connection.rb
@@ -39,9 +39,8 @@ def scrub(options)
           uri.password = redacted
           scrubbed_options[:url] = uri.to_s
         end
-        if scrubbed_options[:password]
-          scrubbed_options[:password] = redacted
-        end
+        scrubbed_options[:password] = redacted if scrubbed_options[:password]
+        scrubbed_options[:sentinel_password] = redacted if scrubbed_options[:sentinel_password]
         scrubbed_options[:sentinels]&.each do |sentinel|
           sentinel[:password] = redacted if sentinel[:password]
         end
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/ring_buffer.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/ring_buffer.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/ring_buffer.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/ring_buffer.rb
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/scheduled.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/scheduled.rb
similarity index 99%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/scheduled.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/scheduled.rb
index d217020653506c4db74f22cd5d1a26909f3a1247..f019e6d832ff2c5abb4ed3323c29acba1ca1437d 100644
--- a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/scheduled.rb
+++ b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/scheduled.rb
@@ -144,7 +144,7 @@ def random_poll_interval
         # In the example above, each process should schedule every 10 seconds on average. We special
         # case smaller clusters to add 50% so they would sleep somewhere between 5 and 15 seconds.
         # As we run more processes, the scheduling interval average will approach an even spread
-        # between 0 and poll interval so we don't need this artifical boost.
+        # between 0 and poll interval so we don't need this artificial boost.
         #
         count = process_count
         interval = poll_interval_average(count)
@@ -193,7 +193,7 @@ def process_count
       # should never depend on sidekiq/api.
       def cleanup
         # dont run cleanup more than once per minute
-        return 0 unless redis { |conn| conn.set("process_cleanup", "1", nx: true, ex: 60) }
+        return 0 unless redis { |conn| conn.set("process_cleanup", "1", "NX", "EX", "60") }
 
         count = 0
         redis do |conn|
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/sd_notify.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/sd_notify.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/sd_notify.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/sd_notify.rb
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/systemd.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/systemd.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/systemd.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/systemd.rb
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/testing.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/testing.rb
similarity index 93%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/testing.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/testing.rb
index 3e3efb1c143883c171cf0cd07be7bd3ecbf4bf22..a2e7d7a125cea7aac42971687c0307e8ce5515f3 100644
--- a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/testing.rb
+++ b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/testing.rb
@@ -5,6 +5,7 @@
 
 module Sidekiq
   class Testing
+    class TestModeAlreadySetError < RuntimeError; end
     class << self
       attr_accessor :__global_test_mode
 
@@ -12,8 +13,13 @@ class << self
       # all threads. Calling with a block only affects the current Thread.
       def __set_test_mode(mode)
         if block_given?
+          # Reentrant testing modes will lead to a rat's nest of code which is
+          # hard to reason about. You can set the testing mode once globally and
+          # you can override that global setting once per-thread.
+          raise TestModeAlreadySetError, "Nesting test modes is not supported" if __local_test_mode
+
+          self.__local_test_mode = mode
           begin
-            self.__local_test_mode = mode
             yield
           ensure
             self.__local_test_mode = nil
@@ -106,7 +112,7 @@ module Queues
     # The Queues class is only for testing the fake queue implementation.
     # There are 2 data structures involved in tandem. This is due to the
     # Rspec syntax of change(HardJob.jobs, :size). It keeps a reference
-    # to the array. Because the array was dervied from a filter of the total
+    # to the array. Because the array was derived from a filter of the total
     # jobs enqueued, it appeared as though the array didn't change.
     #
     # To solve this, we'll keep 2 hashes containing the jobs. One with keys based
@@ -272,7 +278,7 @@ def drain
       def perform_one
         raise(EmptyQueueError, "perform_one called with empty job queue") if jobs.empty?
         next_job = jobs.first
-        Queues.delete_for(next_job["jid"], queue, to_s)
+        Queues.delete_for(next_job["jid"], next_job["queue"], to_s)
         process_job(next_job)
       end
 
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/testing/inline.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/testing/inline.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/testing/inline.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/testing/inline.rb
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/transaction_aware_client.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/transaction_aware_client.rb
similarity index 87%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/transaction_aware_client.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/transaction_aware_client.rb
index 28490196508b8591ee30fbb2dda6f8b2341e0265..f12496a78c4ad0b8b2d2af9cade41d5d960a917a 100644
--- a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/transaction_aware_client.rb
+++ b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/transaction_aware_client.rb
@@ -9,7 +9,14 @@ def initialize(pool: nil, config: nil)
       @redis_client = Client.new(pool: pool, config: config)
     end
 
+    def batching?
+      Thread.current[:sidekiq_batch]
+    end
+
     def push(item)
+      # 6160 we can't support both Sidekiq::Batch and transactions.
+      return @redis_client.push(item) if batching?
+
       # pre-allocate the JID so we can return it immediately and
       # save it to the database as part of the transaction.
       item["jid"] ||= SecureRandom.hex(12)
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/version.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/version.rb
similarity index 75%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/version.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/version.rb
index e8c7e6fc74f3436246460add36bc8adc58fce864..e93ed589d7e1ca0d33f975e26b54143a1eb07567 100644
--- a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/version.rb
+++ b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/version.rb
@@ -1,6 +1,6 @@
 # frozen_string_literal: true
 
 module Sidekiq
-  VERSION = "7.1.6"
+  VERSION = "7.2.4"
   MAJOR = 7
 end
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/web.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/web.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/web.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/web.rb
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/web/action.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/web/action.rb
similarity index 94%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/web/action.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/web/action.rb
index 4a28558a22764336f308c0e8d39aee58ac6261f1..05dc4a88e2366d52410170e5be36584c27be0985 100644
--- a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/web/action.rb
+++ b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/web/action.rb
@@ -22,6 +22,11 @@ def redirect(location)
       throw :halt, [302, {Web::LOCATION => "#{request.base_url}#{location}"}, []]
     end
 
+    def reload_page
+      current_location = request.referer.gsub(request.base_url, "")
+      redirect current_location
+    end
+
     def params
       indifferent_hash = Hash.new { |hash, key| hash[key.to_s] if Symbol === key }
 
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/web/application.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/web/application.rb
similarity index 92%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/web/application.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/web/application.rb
index 714a38a36d7cdef892b539c980adcfe5d5bbc0df..7d925164d958f893db744f1247fcd7e3822e26d5 100644
--- a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/web/application.rb
+++ b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/web/application.rb
@@ -15,7 +15,7 @@ class WebApplication
       "manifest-src 'self'",
       "media-src 'self'",
       "object-src 'none'",
-      "script-src 'self' https: http: 'unsafe-inline'",
+      "script-src 'self' https: http:",
       "style-src 'self' https: http: 'unsafe-inline'",
       "worker-src 'self'",
       "base-uri 'self'"
@@ -49,9 +49,9 @@ def self.set(key, val)
 
     head "/" do
       # HEAD / is the cheapest heartbeat possible,
-      # it hits Redis to ensure connectivity
-      Sidekiq.redis { |c| c.llen("queue:default") }
-      ""
+      # it hits Redis to ensure connectivity and returns
+      # the size of the default queue
+      Sidekiq.redis { |c| c.llen("queue:default") }.to_s
     end
 
     get "/" do
@@ -330,6 +330,22 @@ def self.set(key, val)
 
     ########
     # Filtering
+
+    get "/filter/metrics" do
+      redirect "#{root_path}metrics"
+    end
+
+    post "/filter/metrics" do
+      x = params[:substr]
+      q = Sidekiq::Metrics::Query.new
+      @period = h((params[:period] || "")[0..1])
+      @periods = METRICS_PERIODS
+      minutes = @periods.fetch(@period, @periods.values.first)
+      @query_result = q.top_jobs(minutes: minutes, class_filter: Regexp.new(Regexp.escape(x), Regexp::IGNORECASE))
+
+      erb :metrics
+    end
+
     get "/filter/retries" do
       x = params[:substr]
       return redirect "#{root_path}retries" unless x && x != ""
@@ -378,6 +394,18 @@ def self.set(key, val)
       erb :morgue
     end
 
+    post "/change_locale" do
+      locale = params["locale"]
+
+      match = available_locales.find { |available|
+        locale == available
+      }
+
+      session[:locale] = match if match
+
+      reload_page
+    end
+
     def call(env)
       action = self.class.match(env)
       return [404, {Rack::CONTENT_TYPE => "text/plain", Web::X_CASCADE => "pass"}, ["Not Found"]] unless action
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/web/csrf_protection.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/web/csrf_protection.rb
similarity index 94%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/web/csrf_protection.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/web/csrf_protection.rb
index 87e33215fd6d2afdfd857d54de25e33cb44cee85..a8dfa3e312885737fdf4ee9ae5b623cfc1ab7409 100644
--- a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/web/csrf_protection.rb
+++ b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/web/csrf_protection.rb
@@ -27,7 +27,6 @@
 # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 require "securerandom"
-require "base64"
 require "rack/request"
 
 module Sidekiq
@@ -57,7 +56,7 @@ def safe?(env)
       end
 
       def logger(env)
-        @logger ||= (env["rack.logger"] || ::Logger.new(env["rack.errors"]))
+        @logger ||= env["rack.logger"] || ::Logger.new(env["rack.errors"])
       end
 
       def deny(env)
@@ -116,7 +115,7 @@ def valid_token?(env, giventoken)
         sess = session(env)
         localtoken = sess[:csrf]
 
-        # Checks that Rack::Session::Cookie actualy contains the csrf toekn
+        # Checks that Rack::Session::Cookie actually contains the csrf token
         return false if localtoken.nil?
 
         # Rotate the session token after every use
@@ -143,7 +142,7 @@ def mask_token(token)
         one_time_pad = SecureRandom.random_bytes(token.length)
         encrypted_token = xor_byte_strings(one_time_pad, token)
         masked_token = one_time_pad + encrypted_token
-        Base64.urlsafe_encode64(masked_token)
+        encode_token(masked_token)
       end
 
       # Essentially the inverse of +mask_token+.
@@ -168,8 +167,12 @@ def compare_with_real_token(token, local)
         ::Rack::Utils.secure_compare(token.to_s, decode_token(local).to_s)
       end
 
+      def encode_token(token)
+        [token].pack("m0").tr("+/", "-_")
+      end
+
       def decode_token(token)
-        Base64.urlsafe_decode64(token)
+        token.tr("-_", "+/").unpack1("m0")
       end
 
       def xor_byte_strings(s1, s2)
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/web/helpers.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/web/helpers.rb
similarity index 93%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/web/helpers.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/web/helpers.rb
index 38c73cc3d80f38ae3f9a0b3d61bcbf301efa4546..b7626500ea2e6b6e9febd74378925cae4215bda2 100644
--- a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/web/helpers.rb
+++ b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/web/helpers.rb
@@ -21,6 +21,10 @@ def strings(lang)
       end
     end
 
+    def to_json(x)
+      Sidekiq.dump_json(x)
+    end
+
     def singularize(str, count)
       if count == 1 && str.respond_to?(:singularize) # rails
         str.singularize
@@ -117,6 +121,10 @@ def user_preferred_languages
     #
     # Inspiration taken from https://github.com/iain/http_accept_language/blob/master/lib/http_accept_language/parser.rb
     def locale
+      # session[:locale] is set via the locale selector from the footer
+      # defined?(session) && session are used to avoid exceptions when running tests
+      return session[:locale] if defined?(session) && session&.[](:locale)
+
       @locale ||= begin
         matched_locale = user_preferred_languages.map { |preferred|
           preferred_language = preferred.split("-", 2).first
@@ -292,23 +300,13 @@ def format_memory(rss_kb)
       elsif rss_kb < 10_000_000
         "#{number_with_delimiter((rss_kb / 1024.0).to_i)} MB"
       else
-        "#{number_with_delimiter((rss_kb / (1024.0 * 1024.0)).round(1))} GB"
+        "#{number_with_delimiter((rss_kb / (1024.0 * 1024.0)), precision: 1)} GB"
       end
     end
 
-    def number_with_delimiter(number)
-      return "" if number.nil?
-
-      begin
-        Float(number)
-      rescue ArgumentError, TypeError
-        return number
-      end
-
-      options = {delimiter: ",", separator: "."}
-      parts = number.to_s.to_str.split(".")
-      parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{options[:delimiter]}")
-      parts.join(options[:separator])
+    def number_with_delimiter(number, options = {})
+      precision = options[:precision] || 0
+      %(<span data-nwp="#{precision}">#{number.round(precision)}</span>)
     end
 
     def h(text)
@@ -346,7 +344,8 @@ def server_utc_time
     end
 
     def pollable?
-      !(current_path == "" || current_path.start_with?("metrics"))
+      # there's no point to refreshing the metrics pages every N seconds
+      !(current_path == "" || current_path.index("metrics"))
     end
 
     def retry_or_delete_or_kill(job, params)
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/web/router.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/web/router.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/web/router.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/web/router.rb
diff --git a/vendor/gems/sidekiq-7.1.6/lib/sidekiq/worker_compatibility_alias.rb b/vendor/gems/sidekiq-7.2.4/lib/sidekiq/worker_compatibility_alias.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/lib/sidekiq/worker_compatibility_alias.rb
rename to vendor/gems/sidekiq-7.2.4/lib/sidekiq/worker_compatibility_alias.rb
diff --git a/vendor/gems/sidekiq-7.1.6/sidekiq.gemspec b/vendor/gems/sidekiq-7.2.4/sidekiq.gemspec
similarity index 98%
rename from vendor/gems/sidekiq-7.1.6/sidekiq.gemspec
rename to vendor/gems/sidekiq-7.2.4/sidekiq.gemspec
index 4d4f963b3f42bacc7eebe7dc0667f6d9c3a008c4..a12554218f647af974c502e239b1f041a2a8b94e 100644
--- a/vendor/gems/sidekiq-7.1.6/sidekiq.gemspec
+++ b/vendor/gems/sidekiq-7.2.4/sidekiq.gemspec
@@ -14,6 +14,7 @@ Gem::Specification.new do |gem|
     README.md
     Changes.md
     LICENSE.txt
+    bin/multi_queue_bench
     bin/sidekiq
     bin/sidekiqload
     bin/sidekiqmon
@@ -134,7 +135,6 @@ Gem::Specification.new do |gem|
     web/views/scheduled.erb
     web/views/scheduled_job_info.erb
   ]
-
   gem.name = "sidekiq"
   gem.version = Sidekiq::VERSION
   gem.required_ruby_version = ">= 2.7.0"
@@ -148,7 +148,7 @@ Gem::Specification.new do |gem|
     "rubygems_mfa_required" => "true"
   }
 
-  gem.add_dependency "redis-client", ">= 0.14.0"
+  gem.add_dependency "redis-client", ">= 0.19.0"
   gem.add_dependency "connection_pool", ">= 2.3.0"
   gem.add_dependency "rack", ">= 2.2.4"
   gem.add_dependency "concurrent-ruby", "< 2"
diff --git a/vendor/gems/sidekiq-7.1.6/test/actors_test.rb b/vendor/gems/sidekiq-7.2.4/test/actors_test.rb
similarity index 98%
rename from vendor/gems/sidekiq-7.1.6/test/actors_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/actors_test.rb
index f8845d818a02e0651b08884411eb44953d49c2f4..3565dab74ca33f77093004945e1ebae5080e54da 100644
--- a/vendor/gems/sidekiq-7.1.6/test/actors_test.rb
+++ b/vendor/gems/sidekiq-7.2.4/test/actors_test.rb
@@ -73,7 +73,7 @@ def await(timeout = 0.5)
     it "can stop" do
       f = Sidekiq::Processor.new(@cap) { |p, ex| raise "should not raise!" }
       f.terminate
-      assert_nil f.thread # didnt start it
+      assert_nil f.thread # didn't start it
     end
 
     it "deals with errors" do
diff --git a/vendor/gems/sidekiq-7.1.6/test/api_test.rb b/vendor/gems/sidekiq-7.2.4/test/api_test.rb
similarity index 95%
rename from vendor/gems/sidekiq-7.1.6/test/api_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/api_test.rb
index 015bce955c90e7c8a2e1567c1b64f5b2af124028..a0acd8549fdc3a8a669fd05b4e3953a3217d417d 100644
--- a/vendor/gems/sidekiq-7.1.6/test/api_test.rb
+++ b/vendor/gems/sidekiq-7.2.4/test/api_test.rb
@@ -266,7 +266,7 @@ class JobWithTags
 
     it "enumerates jobs in descending score order" do
       # We need to enqueue more than 50 items, which is the page size when retrieving
-      # from Redis to ensure everything is sorted: the pages and the items withing them.
+      # from Redis to ensure everything is sorted: the pages and the items within them.
       51.times { ApiJob.perform_in(100, 1, "foo") }
 
       set = Sidekiq::ScheduledSet.new.to_a
@@ -634,12 +634,19 @@ class JobWithTags
         c.hset(s, "1234", data)
       end
 
-      w.each do |p, x, y|
+      w.each do |p, x, work|
         assert_equal key, p
         assert_equal "1234", x
-        assert_equal "default", y["queue"]
-        assert_equal("{}", y["payload"])
-        assert_equal Time.now.year, Time.at(y["run_at"]).year
+        assert_equal "default", work["queue"]
+        assert_equal("{}", work["payload"])
+        assert_equal Time.now.year, Time.at(work["run_at"]).year
+
+        assert_equal "{}", work.payload
+        assert_equal({}, work.job.item)
+        assert_equal(Time.now.year, work.run_at.year)
+        assert_equal "default", work.queue
+        assert_equal "1234", work.thread_id
+        assert_equal key, work.process_id
       end
 
       s = "#{key}:work"
@@ -654,6 +661,27 @@ class JobWithTags
       assert_equal ["5678", "1234"], w.map { |_, tid, _| tid }
     end
 
+    it "can find a work by jid" do
+      w = Sidekiq::Workers.new
+      hn = Socket.gethostname
+      key = "#{hn}:#{$$}"
+      @cfg.redis do |conn|
+        conn.sadd("processes", [key])
+      end
+
+      s = "#{key}:work"
+      jid = "abcdef"
+      data = Sidekiq.dump_json({"payload" => {"args" => ["foo"], "jid" => jid}, "queue" => "default", "run_at" => Time.now.to_i})
+      @cfg.redis do |c|
+        c.hset(s, "1234", data)
+      end
+
+      assert_nil w.find_work_by_jid("nonexistent")
+
+      work = w.find_work_by_jid(jid)
+      assert_equal ["foo"], work.job.args
+    end
+
     it "can reschedule jobs" do
       add_retry("foo1")
       add_retry("foo2")
diff --git a/vendor/gems/sidekiq-7.1.6/test/capsule_test.rb b/vendor/gems/sidekiq-7.2.4/test/capsule_test.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/capsule_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/capsule_test.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/cfg/config__FILE__and__dir__.yml b/vendor/gems/sidekiq-7.2.4/test/cfg/config__FILE__and__dir__.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/cfg/config__FILE__and__dir__.yml
rename to vendor/gems/sidekiq-7.2.4/test/cfg/config__FILE__and__dir__.yml
diff --git a/vendor/gems/sidekiq-7.1.6/test/cfg/config_capsules.yml b/vendor/gems/sidekiq-7.2.4/test/cfg/config_capsules.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/cfg/config_capsules.yml
rename to vendor/gems/sidekiq-7.2.4/test/cfg/config_capsules.yml
diff --git a/vendor/gems/sidekiq-7.1.6/test/cfg/config_empty.yml b/vendor/gems/sidekiq-7.2.4/test/cfg/config_empty.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/cfg/config_empty.yml
rename to vendor/gems/sidekiq-7.2.4/test/cfg/config_empty.yml
diff --git a/vendor/gems/sidekiq-7.1.6/test/cfg/config_environment.yml b/vendor/gems/sidekiq-7.2.4/test/cfg/config_environment.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/cfg/config_environment.yml
rename to vendor/gems/sidekiq-7.2.4/test/cfg/config_environment.yml
diff --git a/vendor/gems/sidekiq-7.1.6/test/cfg/config_queues_without_weights.yml b/vendor/gems/sidekiq-7.2.4/test/cfg/config_queues_without_weights.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/cfg/config_queues_without_weights.yml
rename to vendor/gems/sidekiq-7.2.4/test/cfg/config_queues_without_weights.yml
diff --git a/vendor/gems/sidekiq-7.1.6/test/cfg/config_string.yml b/vendor/gems/sidekiq-7.2.4/test/cfg/config_string.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/cfg/config_string.yml
rename to vendor/gems/sidekiq-7.2.4/test/cfg/config_string.yml
diff --git a/vendor/gems/sidekiq-7.1.6/test/cfg/config_with_alias.yml b/vendor/gems/sidekiq-7.2.4/test/cfg/config_with_alias.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/cfg/config_with_alias.yml
rename to vendor/gems/sidekiq-7.2.4/test/cfg/config_with_alias.yml
diff --git a/vendor/gems/sidekiq-7.1.6/test/cfg/config_with_internal_options.yml b/vendor/gems/sidekiq-7.2.4/test/cfg/config_with_internal_options.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/cfg/config_with_internal_options.yml
rename to vendor/gems/sidekiq-7.2.4/test/cfg/config_with_internal_options.yml
diff --git a/vendor/gems/sidekiq-7.1.6/test/cli_test.rb b/vendor/gems/sidekiq-7.2.4/test/cli_test.rb
similarity index 98%
rename from vendor/gems/sidekiq-7.1.6/test/cli_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/cli_test.rb
index cac3c1b472dff9e28c8c6759e7f9802bc8c7d22c..e6ca4ab0d9d97b51faf8434f1dfbd7d1cbdc51c2 100644
--- a/vendor/gems/sidekiq-7.1.6/test/cli_test.rb
+++ b/vendor/gems/sidekiq-7.2.4/test/cli_test.rb
@@ -225,7 +225,7 @@ def capsules
 
       describe "default config file" do
         describe "when required path is a directory" do
-          it "tries config/sidekiq.yml from required diretory" do
+          it "tries config/sidekiq.yml from required directory" do
             @cli.parse(%w[sidekiq -r ./test/dummy])
 
             assert_equal "./test/dummy/config/sidekiq.yml", config[:config_file]
@@ -234,7 +234,7 @@ def capsules
         end
 
         describe "when required path is a file" do
-          it "tries config/sidekiq.yml from current diretory" do
+          it "tries config/sidekiq.yml from current directory" do
             config[:require] = "./test/dummy" # stub current dir – ./
 
             @cli.parse(%w[sidekiq -r ./test/fake_env.rb])
@@ -245,7 +245,7 @@ def capsules
         end
 
         describe "without any required path" do
-          it "tries config/sidekiq.yml from current diretory" do
+          it "tries config/sidekiq.yml from current directory" do
             config[:require] = "./test/dummy" # stub current dir – ./
 
             @cli.parse(%w[sidekiq])
diff --git a/vendor/gems/sidekiq-7.1.6/test/client_test.rb b/vendor/gems/sidekiq-7.2.4/test/client_test.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/client_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/client_test.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/config.yml b/vendor/gems/sidekiq-7.2.4/test/config.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/config.yml
rename to vendor/gems/sidekiq-7.2.4/test/config.yml
diff --git a/vendor/gems/sidekiq-7.1.6/test/config_test.rb b/vendor/gems/sidekiq-7.2.4/test/config_test.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/config_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/config_test.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/csrf_test.rb b/vendor/gems/sidekiq-7.2.4/test/csrf_test.rb
similarity index 95%
rename from vendor/gems/sidekiq-7.1.6/test/csrf_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/csrf_test.rb
index 993270f0ae4a6f41ababd225c85d6fbd66293443..a47330d2d96952fdd54a5b80841241b6781d1859 100644
--- a/vendor/gems/sidekiq-7.1.6/test/csrf_test.rb
+++ b/vendor/gems/sidekiq-7.2.4/test/csrf_test.rb
@@ -50,7 +50,7 @@ def call(env, &block)
 
   it "bad post" do
     result = call(env(:post)) do
-      raise "Shouldnt be called"
+      raise "Shouldn't be called"
     end
     refute_nil result
     assert_equal 403, result[0]
@@ -79,7 +79,7 @@ def call(env, &block)
   it "fails with bad token" do
     # Make a POST with a known bad token
     result = call(env(:post, "authenticity_token" => "N0QRBD34tU61d7fi+0ZaF/35JLW/9K+8kk8dc1TZoK/0pTl7GIHap5gy7BWGsoKlzbMLRp1yaDpCDFwTJtxWAg==")) do
-      raise "shouldnt be called"
+      raise "shouldn't be called"
     end
     refute_nil result
     assert_equal 403, result[0]
@@ -95,7 +95,7 @@ def call(env, &block)
 
     # Make a POST with an empty session data and good token
     result = call(env(:post, {"authenticity_token" => goodtoken}, {})) do
-      raise "shouldnt be called"
+      raise "shouldn't be called"
     end
     refute_nil result
     assert_equal 403, result[0]
@@ -111,7 +111,7 @@ def call(env, &block)
 
     # Make a POST without csrf session data and good token
     result = call(env(:post, {"authenticity_token" => goodtoken}, {"session_id" => "foo"})) do
-      raise "shouldnt be called"
+      raise "shouldn't be called"
     end
     refute_nil result
     assert_equal 403, result[0]
diff --git a/vendor/gems/sidekiq-7.1.6/test/current_attributes_test.rb b/vendor/gems/sidekiq-7.2.4/test/current_attributes_test.rb
similarity index 95%
rename from vendor/gems/sidekiq-7.1.6/test/current_attributes_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/current_attributes_test.rb
index f53517e12a656402bbc0c5af374097aa8480eecd..dab008cb0e2971f4de1ac6b3e89d07655f44a7e6 100644
--- a/vendor/gems/sidekiq-7.1.6/test/current_attributes_test.rb
+++ b/vendor/gems/sidekiq-7.2.4/test/current_attributes_test.rb
@@ -57,7 +57,7 @@ class OtherCurrent < ActiveSupport::CurrentAttributes
       assert_equal 123, Myapp::Current.user_id
       assert_equal 456, Myapp::OtherCurrent.other_id
     end
-    # the Rails reloader is responsible for reseting Current after every unit of work
+    # the Rails reloader is responsible for resetting Current after every unit of work
   end
 
   it "persists with class argument" do
@@ -98,7 +98,7 @@ class OtherCurrent < ActiveSupport::CurrentAttributes
 
   def with_context(strklass, attr, value)
     constklass = strklass.constantize
-    constklass.send("#{attr}=", value)
+    constklass.send(:"#{attr}=", value)
     yield
   ensure
     constklass.reset_all
diff --git a/vendor/gems/sidekiq-7.1.6/test/dead_set_test.rb b/vendor/gems/sidekiq-7.2.4/test/dead_set_test.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/dead_set_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/dead_set_test.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/dummy/config/application.rb b/vendor/gems/sidekiq-7.2.4/test/dummy/config/application.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/dummy/config/application.rb
rename to vendor/gems/sidekiq-7.2.4/test/dummy/config/application.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/dummy/config/database.yml b/vendor/gems/sidekiq-7.2.4/test/dummy/config/database.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/dummy/config/database.yml
rename to vendor/gems/sidekiq-7.2.4/test/dummy/config/database.yml
diff --git a/vendor/gems/sidekiq-7.1.6/test/dummy/config/environment.rb b/vendor/gems/sidekiq-7.2.4/test/dummy/config/environment.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/dummy/config/environment.rb
rename to vendor/gems/sidekiq-7.2.4/test/dummy/config/environment.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/dummy/config/sidekiq.yml b/vendor/gems/sidekiq-7.2.4/test/dummy/config/sidekiq.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/dummy/config/sidekiq.yml
rename to vendor/gems/sidekiq-7.2.4/test/dummy/config/sidekiq.yml
diff --git a/vendor/gems/sidekiq-7.1.6/test/dummy/tmp/.keep b/vendor/gems/sidekiq-7.2.4/test/dummy/tmp/.keep
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/dummy/tmp/.keep
rename to vendor/gems/sidekiq-7.2.4/test/dummy/tmp/.keep
diff --git a/vendor/gems/sidekiq-7.1.6/test/dummy/tmp/development_secret.txt b/vendor/gems/sidekiq-7.2.4/test/dummy/tmp/development_secret.txt
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/dummy/tmp/development_secret.txt
rename to vendor/gems/sidekiq-7.2.4/test/dummy/tmp/development_secret.txt
diff --git a/vendor/gems/sidekiq-7.2.4/test/dummy/tmp/local_secret.txt b/vendor/gems/sidekiq-7.2.4/test/dummy/tmp/local_secret.txt
new file mode 100644
index 0000000000000000000000000000000000000000..86cbf6b51c649ff4e280638b5cf2eb14327e51b8
--- /dev/null
+++ b/vendor/gems/sidekiq-7.2.4/test/dummy/tmp/local_secret.txt
@@ -0,0 +1 @@
+b2154651ec61ed57e212aad4fdde9c219be60b56ec99cc0c1f300908cb6c93dc3164f1db12851359d03420cc679b4f1431d76ff8191dfd0b0019a5717ad1eb86
\ No newline at end of file
diff --git a/vendor/gems/sidekiq-7.2.4/test/exception_handler_test.rb b/vendor/gems/sidekiq-7.2.4/test/exception_handler_test.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2801366280a5cacb368d27cdf37fe4bdf03b2493
--- /dev/null
+++ b/vendor/gems/sidekiq-7.2.4/test/exception_handler_test.rb
@@ -0,0 +1,141 @@
+# frozen_string_literal: true
+
+require_relative "helper"
+require "sidekiq/component"
+require "sidekiq/rails"
+require "stringio"
+require "logger"
+
+ExceptionHandlerTestException = Class.new(StandardError)
+TEST_EXCEPTION = ExceptionHandlerTestException.new("Something didn't work!")
+
+class Thing
+  include Sidekiq::Component
+  attr_reader :config
+
+  def initialize(config)
+    @config = config
+  end
+
+  def invoke_exception(args)
+    raise TEST_EXCEPTION
+  rescue ExceptionHandlerTestException => e
+    handle_exception(e, args)
+  end
+end
+
+class ClassyErrorHandler1
+  def call(x, y)
+    raise SystemStackError
+  end
+end
+
+class ClassyErrorHandler2
+  def call(x, y, z)
+    raise SystemStackError
+  end
+end
+
+class ClassyErrorHandler3
+  def call(x, y, z = nil)
+    raise SystemStackError
+  end
+end
+
+CLASSY_ERROR_HANDLER1 = ClassyErrorHandler1.new
+CLASSY_ERROR_HANDLER2 = ClassyErrorHandler2.new
+CLASSY_ERROR_HANDLER3 = ClassyErrorHandler3.new
+
+LAMBDA_ERROR_HANDLER1 = ->(_ex, _ctx) { raise SystemStackError }
+LAMBDA_ERROR_HANDLER2 = ->(_ex, _ctx, _cfg) { raise SystemStackError }
+LAMBDA_ERROR_HANDLER3 = ->(_ex, _ctx, _cfg = nil) { raise SystemStackError }
+
+PROC_ERROR_HANDLER1 = proc { |_ex, _ctx| raise SystemStackError }
+PROC_ERROR_HANDLER2 = proc { |_ex, _ctx, _cfg| raise SystemStackError }
+PROC_ERROR_HANDLER3 = proc { |_ex, _ctx, _cfg = nil| raise SystemStackError }
+
+VALID_ERROR_HANDLERS = %w[
+  CLASSY_ERROR_HANDLER2
+  CLASSY_ERROR_HANDLER3
+  LAMBDA_ERROR_HANDLER2
+  LAMBDA_ERROR_HANDLER3
+  PROC_ERROR_HANDLER2
+  PROC_ERROR_HANDLER3
+]
+DEPRECATED_ERROR_HANDLERS = %w[
+  CLASSY_ERROR_HANDLER1
+  LAMBDA_ERROR_HANDLER1
+  PROC_ERROR_HANDLER1
+]
+
+describe Sidekiq::Component do
+  describe "with mock logger" do
+    before do
+      @config = reset!
+    end
+
+    it "logs the exception to Sidekiq.logger" do
+      @config[:reloader] = Sidekiq::Rails::Reloader.new
+      output = capture_logging(@config) do
+        Thing.new(@config).invoke_exception(a: 1)
+      end
+      assert_match(/"a":1/, output, "didn't include the context")
+      assert_match(/Something didn't work!/, output, "didn't include the exception message")
+      assert_match(/test\/exception_handler_test.rb/, output, "didn't include the backtrace")
+    end
+
+    VALID_ERROR_HANDLERS.each do |handler_name|
+      it "handles exceptions in #{handler_name} without DEPRECATION" do
+        test_handler = self.class.const_get(handler_name)
+        @config[:error_handlers] << test_handler
+        output = capture_logging(@config) do
+          Thing.new(@config).invoke_exception(a: 1)
+        end
+
+        refute_match(/DEPRECATION/, output, "didn't include the deprecation warning")
+        assert_match(/SystemStackError/, output, "didn't include the exception")
+        assert_match(/Something didn't work!/, output, "didn't include the exception message")
+        assert_match(/!!! ERROR HANDLER THREW AN ERROR !!!/, output, "didn't include error handler problem message")
+      ensure
+        @config[:error_handlers].delete(test_handler)
+      end
+    end
+
+    DEPRECATED_ERROR_HANDLERS.each do |handler_name|
+      it "handles exceptions in #{handler_name} with DEPRECATION" do
+        test_handler = self.class.const_get(handler_name)
+        @config[:error_handlers] << test_handler
+        output = capture_logging(@config) do
+          Thing.new(@config).invoke_exception(a: 1)
+        end
+
+        assert_match(/DEPRECATION/, output, "didn't include the deprecation warning")
+        assert_match(/SystemStackError/, output, "didn't include the exception")
+        assert_match(/Something didn't work!/, output, "didn't include the exception message")
+        assert_match(/!!! ERROR HANDLER THREW AN ERROR !!!/, output, "didn't include error handler problem message")
+      ensure
+        @config[:error_handlers].delete(test_handler)
+      end
+    end
+
+    it "cleans a backtrace if there is a cleaner" do
+      @config[:backtrace_cleaner] = ->(backtrace) { backtrace.take(1) }
+      output = capture_logging(@config) do
+        Thing.new(@config).invoke_exception(a: 1)
+      end
+
+      assert_equal 1, output.lines.count { |line| line.match?(/\d+:in/) }
+    ensure
+      @config[:backtrace_cleaner] = Sidekiq::Config::DEFAULTS[:backtrace_cleaner]
+    end
+
+    describe "when the exception does not have a backtrace" do
+      it "does not fail" do
+        exception = ExceptionHandlerTestException.new
+        assert_nil exception.backtrace
+
+        Thing.new(@config).handle_exception exception
+      end
+    end
+  end
+end
diff --git a/vendor/gems/sidekiq-7.1.6/test/fake_env.rb b/vendor/gems/sidekiq-7.2.4/test/fake_env.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/fake_env.rb
rename to vendor/gems/sidekiq-7.2.4/test/fake_env.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/fetch_test.rb b/vendor/gems/sidekiq-7.2.4/test/fetch_test.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/fetch_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/fetch_test.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/filtering_test.rb b/vendor/gems/sidekiq-7.2.4/test/filtering_test.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/filtering_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/filtering_test.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/fixtures/en.yml b/vendor/gems/sidekiq-7.2.4/test/fixtures/en.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/fixtures/en.yml
rename to vendor/gems/sidekiq-7.2.4/test/fixtures/en.yml
diff --git a/vendor/gems/sidekiq-7.1.6/test/helper.rb b/vendor/gems/sidekiq-7.2.4/test/helper.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/helper.rb
rename to vendor/gems/sidekiq-7.2.4/test/helper.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/job_generator_test.rb b/vendor/gems/sidekiq-7.2.4/test/job_generator_test.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/job_generator_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/job_generator_test.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/job_logger_test.rb b/vendor/gems/sidekiq-7.2.4/test/job_logger_test.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/job_logger_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/job_logger_test.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/job_test.rb b/vendor/gems/sidekiq-7.2.4/test/job_test.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/job_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/job_test.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/launcher_test.rb b/vendor/gems/sidekiq-7.2.4/test/launcher_test.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/launcher_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/launcher_test.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/logger_test.rb b/vendor/gems/sidekiq-7.2.4/test/logger_test.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/logger_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/logger_test.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/manager_test.rb b/vendor/gems/sidekiq-7.2.4/test/manager_test.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/manager_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/manager_test.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/metrics_test.rb b/vendor/gems/sidekiq-7.2.4/test/metrics_test.rb
similarity index 89%
rename from vendor/gems/sidekiq-7.1.6/test/metrics_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/metrics_test.rb
index 1926801655278c0b0d5d73729749698251075efd..78fce29b14ae0255f814e14441c19e506bf7a716 100644
--- a/vendor/gems/sidekiq-7.1.6/test/metrics_test.rb
+++ b/vendor/gems/sidekiq-7.2.4/test/metrics_test.rb
@@ -102,6 +102,23 @@ def create_known_metrics(time = fixed_time)
       assert_equal(["DoesntExist"], result.job_results.keys)
     end
 
+    it "filters top job data" do
+      create_known_metrics
+
+      q = Sidekiq::Metrics::Query.new(now: fixed_time)
+      result = q.top_jobs(class_filter: /some/i)
+      assert_equal fixed_time - 59 * 60, result.starts_at
+      assert_equal fixed_time, result.ends_at
+
+      assert_equal 60, result.buckets.size
+      assert_equal "21:04", result.buckets.first
+      assert_equal "22:03", result.buckets.last
+
+      assert_equal %w[App::SomeJob].sort, result.job_results.keys.sort
+      job_result = result.job_results["App::SomeJob"]
+      refute_nil job_result
+    end
+
     it "fetches top job data" do
       create_known_metrics
       d = Sidekiq::Deploy.new
@@ -127,8 +144,8 @@ def create_known_metrics(time = fixed_time)
       assert_equal 2, job_result.series.dig("p", "22:03")
       assert_equal 3, job_result.totals["p"]
       # Execution time is not consistent, so these assertions are not exact
-      assert job_result.total_avg("ms").between?(0.5, 8), job_result.total_avg("ms")
-      assert job_result.series_avg("s")["22:03"].between?(0.0005, 0.008), job_result.series_avg("s")
+      assert job_result.total_avg("ms").between?(0.5, 2), job_result.total_avg("ms")
+      assert job_result.series_avg("s")["22:03"].between?(0.0005, 0.002), job_result.series_avg("s")
     end
 
     it "fetches job-specific data" do
diff --git a/vendor/gems/sidekiq-7.1.6/test/middleware_test.rb b/vendor/gems/sidekiq-7.2.4/test/middleware_test.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/middleware_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/middleware_test.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/processor_test.rb b/vendor/gems/sidekiq-7.2.4/test/processor_test.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/processor_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/processor_test.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/rails_test.rb b/vendor/gems/sidekiq-7.2.4/test/rails_test.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/rails_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/rails_test.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/redis_connection_test.rb b/vendor/gems/sidekiq-7.2.4/test/redis_connection_test.rb
similarity index 98%
rename from vendor/gems/sidekiq-7.1.6/test/redis_connection_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/redis_connection_test.rb
index 81923fb53957be83c946380488042b22a6f335b7..d0cfb3bd835573f15ad955b9266724395755c7de 100644
--- a/vendor/gems/sidekiq-7.1.6/test/redis_connection_test.rb
+++ b/vendor/gems/sidekiq-7.2.4/test/redis_connection_test.rb
@@ -151,6 +151,7 @@ def server_connection(args = {})
         options = {
           role: "master",
           master_name: "mymaster",
+          sentinel_password: "secret",
           sentinels: [
             {host: "host1", port: 26379, password: "secret"},
             {host: "host2", port: 26379, password: "secret"},
@@ -164,6 +165,7 @@ def server_connection(args = {})
         end
 
         refute_includes(options.inspect, "REDACTED")
+        refute_includes(output, "secret")
         assert_includes(output, ':host=>"host1", :port=>26379, :password=>"REDACTED"')
         assert_includes(output, ':host=>"host2", :port=>26379, :password=>"REDACTED"')
         assert_includes(output, ':host=>"host3", :port=>26379, :password=>"REDACTED"')
diff --git a/vendor/gems/sidekiq-7.1.6/test/retry_exhausted_test.rb b/vendor/gems/sidekiq-7.2.4/test/retry_exhausted_test.rb
similarity index 69%
rename from vendor/gems/sidekiq-7.1.6/test/retry_exhausted_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/retry_exhausted_test.rb
index bb005c75d3ccd8ba807f63bfd1fb50f930df1292..c32fbec33dce1f0a89ae9723ab4fe9a8e34ecf6f 100644
--- a/vendor/gems/sidekiq-7.1.6/test/retry_exhausted_test.rb
+++ b/vendor/gems/sidekiq-7.2.4/test/retry_exhausted_test.rb
@@ -25,6 +25,17 @@ class OldJob
   end
 end
 
+class DiscardJob
+  include Sidekiq::Job
+
+  sidekiq_class_attribute :exhausted_called
+
+  sidekiq_retries_exhausted do |job, e|
+    self.exhausted_called = true
+    :discard
+  end
+end
+
 class Foobar
   include Sidekiq::Job
 end
@@ -154,6 +165,66 @@ def job(options = {})
     assert_equal raised_error, exhausted_exception
   end
 
+  it "adds jobs to the dead set" do
+    assert_raises RuntimeError do
+      handler.local(new_worker, job("retry" => 0), "default") do
+        raise "kerblammo!"
+      end
+    end
+
+    assert_equal 1, Sidekiq::DeadSet.new.size
+  end
+
+  it "allows disabling dead set" do
+    assert_raises RuntimeError do
+      handler.local(new_worker, job("retry" => 0, "dead" => false), "default") do
+        raise "kerblammo!"
+      end
+    end
+
+    assert_equal 0, Sidekiq::DeadSet.new.size
+  end
+
+  it "does not allow disabling global failure handlers when disabling dead set" do
+    exhausted_job = nil
+    exhausted_exception = nil
+    @config.death_handlers.clear
+    @config.death_handlers << proc do |job, ex|
+      exhausted_job = job
+      exhausted_exception = ex
+    end
+    assert_raises RuntimeError do
+      handler.local(new_worker, job("retry" => 0, "dead" => false), "default") do
+        raise "kerblammo!"
+      end
+    end
+
+    assert exhausted_job
+    assert exhausted_exception
+  end
+
+  it "supports discard option to disable global failure handlers and dead set" do
+    discard_job = DiscardJob.new
+
+    exhausted_job = nil
+    exhausted_exception = nil
+    @config.death_handlers.clear
+    @config.death_handlers << proc do |job, ex|
+      exhausted_job = job
+      exhausted_exception = ex
+    end
+    assert_raises RuntimeError do
+      handler.local(discard_job, job("retry" => 0), "default") do
+        raise "kerblammo!"
+      end
+    end
+
+    assert DiscardJob.exhausted_called
+    assert_equal 0, Sidekiq::DeadSet.new.size
+    assert_nil exhausted_job
+    assert_nil exhausted_exception
+  end
+
   it "supports wrapped jobs" do
     assert_raises RuntimeError do
       handler.local(WrappedJob.new, job("retry_count" => 0, "retry" => 1, "wrapped" => WrappedJob.to_s), "default") do
diff --git a/vendor/gems/sidekiq-7.1.6/test/retry_test.rb b/vendor/gems/sidekiq-7.2.4/test/retry_test.rb
similarity index 99%
rename from vendor/gems/sidekiq-7.1.6/test/retry_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/retry_test.rb
index a44dc8d699f043ed55899b66759e0612a8ad42fa..41979eda618ba6fe049f9ca1d3fff724d05f50b8 100644
--- a/vendor/gems/sidekiq-7.1.6/test/retry_test.rb
+++ b/vendor/gems/sidekiq-7.2.4/test/retry_test.rb
@@ -423,7 +423,7 @@ def job
       end
     end
 
-    describe "handles errors withouth cause" do
+    describe "handles errors without cause" do
       before do
         @error = nil
         begin
diff --git a/vendor/gems/sidekiq-7.1.6/test/scheduled_test.rb b/vendor/gems/sidekiq-7.2.4/test/scheduled_test.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/scheduled_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/scheduled_test.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/scheduling_test.rb b/vendor/gems/sidekiq-7.2.4/test/scheduling_test.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/scheduling_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/scheduling_test.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/sharding_test.rb b/vendor/gems/sidekiq-7.2.4/test/sharding_test.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/sharding_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/sharding_test.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/sidekiq_test.rb b/vendor/gems/sidekiq-7.2.4/test/sidekiq_test.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/sidekiq_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/sidekiq_test.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/sidekiqmon_test.rb b/vendor/gems/sidekiq-7.2.4/test/sidekiqmon_test.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/sidekiqmon_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/sidekiqmon_test.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/systemd_test.rb b/vendor/gems/sidekiq-7.2.4/test/systemd_test.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/systemd_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/systemd_test.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/testing_fake_test.rb b/vendor/gems/sidekiq-7.2.4/test/testing_fake_test.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/testing_fake_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/testing_fake_test.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/testing_inline_test.rb b/vendor/gems/sidekiq-7.2.4/test/testing_inline_test.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/testing_inline_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/testing_inline_test.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/testing_test.rb b/vendor/gems/sidekiq-7.2.4/test/testing_test.rb
similarity index 90%
rename from vendor/gems/sidekiq-7.1.6/test/testing_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/testing_test.rb
index 0417ee0828ac9c7ee9ec8a50cea5aebd7d7d0864..3d6a15a842353fb4dfe88076af64bd9d933237a1 100644
--- a/vendor/gems/sidekiq-7.1.6/test/testing_test.rb
+++ b/vendor/gems/sidekiq-7.2.4/test/testing_test.rb
@@ -100,6 +100,18 @@ def call(worker, msg, queue)
       refute Sidekiq::Testing.fake?
     end
 
+    it "exception on nested inline testing" do
+      Sidekiq::Testing.inline! do
+        assert Sidekiq::Testing.inline?
+        assert_raises(Sidekiq::Testing::TestModeAlreadySetError) do
+          Sidekiq::Testing.inline! do
+            # Block needed to set local test mode
+          end
+        end
+        assert Sidekiq::Testing.inline?
+      end
+    end
+
     it "enables inline testing in a block" do
       Sidekiq::Testing.disable!
       assert Sidekiq::Testing.disabled?
diff --git a/vendor/gems/sidekiq-7.1.6/test/transaction_aware_client_test.rb b/vendor/gems/sidekiq-7.2.4/test/transaction_aware_client_test.rb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/test/transaction_aware_client_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/transaction_aware_client_test.rb
diff --git a/vendor/gems/sidekiq-7.1.6/test/web_helpers_test.rb b/vendor/gems/sidekiq-7.2.4/test/web_helpers_test.rb
similarity index 93%
rename from vendor/gems/sidekiq-7.1.6/test/web_helpers_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/web_helpers_test.rb
index b90c2c5ea1c6fdc0ca6f92ca86aedb909d25c81a..eeade6a44e5c2ca6328941d8406bde7227ec549e 100644
--- a/vendor/gems/sidekiq-7.1.6/test/web_helpers_test.rb
+++ b/vendor/gems/sidekiq-7.2.4/test/web_helpers_test.rb
@@ -96,6 +96,18 @@ def path_info
     assert_equal "en", obj.locale
   end
 
+  it "tests user selected locale" do
+    obj = Helpers.new("HTTP_ACCEPT_LANGUAGE" => "*")
+
+    obj.instance_eval do
+      def session
+        {locale: "es"}
+      end
+    end
+
+    assert_equal "es", obj.locale
+  end
+
   it "tests available locales" do
     obj = Helpers.new
     expected = %w[
@@ -136,17 +148,17 @@ def params
   describe "#format_memory" do
     it "returns in KB" do
       obj = Helpers.new
-      assert_equal "1 KB", obj.format_memory(1)
+      assert_equal "<span data-nwp=\"0\">1</span> KB", obj.format_memory(1)
     end
 
     it "returns in MB" do
       obj = Helpers.new
-      assert_equal "97 MB", obj.format_memory(100_002)
+      assert_equal "<span data-nwp=\"0\">97</span> MB", obj.format_memory(100_002)
     end
 
     it "returns in GB" do
       obj = Helpers.new
-      assert_equal "9.5 GB", obj.format_memory(10_000_001)
+      assert_equal "<span data-nwp=\"1\">9.5</span> GB", obj.format_memory(10_000_001)
     end
   end
 
diff --git a/vendor/gems/sidekiq-7.1.6/test/web_test.rb b/vendor/gems/sidekiq-7.2.4/test/web_test.rb
similarity index 80%
rename from vendor/gems/sidekiq-7.1.6/test/web_test.rb
rename to vendor/gems/sidekiq-7.2.4/test/web_test.rb
index ad1dbb5af8afff49f4316ad6e04473241572bd93..dc3ad82a18537bb668e11213518859ca32c140c7 100644
--- a/vendor/gems/sidekiq-7.1.6/test/web_test.rb
+++ b/vendor/gems/sidekiq-7.2.4/test/web_test.rb
@@ -20,6 +20,9 @@ def add_pair(job)
 
 describe Sidekiq::Web do
   include Rack::Test::Methods
+  def session_secret
+    "v3rys3cr31v3rys3cr31v3rys3cr31v3rys3cr31v3rys3cr31v3rys3cr31mike!"
+  end
 
   def app
     @app ||= Sidekiq::Web.new
@@ -34,6 +37,12 @@ def job_params(job, score)
     app.middlewares.clear
   end
 
+  it "passes on unexpected methods" do
+    patch "/"
+    assert_equal 404, last_response.status
+    assert_equal "pass", last_response.headers[Sidekiq::Web::X_CASCADE]
+  end
+
   it "can show text with any locales" do
     rackenv = {"HTTP_ACCEPT_LANGUAGE" => "ru,en"}
     get "/", {}, rackenv
@@ -60,10 +69,18 @@ def job_params(job, score)
     policies = last_response.headers["Content-Security-Policy"].split("; ")
     assert_includes(policies, "connect-src 'self' https: http: wss: ws:")
     assert_includes(policies, "style-src 'self' https: http: 'unsafe-inline'")
-    assert_includes(policies, "script-src 'self' https: http: 'unsafe-inline'")
+    assert_includes(policies, "script-src 'self' https: http:")
     assert_includes(policies, "object-src 'none'")
   end
 
+  it "provides a cheap HEAD response" do
+    WebJob.perform_async
+    assert_equal 1, Sidekiq::Queue.new.size
+
+    head "/", {}
+    assert_equal "1", last_response.body.to_s
+  end
+
   describe "busy" do
     it "can display workers" do
       @config.redis do |conn|
@@ -71,7 +88,7 @@ def job_params(job, score)
         conn.sadd("processes", ["foo:1234"])
         conn.hset("foo:1234", "info", Sidekiq.dump_json("hostname" => "foo", "started_at" => Time.now.to_f, "queues" => [], "concurrency" => 10), "at", Time.now.to_f, "busy", 4)
         identity = "foo:1234:work"
-        hash = {queue: "critical", payload: {"class" => WebJob.name, "args" => [1, "abc"]}, run_at: Time.now.to_i}
+        hash = {queue: "critical", payload: Sidekiq.dump_json({"class" => WebJob.name, "args" => [1, "abc"]}), run_at: Time.now.to_i}
         conn.hset(identity, 1001, Sidekiq.dump_json(hash))
       end
       assert_equal ["1001"], Sidekiq::WorkSet.new.map { |pid, tid, data| tid }
@@ -120,19 +137,20 @@ def job_params(job, score)
       end
 
       assert_nil @config.redis { |c| c.lpop signals_key }
-      post "/busy", "stop" => "1", "identity" => identity
+      post "/busy", "stop" => "Stop All", "identity" => identity
+      assert_equal 302, last_response.status
+      assert_equal "TERM", @config.redis { |c| c.lpop signals_key }
+
+      post "/busy", "stop" => "Stop All"
       assert_equal 302, last_response.status
       assert_equal "TERM", @config.redis { |c| c.lpop signals_key }
     end
   end
 
   it "can display queues" do
-    Time.stub(:now, Time.now) do
-      assert Sidekiq::Client.push("queue" => :foo, "class" => WebJob, "args" => [1, 3])
-
-      get "/queues"
-    end
+    assert Sidekiq::Client.push("queue" => :foo, "class" => WebJob, "args" => [1, 3])
 
+    get "/queues"
     assert_equal 200, last_response.status
     assert_match(/foo/, last_response.body)
     refute_match(/HardJob/, last_response.body)
@@ -327,11 +345,42 @@ def job_params(job, score)
     assert_equal 302, last_response.status
   end
 
+  it "can filter retries" do
+    3.times { add_retry }
+    add_retry("MIKE1234")
+
+    get "/filter/retries"
+    assert_equal 302, last_response.status
+
+    post "/filter/retries"
+    assert_equal 302, last_response.status
+
+    post "/filter/retries", substr: "nope"
+    refute_match(/RuntimeError/, last_response.body)
+
+    get "/filter/retries", substr: "nope"
+    refute_match(/RuntimeError/, last_response.body)
+
+    post "/filter/retries", substr: "MIKE1234"
+    assert_match(/MIKE1234/, last_response.body)
+  end
+
+  it "can delete multiple retries" do
+    params = add_retry
+    post "/retries", "key" => [job_params(*params)], "delete" => "Delete"
+    assert_equal 302, last_response.status
+    assert_equal "http://example.org/retries", last_response.headers["Location"]
+
+    get "/retries"
+    assert_equal 200, last_response.status
+    refute_match(/#{params.first["args"][2]}/, last_response.body)
+  end
+
   it "can delete a single retry" do
     params = add_retry
     post "/retries/#{job_params(*params)}", "delete" => "Delete"
     assert_equal 302, last_response.status
-    assert_equal "http://example.org/retries", last_response.header["Location"]
+    assert_equal "http://example.org/retries", last_response.headers["Location"]
 
     get "/retries"
     assert_equal 200, last_response.status
@@ -344,14 +393,24 @@ def job_params(job, score)
     post "/retries/all/delete", "delete" => "Delete"
     assert_equal 0, Sidekiq::RetrySet.new.size
     assert_equal 302, last_response.status
-    assert_equal "http://example.org/retries", last_response.header["Location"]
+    assert_equal "http://example.org/retries", last_response.headers["Location"]
+  end
+
+  it "can kill all retries" do
+    3.times { add_retry }
+
+    post "/retries/all/kill"
+    assert_equal 0, Sidekiq::RetrySet.new.size
+    assert_equal 3, Sidekiq::DeadSet.new.size
+    assert_equal 302, last_response.status
+    assert_equal "http://example.org/retries", last_response.headers["Location"]
   end
 
   it "can retry a single retry now" do
     params = add_retry
     post "/retries/#{job_params(*params)}", "retry" => "Retry"
     assert_equal 302, last_response.status
-    assert_equal "http://example.org/retries", last_response.header["Location"]
+    assert_equal "http://example.org/retries", last_response.headers["Location"]
 
     get "/queues/default"
     assert_equal 200, last_response.status
@@ -362,7 +421,7 @@ def job_params(job, score)
     params = add_retry
     post "/retries/#{job_params(*params)}", "kill" => "Kill"
     assert_equal 302, last_response.status
-    assert_equal "http://example.org/retries", last_response.header["Location"]
+    assert_equal "http://example.org/retries", last_response.headers["Location"]
 
     get "/morgue"
     assert_equal 200, last_response.status
@@ -404,11 +463,31 @@ def job_params(job, score)
     assert_equal 302, last_response.status
   end
 
+  it "can filter scheduled" do
+    3.times { add_scheduled }
+    add_scheduled("MIKE1234")
+
+    get "/filter/scheduled"
+    assert_equal 302, last_response.status
+
+    post "/filter/scheduled"
+    assert_equal 302, last_response.status
+
+    get "/filter/scheduled", substr: "nope"
+    refute_match(/RuntimeError/, last_response.body)
+
+    post "/filter/scheduled", substr: "nope"
+    refute_match(/RuntimeError/, last_response.body)
+
+    post "/filter/scheduled", substr: "MIKE1234"
+    assert_match(/MIKE1234/, last_response.body)
+  end
+
   it "can add to queue a single scheduled job" do
     params = add_scheduled
     post "/scheduled/#{job_params(*params)}", "add_to_queue" => true
     assert_equal 302, last_response.status
-    assert_equal "http://example.org/scheduled", last_response.header["Location"]
+    assert_equal "http://example.org/scheduled", last_response.headers["Location"]
 
     get "/queues/default"
     assert_equal 200, last_response.status
@@ -419,7 +498,7 @@ def job_params(job, score)
     params = add_scheduled
     post "/scheduled/#{job_params(*params)}", "delete" => "Delete"
     assert_equal 302, last_response.status
-    assert_equal "http://example.org/scheduled", last_response.header["Location"]
+    assert_equal "http://example.org/scheduled", last_response.headers["Location"]
 
     get "/scheduled"
     assert_equal 200, last_response.status
@@ -432,7 +511,7 @@ def job_params(job, score)
       assert_equal 1, conn.zcard("schedule")
       post "/scheduled", "key" => [job_params(*params)], "delete" => "Delete"
       assert_equal 302, last_response.status
-      assert_equal "http://example.org/scheduled", last_response.header["Location"]
+      assert_equal "http://example.org/scheduled", last_response.headers["Location"]
       assert_equal 0, conn.zcard("schedule")
     end
   end
@@ -445,7 +524,7 @@ def job_params(job, score)
       assert_equal 0, q.size
       post "/scheduled", "key" => [job_params(*params)], "add_to_queue" => "AddToQueue"
       assert_equal 302, last_response.status
-      assert_equal "http://example.org/scheduled", last_response.header["Location"]
+      assert_equal "http://example.org/scheduled", last_response.headers["Location"]
       assert_equal 0, conn.zcard("schedule")
       assert_equal 1, q.size
       get "/queues/default"
@@ -460,7 +539,7 @@ def job_params(job, score)
 
     post "/retries/all/retry", "retry" => "Retry"
     assert_equal 302, last_response.status
-    assert_equal "http://example.org/retries", last_response.header["Location"]
+    assert_equal "http://example.org/retries", last_response.headers["Location"]
     assert_equal 2, Sidekiq::Queue.new("default").size
 
     get "/queues/default"
@@ -475,10 +554,10 @@ def job_params(job, score)
     assert_equal 200, last_response.status
     assert_match(/FailJob/, last_response.body)
 
-    assert last_response.body.include?("fail message: &lt;a&gt;hello&lt;&#x2F;a&gt;")
+    assert last_response.body.include?("fail message: &lt;a&gt;hello&lt;/a&gt;")
     assert !last_response.body.include?("fail message: <a>hello</a>")
 
-    assert last_response.body.include?("args\">&quot;&lt;a&gt;hello&lt;&#x2F;a&gt;&quot;<")
+    assert last_response.body.include?("args\">&quot;&lt;a&gt;hello&lt;/a&gt;&quot;<")
     assert !last_response.body.include?("args\"><a>hello</a><")
 
     # on /workers page
@@ -487,7 +566,7 @@ def job_params(job, score)
       conn.sadd("processes", [pro])
       conn.hset(pro, "info", Sidekiq.dump_json("started_at" => Time.now.to_f, "labels" => ["frumduz"], "queues" => [], "concurrency" => 10), "busy", 1, "beat", Time.now.to_f)
       identity = "#{pro}:work"
-      hash = {queue: "critical", payload: {"class" => "FailJob", "args" => ["<a>hello</a>"]}, run_at: Time.now.to_i}
+      hash = {queue: "critical", payload: Sidekiq.dump_json({"class" => "FailJob", "args" => ["<a>hello</a>"]}), run_at: Time.now.to_i}
       conn.hset(identity, 100001, Sidekiq.dump_json(hash))
       conn.incr("busy")
     end
@@ -496,7 +575,7 @@ def job_params(job, score)
     assert_equal 200, last_response.status
     assert_match(/FailJob/, last_response.body)
     assert_match(/frumduz/, last_response.body)
-    assert last_response.body.include?("&lt;a&gt;hello&lt;&#x2F;a&gt;")
+    assert last_response.body.include?("&lt;a&gt;hello&lt;/a&gt;")
     assert !last_response.body.include?("<a>hello</a>")
 
     # on /queues page
@@ -506,7 +585,7 @@ def job_params(job, score)
 
     get "/queues/foo"
     assert_equal 200, last_response.status
-    assert last_response.body.include?("&lt;a&gt;hello&lt;&#x2F;a&gt;")
+    assert last_response.body.include?("&lt;a&gt;hello&lt;/a&gt;")
     assert !last_response.body.include?("<a>hello</a>")
   end
 
@@ -524,6 +603,18 @@ def job_params(job, score)
     assert_equal 200, last_response.status
   end
 
+  it "can change the locale" do
+    session_data = {"rack.session" => {}}
+    headers = {"HTTP_REFERER" => "http://example.org/path", "HTTP_BASE_URL" => "http://example.org/"}
+
+    post "/change_locale", {"locale" => "es"}, session_data.merge(headers)
+
+    assert_equal "es", last_request.env["rack.session"][:locale]
+
+    assert_equal 302, last_response.status
+    assert_equal "http://example.org/path", last_response.location
+  end
+
   describe "custom locales" do
     before do
       Sidekiq::Web.settings.locales << File.join(File.dirname(__FILE__), "fixtures")
@@ -550,7 +641,7 @@ def job_params(job, score)
     it "redirects to stats" do
       get "/dashboard/stats"
       assert_equal 302, last_response.status
-      assert_equal "http://example.org/stats", last_response.header["Location"]
+      assert_equal "http://example.org/stats", last_response.headers["Location"]
     end
   end
 
@@ -642,14 +733,57 @@ def job_params(job, score)
       assert_match(/#{score}/, last_response.body)
     end
 
+    it "can delete multiple dead" do
+      params = add_dead
+      post "/morgue", "key" => [job_params(*params)], "delete" => "Delete"
+      assert_equal 302, last_response.status
+      assert_equal "http://example.org/morgue", last_response.headers["Location"]
+
+      get "/morgue"
+      assert_equal 200, last_response.status
+      refute_match(/#{params.first["args"][2]}/, last_response.body)
+    end
+
     it "can delete all dead" do
       3.times { add_dead }
 
       assert_equal 3, Sidekiq::DeadSet.new.size
-      post "/morgue/all/delete", "delete" => "Delete"
+      post "/morgue/all/delete"
+      assert_equal 0, Sidekiq::DeadSet.new.size
+      assert_equal 302, last_response.status
+      assert_equal "http://example.org/morgue", last_response.headers["Location"]
+    end
+
+    it "can filter dead" do
+      3.times { add_dead }
+      add_dead("MIKE1234")
+
+      get "/filter/dead"
+      assert_equal 302, last_response.status
+
+      post "/filter/dead"
+      assert_equal 302, last_response.status
+
+      post "/filter/dead", substr: "nope"
+      refute_match(/RuntimeError/, last_response.body)
+
+      get "/filter/dead", substr: "nope"
+      refute_match(/RuntimeError/, last_response.body)
+
+      post "/filter/dead", substr: "MIKE1234"
+      assert_match(/MIKE1234/, last_response.body)
+    end
+
+    it "can retry all dead" do
+      3.times { add_dead }
+
+      assert_equal 0, Sidekiq::Queue.new("foo").size
+      assert_equal 3, Sidekiq::DeadSet.new.size
+      post "/morgue/all/retry"
       assert_equal 0, Sidekiq::DeadSet.new.size
+      assert_equal 3, Sidekiq::Queue.new("foo").size
       assert_equal 302, last_response.status
-      assert_equal "http://example.org/morgue", last_response.header["Location"]
+      assert_equal "http://example.org/morgue", last_response.headers["Location"]
     end
 
     it "can display a dead job" do
@@ -662,7 +796,7 @@ def job_params(job, score)
       params = add_dead
       post "/morgue/#{job_params(*params)}", "retry" => "Retry"
       assert_equal 302, last_response.status
-      assert_equal "http://example.org/morgue", last_response.header["Location"]
+      assert_equal "http://example.org/morgue", last_response.headers["Location"]
       assert_equal 0, Sidekiq::DeadSet.new.size
 
       params = add_dead("jid-with-hyphen")
@@ -676,11 +810,11 @@ def job_params(job, score)
     end
   end
 
-  def add_scheduled
+  def add_scheduled(jid = SecureRandom.hex(12))
     score = Time.now.to_f
     msg = {"class" => "HardJob",
            "args" => ["bob", 1, Time.now.to_f],
-           "jid" => SecureRandom.hex(12),
+           "jid" => jid,
            "tags" => ["tag1", "tag2"]}
     @config.redis do |conn|
       conn.zadd("schedule", score, Sidekiq.dump_json(msg))
@@ -688,7 +822,7 @@ def add_scheduled
     [msg, score]
   end
 
-  def add_retry
+  def add_retry(jid = SecureRandom.hex(12))
     msg = {"class" => "HardJob",
            "args" => ["bob", 1, Time.now.to_f],
            "queue" => "default",
@@ -696,7 +830,7 @@ def add_retry
            "error_class" => "RuntimeError",
            "retry_count" => 0,
            "failed_at" => Time.now.to_f,
-           "jid" => SecureRandom.hex(12)}
+           "jid" => jid}
     score = Time.now.to_f
     @config.redis do |conn|
       conn.zadd("retry", score, Sidekiq.dump_json(msg))
@@ -778,7 +912,7 @@ def app
       get "/"
 
       assert_equal 401, last_response.status
-      refute_nil last_response.header["WWW-Authenticate"]
+      refute_nil last_response.headers["WWW-Authenticate"]
     end
 
     it "authenticates successfully" do
@@ -796,7 +930,7 @@ def app
 
     def app
       app = Sidekiq::Web.new
-      app.use Rack::Session::Cookie, secret: "v3rys3cr31", host: "nicehost.org"
+      app.use Rack::Session::Cookie, secret: session_secret, host: "nicehost.org"
       app
     end
 
@@ -805,7 +939,7 @@ def app
 
       session_options = last_request.env["rack.session"].options
 
-      assert_equal "v3rys3cr31", session_options[:secret]
+      assert_equal session_secret, session_options[:secret]
       assert_equal "nicehost.org", session_options[:host]
     end
   end
@@ -826,7 +960,7 @@ def app
 
     def app
       app = Sidekiq::Web.new
-      app.use Rack::Session::Cookie, secret: "v3rys3cr31", host: "nicehost.org"
+      app.use Rack::Session::Cookie, secret: session_secret, host: "nicehost.org"
       app
     end
 
@@ -837,6 +971,17 @@ def app
   end
 
   describe "Metrics" do
+    before do
+      require "sidekiq/component"
+      require "sidekiq/metrics/tracking"
+      t = Sidekiq::Metrics::ExecutionTracker.new(@config)
+      t.track("default", "MikeJob") do
+        # TODO replace sleep with a method we can call
+        sleep 0.02
+      end
+      t.flush
+    end
+
     describe "/metrics" do
       it "calls the Sidekiq::Metrics::Query and renders correctly" do
         result_mock = Minitest::Mock.new
@@ -857,6 +1002,19 @@ def app
           assert_match(/Metrics/, last_response.body)
         end
       end
+
+      it "supports filtering" do
+        get "/filter/metrics"
+        assert_equal 302, last_response.status
+
+        post "/filter/metrics", "substr" => "mike"
+        assert_equal 200, last_response.status
+        assert_match(/MikeJob/, last_response.body)
+
+        post "/filter/metrics", "substr" => "notfound"
+        assert_equal 200, last_response.status
+        refute_match(/MikeJob/, last_response.body)
+      end
     end
 
     describe "/metrics/:job" do
diff --git a/vendor/gems/sidekiq-7.2.4/tmp/app/sidekiq/foo_job.rb b/vendor/gems/sidekiq-7.2.4/tmp/app/sidekiq/foo_job.rb
new file mode 100644
index 0000000000000000000000000000000000000000..13f079dca16c6510eb0e96f92a7a89183d9ff542
--- /dev/null
+++ b/vendor/gems/sidekiq-7.2.4/tmp/app/sidekiq/foo_job.rb
@@ -0,0 +1,7 @@
+class FooJob
+  include Sidekiq::Job
+
+  def perform(*args)
+    # Do something
+  end
+end
diff --git a/vendor/gems/sidekiq-7.1.6/web/assets/images/apple-touch-icon.png b/vendor/gems/sidekiq-7.2.4/web/assets/images/apple-touch-icon.png
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/assets/images/apple-touch-icon.png
rename to vendor/gems/sidekiq-7.2.4/web/assets/images/apple-touch-icon.png
diff --git a/vendor/gems/sidekiq-7.1.6/web/assets/images/favicon.ico b/vendor/gems/sidekiq-7.2.4/web/assets/images/favicon.ico
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/assets/images/favicon.ico
rename to vendor/gems/sidekiq-7.2.4/web/assets/images/favicon.ico
diff --git a/vendor/gems/sidekiq-7.1.6/web/assets/images/logo.png b/vendor/gems/sidekiq-7.2.4/web/assets/images/logo.png
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/assets/images/logo.png
rename to vendor/gems/sidekiq-7.2.4/web/assets/images/logo.png
diff --git a/vendor/gems/sidekiq-7.1.6/web/assets/images/status.png b/vendor/gems/sidekiq-7.2.4/web/assets/images/status.png
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/assets/images/status.png
rename to vendor/gems/sidekiq-7.2.4/web/assets/images/status.png
diff --git a/vendor/gems/sidekiq-7.1.6/web/assets/javascripts/application.js b/vendor/gems/sidekiq-7.2.4/web/assets/javascripts/application.js
similarity index 98%
rename from vendor/gems/sidekiq-7.1.6/web/assets/javascripts/application.js
rename to vendor/gems/sidekiq-7.2.4/web/assets/javascripts/application.js
index 9f50ca8019e9f2e71d790e1102ad3b859d4f21be..01b175c1758116598ad828662a421f1106b6ee38 100644
--- a/vendor/gems/sidekiq-7.1.6/web/assets/javascripts/application.js
+++ b/vendor/gems/sidekiq-7.2.4/web/assets/javascripts/application.js
@@ -33,6 +33,7 @@ function addListeners() {
 
   addShiftClickListeners()
   updateFuzzyTimes();
+  updateNumbers();
   setLivePollFromUrl();
 
   var buttons = document.querySelectorAll(".live-poll");
@@ -46,6 +47,8 @@ function addListeners() {
       scheduleLivePoll();
     }
   }
+
+  document.getElementById("locale-select").addEventListener("change", updateLocale);
 }
 
 function addPollingListeners(_event)  {
@@ -102,6 +105,20 @@ function updateFuzzyTimes() {
   t.cancel();
 }
 
+function updateNumbers() {
+  document.querySelectorAll("[data-nwp]").forEach(node => {
+    let number = parseFloat(node.textContent);
+    let precision = parseInt(node.dataset["nwp"] || 0);
+    if (typeof number === "number") {
+      let formatted = number.toLocaleString(undefined, {
+        minimumFractionDigits: precision,
+        maximumFractionDigits: precision,
+      });
+      node.textContent = formatted;
+    }
+  });
+}
+
 function setLivePollFromUrl() {
   var url_params = new URL(window.location.href).searchParams
 
@@ -160,3 +177,7 @@ function replacePage(text) {
 function showError(error) {
   console.error(error)
 }
+
+function updateLocale(event) {
+  event.target.form.submit();
+};
\ No newline at end of file
diff --git a/vendor/gems/sidekiq-7.1.6/web/assets/javascripts/base-charts.js b/vendor/gems/sidekiq-7.2.4/web/assets/javascripts/base-charts.js
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/assets/javascripts/base-charts.js
rename to vendor/gems/sidekiq-7.2.4/web/assets/javascripts/base-charts.js
diff --git a/vendor/gems/sidekiq-7.1.6/web/assets/javascripts/chart.min.js b/vendor/gems/sidekiq-7.2.4/web/assets/javascripts/chart.min.js
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/assets/javascripts/chart.min.js
rename to vendor/gems/sidekiq-7.2.4/web/assets/javascripts/chart.min.js
diff --git a/vendor/gems/sidekiq-7.1.6/web/assets/javascripts/chartjs-plugin-annotation.min.js b/vendor/gems/sidekiq-7.2.4/web/assets/javascripts/chartjs-plugin-annotation.min.js
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/assets/javascripts/chartjs-plugin-annotation.min.js
rename to vendor/gems/sidekiq-7.2.4/web/assets/javascripts/chartjs-plugin-annotation.min.js
diff --git a/vendor/gems/sidekiq-7.1.6/web/assets/javascripts/dashboard-charts.js b/vendor/gems/sidekiq-7.2.4/web/assets/javascripts/dashboard-charts.js
similarity index 91%
rename from vendor/gems/sidekiq-7.1.6/web/assets/javascripts/dashboard-charts.js
rename to vendor/gems/sidekiq-7.2.4/web/assets/javascripts/dashboard-charts.js
index 7c249c2eda5aaa0472b229f00f941adaf79b7246..224f95af50f9b2bf6398d9b0ad0857462c27727b 100644
--- a/vendor/gems/sidekiq-7.1.6/web/assets/javascripts/dashboard-charts.js
+++ b/vendor/gems/sidekiq-7.2.4/web/assets/javascripts/dashboard-charts.js
@@ -86,6 +86,7 @@ class RealtimeChart extends DashboardChart {
     updateStatsSummary(this.stats.sidekiq);
     updateRedisStats(this.stats.redis);
     updateFooterUTCTime(this.stats.server_utc_time);
+    updateNumbers();
     pulseBeacon();
 
     this.stats = stats;
@@ -166,3 +167,16 @@ class RealtimeChart extends DashboardChart {
     };
   }
 }
+
+  var rc = document.getElementById("realtime-chart")
+  if (rc != null) {
+    var rtc = new RealtimeChart(rc, JSON.parse(rc.textContent))
+    rtc.registerLegend(document.getElementById("realtime-legend"))
+    window.realtimeChart = rtc
+  }
+
+  var hc = document.getElementById("history-chart")
+  if (hc != null) {
+    var htc = new DashboardChart(hc, JSON.parse(hc.textContent))
+    window.historyChart = htc
+  }
\ No newline at end of file
diff --git a/vendor/gems/sidekiq-7.1.6/web/assets/javascripts/dashboard.js b/vendor/gems/sidekiq-7.2.4/web/assets/javascripts/dashboard.js
similarity index 74%
rename from vendor/gems/sidekiq-7.1.6/web/assets/javascripts/dashboard.js
rename to vendor/gems/sidekiq-7.2.4/web/assets/javascripts/dashboard.js
index ac82e52b0ca54eb818cf2cacdcb2ea92ff9f591f..c6e582fcf9ae2a8f376ff7a85b5d3040f908da03 100644
--- a/vendor/gems/sidekiq-7.1.6/web/assets/javascripts/dashboard.js
+++ b/vendor/gems/sidekiq-7.2.4/web/assets/javascripts/dashboard.js
@@ -1,15 +1,13 @@
 Sidekiq = {};
 
-var nf = new Intl.NumberFormat();
-
 var updateStatsSummary = function(data) {
-  document.getElementById("txtProcessed").innerText = nf.format(data.processed);
-  document.getElementById("txtFailed").innerText = nf.format(data.failed);
-  document.getElementById("txtBusy").innerText = nf.format(data.busy);
-  document.getElementById("txtScheduled").innerText = nf.format(data.scheduled);
-  document.getElementById("txtRetries").innerText = nf.format(data.retries);
-  document.getElementById("txtEnqueued").innerText = nf.format(data.enqueued);
-  document.getElementById("txtDead").innerText = nf.format(data.dead);
+  document.getElementById("txtProcessed").innerText = data.processed;
+  document.getElementById("txtFailed").innerText = data.failed;
+  document.getElementById("txtBusy").innerText = data.busy;
+  document.getElementById("txtScheduled").innerText = data.scheduled;
+  document.getElementById("txtRetries").innerText = data.retries;
+  document.getElementById("txtEnqueued").innerText = data.enqueued;
+  document.getElementById("txtDead").innerText = data.dead;
 }
 
 var updateRedisStats = function(data) {
diff --git a/vendor/gems/sidekiq-7.1.6/web/assets/javascripts/metrics.js b/vendor/gems/sidekiq-7.2.4/web/assets/javascripts/metrics.js
similarity index 87%
rename from vendor/gems/sidekiq-7.1.6/web/assets/javascripts/metrics.js
rename to vendor/gems/sidekiq-7.2.4/web/assets/javascripts/metrics.js
index df16c950b3774d773b35d87c2a2022dbe6f048e9..291ea42793b8a4a01ccc810b72e0133337d4feec 100644
--- a/vendor/gems/sidekiq-7.1.6/web/assets/javascripts/metrics.js
+++ b/vendor/gems/sidekiq-7.2.4/web/assets/javascripts/metrics.js
@@ -262,3 +262,37 @@ class HistBubbleChart extends BaseChart {
     };
   }
 }
+
+var ch = document.getElementById("job-metrics-overview-chart");
+if (ch != null) {
+  var jm = new JobMetricsOverviewChart(ch, JSON.parse(ch.textContent));
+  document.querySelectorAll(".metrics-swatch-wrapper > input[type=checkbox]").forEach((imp) => {
+    jm.registerSwatch(imp.id)
+  });
+  window.jobMetricsChart = jm;
+}
+
+var htc = document.getElementById("hist-totals-chart");
+if (htc != null) {
+  var tc = new HistTotalsChart(htc, JSON.parse(htc.textContent));
+  window.histTotalsChart = tc
+}
+
+var hbc = document.getElementById("hist-bubble-chart");
+if (hbc != null) {
+  var bc = new HistBubbleChart(hbc, JSON.parse(hbc.textContent));
+  window.histBubbleChart = bc
+}
+
+var form = document.getElementById("metrics-form")
+document.querySelectorAll("#period-selector").forEach(node => {
+  node.addEventListener("input", debounce(() => form.submit()))
+})
+
+function debounce(func, timeout = 300) {
+  let timer;
+  return (...args) => {
+    clearTimeout(timer);
+    timer = setTimeout(() => { func.apply(this, args); }, timeout);
+  };
+}
\ No newline at end of file
diff --git a/vendor/gems/sidekiq-7.1.6/web/assets/stylesheets/application-dark.css b/vendor/gems/sidekiq-7.2.4/web/assets/stylesheets/application-dark.css
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/assets/stylesheets/application-dark.css
rename to vendor/gems/sidekiq-7.2.4/web/assets/stylesheets/application-dark.css
diff --git a/vendor/gems/sidekiq-7.1.6/web/assets/stylesheets/application-rtl.css b/vendor/gems/sidekiq-7.2.4/web/assets/stylesheets/application-rtl.css
similarity index 95%
rename from vendor/gems/sidekiq-7.1.6/web/assets/stylesheets/application-rtl.css
rename to vendor/gems/sidekiq-7.2.4/web/assets/stylesheets/application-rtl.css
index 509ed52d9d57b9347b3d124bd54bef6cad6453ec..99c98a10b14513d3f056e593b0a398ea78151a63 100644
--- a/vendor/gems/sidekiq-7.1.6/web/assets/stylesheets/application-rtl.css
+++ b/vendor/gems/sidekiq-7.2.4/web/assets/stylesheets/application-rtl.css
@@ -151,3 +151,13 @@ div.interval-slider {
     padding-left: 5px;
   }
 }
+
+#locale-select {
+  float: right;
+}
+
+@media (max-width: 767px) {
+  #locale-select {
+    float: none;
+  }
+}
\ No newline at end of file
diff --git a/vendor/gems/sidekiq-7.1.6/web/assets/stylesheets/application.css b/vendor/gems/sidekiq-7.2.4/web/assets/stylesheets/application.css
similarity index 99%
rename from vendor/gems/sidekiq-7.1.6/web/assets/stylesheets/application.css
rename to vendor/gems/sidekiq-7.2.4/web/assets/stylesheets/application.css
index 97537a81ba8223c2e40cc5f236b8275bbb0f903b..cb6104793610fba462a0eeccdb4e7c37439b4b9d 100644
--- a/vendor/gems/sidekiq-7.1.6/web/assets/stylesheets/application.css
+++ b/vendor/gems/sidekiq-7.2.4/web/assets/stylesheets/application.css
@@ -370,6 +370,15 @@ img.smallogo {
 .stat p {
   font-size: 0.9em;
 }
+
+.num {
+  font-family: monospace;
+}
+
+td.num {
+  text-align: right;
+}
+
 @media (max-width: 767px) {
   .stats-container {
     display: block;
@@ -722,3 +731,16 @@ div.interval-slider input {
 canvas {
   margin: 20px 0 30px;
 }
+
+#locale-select {
+  float: left;
+  margin: 8px 15px;
+}
+
+@media (max-width: 767px) {
+  #locale-select {
+    float: none;
+    width: auto;
+    margin: 15px auto;
+  }
+}
\ No newline at end of file
diff --git a/vendor/gems/sidekiq-7.1.6/web/assets/stylesheets/bootstrap-rtl.min.css b/vendor/gems/sidekiq-7.2.4/web/assets/stylesheets/bootstrap-rtl.min.css
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/assets/stylesheets/bootstrap-rtl.min.css
rename to vendor/gems/sidekiq-7.2.4/web/assets/stylesheets/bootstrap-rtl.min.css
diff --git a/vendor/gems/sidekiq-7.1.6/web/assets/stylesheets/bootstrap.css b/vendor/gems/sidekiq-7.2.4/web/assets/stylesheets/bootstrap.css
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/assets/stylesheets/bootstrap.css
rename to vendor/gems/sidekiq-7.2.4/web/assets/stylesheets/bootstrap.css
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/ar.yml b/vendor/gems/sidekiq-7.2.4/web/locales/ar.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/ar.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/ar.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/cs.yml b/vendor/gems/sidekiq-7.2.4/web/locales/cs.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/cs.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/cs.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/da.yml b/vendor/gems/sidekiq-7.2.4/web/locales/da.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/da.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/da.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/de.yml b/vendor/gems/sidekiq-7.2.4/web/locales/de.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/de.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/de.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/el.yml b/vendor/gems/sidekiq-7.2.4/web/locales/el.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/el.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/el.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/en.yml b/vendor/gems/sidekiq-7.2.4/web/locales/en.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/en.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/en.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/es.yml b/vendor/gems/sidekiq-7.2.4/web/locales/es.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/es.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/es.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/fa.yml b/vendor/gems/sidekiq-7.2.4/web/locales/fa.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/fa.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/fa.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/fr.yml b/vendor/gems/sidekiq-7.2.4/web/locales/fr.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/fr.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/fr.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/gd.yml b/vendor/gems/sidekiq-7.2.4/web/locales/gd.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/gd.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/gd.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/he.yml b/vendor/gems/sidekiq-7.2.4/web/locales/he.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/he.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/he.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/hi.yml b/vendor/gems/sidekiq-7.2.4/web/locales/hi.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/hi.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/hi.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/it.yml b/vendor/gems/sidekiq-7.2.4/web/locales/it.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/it.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/it.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/ja.yml b/vendor/gems/sidekiq-7.2.4/web/locales/ja.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/ja.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/ja.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/ko.yml b/vendor/gems/sidekiq-7.2.4/web/locales/ko.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/ko.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/ko.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/lt.yml b/vendor/gems/sidekiq-7.2.4/web/locales/lt.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/lt.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/lt.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/nb.yml b/vendor/gems/sidekiq-7.2.4/web/locales/nb.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/nb.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/nb.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/nl.yml b/vendor/gems/sidekiq-7.2.4/web/locales/nl.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/nl.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/nl.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/pl.yml b/vendor/gems/sidekiq-7.2.4/web/locales/pl.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/pl.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/pl.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/pt-br.yml b/vendor/gems/sidekiq-7.2.4/web/locales/pt-br.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/pt-br.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/pt-br.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/pt.yml b/vendor/gems/sidekiq-7.2.4/web/locales/pt.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/pt.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/pt.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/ru.yml b/vendor/gems/sidekiq-7.2.4/web/locales/ru.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/ru.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/ru.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/sv.yml b/vendor/gems/sidekiq-7.2.4/web/locales/sv.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/sv.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/sv.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/ta.yml b/vendor/gems/sidekiq-7.2.4/web/locales/ta.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/ta.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/ta.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/uk.yml b/vendor/gems/sidekiq-7.2.4/web/locales/uk.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/uk.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/uk.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/ur.yml b/vendor/gems/sidekiq-7.2.4/web/locales/ur.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/ur.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/ur.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/vi.yml b/vendor/gems/sidekiq-7.2.4/web/locales/vi.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/vi.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/vi.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/zh-cn.yml b/vendor/gems/sidekiq-7.2.4/web/locales/zh-cn.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/zh-cn.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/zh-cn.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/locales/zh-tw.yml b/vendor/gems/sidekiq-7.2.4/web/locales/zh-tw.yml
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/locales/zh-tw.yml
rename to vendor/gems/sidekiq-7.2.4/web/locales/zh-tw.yml
diff --git a/vendor/gems/sidekiq-7.1.6/web/views/_footer.erb b/vendor/gems/sidekiq-7.2.4/web/views/_footer.erb
similarity index 50%
rename from vendor/gems/sidekiq-7.1.6/web/views/_footer.erb
rename to vendor/gems/sidekiq-7.2.4/web/views/_footer.erb
index 0042c78ae5f6a1fce5a0c78fc513f3895bc75ec5..a0c2902548626e8181c7d84c030ba42c81d148f0 100644
--- a/vendor/gems/sidekiq-7.1.6/web/views/_footer.erb
+++ b/vendor/gems/sidekiq-7.2.4/web/views/_footer.erb
@@ -15,7 +15,19 @@
             <p class="navbar-text"><a rel=help href="https://github.com/sidekiq/sidekiq/wiki">docs</a></p>
           </li>
           <li>
-            <p class="navbar-text"><a rel=external href="https://github.com/sidekiq/sidekiq/tree/main/web/locales"><%= locale %></a></p>
+            <form id="locale-form" class="form-inline" action="<%= root_path %>change_locale" method="post">
+              <%= csrf_tag %>
+              <label class="sr-only" for="locale">Language</label>
+              <select id="locale-select" class="form-control" name="locale">
+                <% available_locales.each do |locale_option| %>
+                  <% if locale_option == locale %>
+                    <option selected value="<%= locale_option %>"><%= locale_option %></option>
+                  <% else %>
+                    <option value="<%= locale_option %>"><%= locale_option %></option>
+                  <% end %>
+                <% end %>
+              </select>
+            </form>
           </li>
         </ul>
     </div>
diff --git a/vendor/gems/sidekiq-7.1.6/web/views/_job_info.erb b/vendor/gems/sidekiq-7.2.4/web/views/_job_info.erb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/views/_job_info.erb
rename to vendor/gems/sidekiq-7.2.4/web/views/_job_info.erb
diff --git a/vendor/gems/sidekiq-7.1.6/web/views/_metrics_period_select.erb b/vendor/gems/sidekiq-7.2.4/web/views/_metrics_period_select.erb
similarity index 70%
rename from vendor/gems/sidekiq-7.1.6/web/views/_metrics_period_select.erb
rename to vendor/gems/sidekiq-7.2.4/web/views/_metrics_period_select.erb
index de4d76a258ed990d76fa9218eb40d94a78847140..662fe003a3b192d98dc26cbd189aa7dd8c7cf553 100644
--- a/vendor/gems/sidekiq-7.1.6/web/views/_metrics_period_select.erb
+++ b/vendor/gems/sidekiq-7.2.4/web/views/_metrics_period_select.erb
@@ -1,5 +1,5 @@
 <div>
-  <select class="form-control" onchange="window.location.href = '<%= path %>?period=' + event.target.value">
+  <select class="form-control" data-metric-period="<%= path %>">
     <% periods.each_key do |code| %>
 
       <% if code == period %>
diff --git a/vendor/gems/sidekiq-7.1.6/web/views/_nav.erb b/vendor/gems/sidekiq-7.2.4/web/views/_nav.erb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/views/_nav.erb
rename to vendor/gems/sidekiq-7.2.4/web/views/_nav.erb
diff --git a/vendor/gems/sidekiq-7.1.6/web/views/_paging.erb b/vendor/gems/sidekiq-7.2.4/web/views/_paging.erb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/views/_paging.erb
rename to vendor/gems/sidekiq-7.2.4/web/views/_paging.erb
diff --git a/vendor/gems/sidekiq-7.1.6/web/views/_poll_link.erb b/vendor/gems/sidekiq-7.2.4/web/views/_poll_link.erb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/views/_poll_link.erb
rename to vendor/gems/sidekiq-7.2.4/web/views/_poll_link.erb
diff --git a/vendor/gems/sidekiq-7.1.6/web/views/_status.erb b/vendor/gems/sidekiq-7.2.4/web/views/_status.erb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/views/_status.erb
rename to vendor/gems/sidekiq-7.2.4/web/views/_status.erb
diff --git a/vendor/gems/sidekiq-7.1.6/web/views/_summary.erb b/vendor/gems/sidekiq-7.2.4/web/views/_summary.erb
similarity index 58%
rename from vendor/gems/sidekiq-7.1.6/web/views/_summary.erb
rename to vendor/gems/sidekiq-7.2.4/web/views/_summary.erb
index 9e187c8d15c2dd00295d23baa5f30165e39b8ae3..93a24a102c96a9d5e61b88371c10660ed9f70049 100644
--- a/vendor/gems/sidekiq-7.1.6/web/views/_summary.erb
+++ b/vendor/gems/sidekiq-7.2.4/web/views/_summary.erb
@@ -1,39 +1,39 @@
 <ul class="list-unstyled summary row">
   <li class="processed col-sm-1">
-    <span id="txtProcessed" class="count"><%= number_with_delimiter(stats.processed) %></span>
+    <span id="txtProcessed" class="count" data-nwp><%= stats.processed %></span>
     <span class="desc"><%= t('Processed') %></span>
   </li>
   <li class="failed col-sm-1">
-    <span id="txtFailed" class="count"><%= number_with_delimiter(stats.failed) %></span>
+    <span id="txtFailed" class="count" data-nwp><%= stats.failed %></span>
     <span class="desc"><%= t('Failed') %></span>
   </li>
   <li class="busy col-sm-1">
     <a href="<%= root_path %>busy">
-      <span id="txtBusy" class="count"><%= number_with_delimiter(workset.size) %></span>
+      <span id="txtBusy" class="count" data-nwp><%= workset.size %></span>
       <span class="desc"><%= t('Busy') %></span>
     </a>
   </li>
   <li class="enqueued col-sm-1">
     <a href="<%= root_path %>queues">
-      <span id="txtEnqueued" class="count"><%= number_with_delimiter(stats.enqueued) %></span>
+      <span id="txtEnqueued" class="count" data-nwp><%= stats.enqueued %></span>
       <span class="desc"><%= t('Enqueued') %></span>
     </a>
   </li>
   <li class="retries col-sm-1">
     <a href="<%= root_path %>retries">
-      <span id="txtRetries" class="count"><%= number_with_delimiter(stats.retry_size) %></span>
+      <span id="txtRetries" class="count" data-nwp><%= stats.retry_size %></span>
       <span class="desc"><%= t('Retries') %></span>
     </a>
   </li>
   <li class="scheduled col-sm-1">
     <a href="<%= root_path %>scheduled">
-      <span id="txtScheduled" class="count"><%= number_with_delimiter(stats.scheduled_size) %></span>
+      <span id="txtScheduled" class="count" data-nwp><%= stats.scheduled_size %></span>
       <span class="desc"><%= t('Scheduled') %></span>
     </a>
   </li>
   <li class="dead col-sm-1">
     <a href="<%= root_path %>morgue">
-      <span id="txtDead" class="count"><%= number_with_delimiter(stats.dead_size) %></span>
+      <span id="txtDead" class="count" data-nwp><%= stats.dead_size %></span>
       <span class="desc"><%= t('Dead') %></span>
     </a>
   </li>
diff --git a/vendor/gems/sidekiq-7.1.6/web/views/busy.erb b/vendor/gems/sidekiq-7.2.4/web/views/busy.erb
similarity index 91%
rename from vendor/gems/sidekiq-7.1.6/web/views/busy.erb
rename to vendor/gems/sidekiq-7.2.4/web/views/busy.erb
index c75faf686e8eb5f5c42426b7a5005ebc41a797d8..4b6c0537b07cc78a130fccc9e9592f382d348f8c 100644
--- a/vendor/gems/sidekiq-7.1.6/web/views/busy.erb
+++ b/vendor/gems/sidekiq-7.2.4/web/views/busy.erb
@@ -86,9 +86,9 @@
           <% end %>
         </td>
         <td><%= relative_time(Time.at(process['started_at'])) %></td>
-        <td><%= format_memory(process['rss'].to_i) %></td>
-        <td><%= process['concurrency'] %></td>
-        <td><%= process['busy'] %></td>
+        <td class="num"><%= format_memory(process['rss'].to_i) %></td>
+        <td class="num"><%= number_with_delimiter(process['concurrency']) %></td>
+        <td class="num"><%= number_with_delimiter(process['busy']) %></td>
         <td>
           <% unless process.embedded? %>
             <form method="POST">
@@ -125,14 +125,14 @@
       <th><%= t('Arguments') %></th>
       <th><%= t('Started') %></th>
     </thead>
-    <% @workset.each do |process, thread, msg| %>
-      <% job = Sidekiq::JobRecord.new(msg['payload']) %>
+    <% @workset.each do |process, thread, work| %>
+      <% job = work.job %>
       <tr>
         <td><%= process %></td>
         <td><%= thread %></td>
         <td><%= job.jid %></td>
         <td>
-          <a href="<%= root_path %>queues/<%= msg['queue'] %>"><%= msg['queue'] %></a>
+          <a href="<%= root_path %>queues/<%= work.queue %>"><%= work.queue %></a>
         </td>
         <td>
           <%= job.display_class %>
@@ -141,7 +141,7 @@
         <td>
           <div class="args"><%= display_args(job.display_args) %></div>
         </td>
-        <td><%= relative_time(Time.at(msg['run_at'])) %></td>
+        <td><%= relative_time(work.run_at) %></td>
       </tr>
     <% end %>
   </table>
diff --git a/vendor/gems/sidekiq-7.1.6/web/views/dashboard.erb b/vendor/gems/sidekiq-7.2.4/web/views/dashboard.erb
similarity index 77%
rename from vendor/gems/sidekiq-7.1.6/web/views/dashboard.erb
rename to vendor/gems/sidekiq-7.2.4/web/views/dashboard.erb
index 4ba60e587a457bdaa0ec90821de7c53f019fedb0..1f44006059298325d47e70353c0f2285a7e443b7 100644
--- a/vendor/gems/sidekiq-7.1.6/web/views/dashboard.erb
+++ b/vendor/gems/sidekiq-7.2.4/web/views/dashboard.erb
@@ -1,7 +1,3 @@
-<script type="text/javascript" src="<%= root_path %>javascripts/chart.min.js"></script>
-<script type="text/javascript" src="<%= root_path %>javascripts/chartjs-plugin-annotation.min.js"></script>
-<script type="text/javascript" src="<%= root_path %>javascripts/base-charts.js"></script>
-<script type="text/javascript" src="<%= root_path %>javascripts/dashboard-charts.js"></script>
 <script type="text/javascript" src="<%= root_path %>javascripts/dashboard.js"></script>
 <div class= "dashboard clearfix">
   <h3 >
@@ -20,26 +16,19 @@
 </div>
 
 <div class="row chart">
-  <canvas id="realtime-chart"></canvas>
-  <script>
-    window.realtimeChart = new RealtimeChart(
-      document.getElementById("realtime-chart"),
-      <%= Sidekiq.dump_json({
-        processedLabel: t('Processed'),
-        failedLabel: t('Failed'),
-        labels: Array.new(50, ""),
-        processed: Array.new(50),
-        failed: Array.new(50),
-        updateUrl: "#{root_path}stats",
-      }) %>
-    )
-  </script>
+  <canvas id="realtime-chart">
+    <%= to_json({
+      processedLabel: t('Processed'),
+      failedLabel: t('Failed'),
+      labels: Array.new(50, ""),
+      processed: Array.new(50),
+      failed: Array.new(50),
+      updateUrl: "#{root_path}stats",
+    }) %>
+  </canvas>
 
   <!-- start with a space in the legend so the height doesn't change when we add content dynamically -->
   <div id="realtime-legend">&nbsp;</div>
-  <script>
-    realtimeChart.registerLegend(document.getElementById("realtime-legend"))
-  </script>
 </div>
 
 <div class="row header">
@@ -55,18 +44,14 @@
     <a href="<%= root_path %>?days=180" class="history-graph <%= "active" if params[:days] == "180" %>"><%= t('SixMonths') %></a>
   </div>
 
-  <canvas id="history-chart"></canvas>
-  <script>
-    window.historyChart = new DashboardChart(
-      document.getElementById("history-chart"),
-      <%= Sidekiq.dump_json({
-        processedLabel: t('Processed'),
-        failedLabel: t('Failed'),
-        processed: @processed_history.to_a.reverse,
-        failed: @failed_history.to_a.reverse,
-      }) %>
-    )
-  </script>
+  <canvas id="history-chart">
+    <%= to_json({
+      processedLabel: t('Processed'),
+      failedLabel: t('Failed'),
+      processed: @processed_history.to_a.reverse,
+      failed: @failed_history.to_a.reverse,
+    }) %>
+  </canvas>
 </div>
 
 <br/>
@@ -113,3 +98,8 @@
     <% end %>
   </div>
 </div>
+
+<script type="text/javascript" src="<%= root_path %>javascripts/chart.min.js"></script>
+<script type="text/javascript" src="<%= root_path %>javascripts/chartjs-plugin-annotation.min.js"></script>
+<script type="text/javascript" src="<%= root_path %>javascripts/base-charts.js"></script>
+<script type="text/javascript" src="<%= root_path %>javascripts/dashboard-charts.js"></script>
\ No newline at end of file
diff --git a/vendor/gems/sidekiq-7.1.6/web/views/dead.erb b/vendor/gems/sidekiq-7.2.4/web/views/dead.erb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/views/dead.erb
rename to vendor/gems/sidekiq-7.2.4/web/views/dead.erb
diff --git a/vendor/gems/sidekiq-7.2.4/web/views/filtering.erb b/vendor/gems/sidekiq-7.2.4/web/views/filtering.erb
new file mode 100644
index 0000000000000000000000000000000000000000..17ac3dbae6888f735bc859d8f11dc87bfdc0cb9e
--- /dev/null
+++ b/vendor/gems/sidekiq-7.2.4/web/views/filtering.erb
@@ -0,0 +1,7 @@
+<div>
+  <form method="post" class="form-inline" action='<%= root_path %>filter/<%= which %>'>
+    <%= csrf_tag %>
+    <label for="substr"><%= t('Filter') %></label>
+    <input class="search form-control" type="search" name="substr" value="<%= h params[:substr] %>" placeholder="<%= t('AnyJobContent') %>"/>
+  </form>
+</div>
diff --git a/vendor/gems/sidekiq-7.1.6/web/views/layout.erb b/vendor/gems/sidekiq-7.2.4/web/views/layout.erb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/views/layout.erb
rename to vendor/gems/sidekiq-7.2.4/web/views/layout.erb
diff --git a/vendor/gems/sidekiq-7.1.6/web/views/metrics.erb b/vendor/gems/sidekiq-7.2.4/web/views/metrics.erb
similarity index 53%
rename from vendor/gems/sidekiq-7.1.6/web/views/metrics.erb
rename to vendor/gems/sidekiq-7.2.4/web/views/metrics.erb
index c58b9e948d0372d66760932f1d80dc998c03f86e..5eefa33ff2f999217577a360a0480df71472c628 100644
--- a/vendor/gems/sidekiq-7.1.6/web/views/metrics.erb
+++ b/vendor/gems/sidekiq-7.2.4/web/views/metrics.erb
@@ -1,16 +1,29 @@
 <script type="text/javascript" src="<%= root_path %>javascripts/chart.min.js"></script>
 <script type="text/javascript" src="<%= root_path %>javascripts/chartjs-plugin-annotation.min.js"></script>
 <script type="text/javascript" src="<%= root_path %>javascripts/base-charts.js"></script>
-<script type="text/javascript" src="<%= root_path %>javascripts/metrics.js"></script>
 
 <div class="header-container">
   <div class="page-title-container">
     <h1><%= t('Metrics') %></h1>
-
     <a target="blank" href="https://github.com/sidekiq/sidekiq/wiki/Metrics"><span class="info-circle" title="Click to learn more about metrics">?</span></a>
   </div>
 
-  <%= erb :_metrics_period_select, locals: { periods: @periods, period: @period, path: "#{root_path}metrics" } %>
+  <div>
+    <form id="metrics-form" class="form-inline" action="<%= root_path %>filter/metrics" method="post">
+      <%= csrf_tag %>
+      <label for="substr"><%= t('Filter') %></label>
+      <input id="class-filter" class="form-control" type="text" name="substr" placeholder="<%= t('Name') %>" value="<%= h params[:substr] %>">
+      <select id="period-selector" class="form-control" name="period">
+        <% @periods.each_key do |code| %>
+          <% if code == @period %>
+            <option selected value="<%= code %>"><%= code %></option>
+          <% else %>
+            <option value="<%= code %>"><%= code %></option>
+          <% end %>
+        <% end %>
+      </select>
+    </form>
+  </div>
 </div>
 
 <%
@@ -21,22 +34,17 @@
 %>
 
 <% if job_results.any? %>
-  <canvas id="job-metrics-overview-chart"></canvas>
-
-  <script>
-    window.jobMetricsChart = new JobMetricsOverviewChart(
-      document.getElementById("job-metrics-overview-chart"),
-      <%= Sidekiq.dump_json({
-        series: job_results.map { |(kls, jr)| [kls, jr.dig("series", "s")] }.to_h,
-        marks: @query_result.marks.map { |m| [m.bucket, m.label] },
-        labels: @query_result.buckets,
-        visibleKls: visible_kls,
-        yLabel: t('TotalExecutionTime'),
-        units: t('Seconds').downcase,
-        markLabel: t('Deploy'),
-      }) %>
-    )
-  </script>
+  <canvas id="job-metrics-overview-chart">
+    <%= to_json({
+      series: job_results.map { |(kls, jr)| [kls, jr.dig("series", "s")] }.to_h,
+      marks: @query_result.marks.map { |m| [m.bucket, m.label] },
+      labels: @query_result.buckets,
+      visibleKls: visible_kls,
+      yLabel: t('TotalExecutionTime'),
+      units: t('Seconds').downcase,
+      markLabel: t('Deploy'),
+    }) %>
+  </canvas>
 <% end %>
 
 <div class="table_container">
@@ -46,8 +54,8 @@
         <th><%= t('Name') %></th>
         <th><%= t('Success') %></th>
         <th><%= t('Failure') %></th>
-        <th><%= t('TotalExecutionTime') %></th>
-        <th><%= t('AvgExecutionTime') %></th>
+        <th><%= t('TotalExecutionTime') %> (Seconds)</th>
+        <th><%= t('AvgExecutionTime') %> (Seconds)</th>
       </tr>
       <% if job_results.any? %>
         <% job_results.each_with_index do |(kls, jr), i| %>
@@ -64,12 +72,11 @@
                 />
                 <code><a href="<%= root_path %>metrics/<%= kls %>?period=<%= @period %>"><%= kls %></a></code>
               </div>
-              <script>jobMetricsChart.registerSwatch("<%= id %>")</script>
             </td>
-            <td><%= jr.dig("totals", "p") - jr.dig("totals", "f") %></td>
-            <td><%= jr.dig("totals", "f") %></td>
-            <td><%= jr.dig("totals", "s").round(2) %> seconds</td>
-            <td><%= jr.total_avg("s").round(2) %> seconds</td>
+            <td class="num"><%= number_with_delimiter(jr.dig("totals", "p") - jr.dig("totals", "f")) %></td>
+            <td class="num"><%= number_with_delimiter(jr.dig("totals", "f")) %></td>
+            <td class="num"><%= number_with_delimiter(jr.dig("totals", "s"), precision: 2) %></td>
+            <td class="num"><%= number_with_delimiter(jr.total_avg("s"), precision: 2) %></td>
           </tr>
         <% end %>
       <% else %>
@@ -79,4 +86,6 @@
   </table>
 </div>
 
-<p><small>Data from <%= @query_result.starts_at %> to <%= @query_result.ends_at %></small></p>
+<!--p><small>Data from <%= @query_result.starts_at %> to <%= @query_result.ends_at %></small></p-->
+
+<script type="text/javascript" src="<%= root_path %>javascripts/metrics.js"></script>
diff --git a/vendor/gems/sidekiq-7.1.6/web/views/metrics_for_job.erb b/vendor/gems/sidekiq-7.2.4/web/views/metrics_for_job.erb
similarity index 57%
rename from vendor/gems/sidekiq-7.1.6/web/views/metrics_for_job.erb
rename to vendor/gems/sidekiq-7.2.4/web/views/metrics_for_job.erb
index a9084b02c2591fe9e06755f809c1f814fc920698..80e8d27afbe4f41d852d4fd99a941f606636dbe8 100644
--- a/vendor/gems/sidekiq-7.1.6/web/views/metrics_for_job.erb
+++ b/vendor/gems/sidekiq-7.2.4/web/views/metrics_for_job.erb
@@ -1,7 +1,6 @@
 <script type="text/javascript" src="<%= root_path %>javascripts/chart.min.js"></script>
 <script type="text/javascript" src="<%= root_path %>javascripts/chartjs-plugin-annotation.min.js"></script>
 <script type="text/javascript" src="<%= root_path %>javascripts/base-charts.js"></script>
-<script type="text/javascript" src="<%= root_path %>javascripts/metrics.js"></script>
 
 <%
   job_result = @query_result.job_results[@name]
@@ -24,40 +23,30 @@
     <%= erb :_metrics_period_select, locals: { periods: @periods, period: @period, path: "#{root_path}metrics/#{@name}" } %>
   </div>
 
-  <canvas id="hist-totals-chart"></canvas>
-
-  <script>
-    window.histTotalsChart = new HistTotalsChart(
-      document.getElementById("hist-totals-chart"),
-      <%= Sidekiq.dump_json({
-        series: hist_totals,
-        labels: bucket_labels,
-        xLabel: t('ExecutionTime'),
-        yLabel: t('Jobs'),
-        units: t('Jobs').downcase,
-      }) %>
-    )
-  </script>
-
-  <canvas id="hist-bubble-chart"></canvas>
-
-  <script>
-    window.histBubbleChart = new HistBubbleChart(
-      document.getElementById("hist-bubble-chart"),
-      <%= Sidekiq.dump_json({
-        hist: job_result.hist,
-        marks: @query_result.marks.map { |m| [m.bucket, m.label] },
-        labels: @query_result.buckets,
-        histIntervals: bucket_intervals,
-        yLabel: t('ExecutionTime'),
-        markLabel: t('Deploy'),
-        yUnits: t('Seconds').downcase,
-        zUnits: t('Jobs').downcase,
-      }) %>
-    )
-  </script>
-
-  <p><small>Data from <%= @query_result.starts_at %> to <%= @query_result.ends_at %></small></p>
+  <canvas id="hist-totals-chart">
+    <%= to_json({
+      series: hist_totals,
+      labels: bucket_labels,
+      xLabel: t('ExecutionTime'),
+      yLabel: t('Jobs'),
+      units: t('Jobs').downcase,
+    }) %>
+  </canvas>
+
+  <canvas id="hist-bubble-chart">
+    <%= to_json({
+      hist: job_result.hist,
+      marks: @query_result.marks.map { |m| [m.bucket, m.label] },
+      labels: @query_result.buckets,
+      histIntervals: bucket_intervals,
+      yLabel: t('ExecutionTime'),
+      markLabel: t('Deploy'),
+      yUnits: t('Seconds').downcase,
+      zUnits: t('Jobs').downcase,
+    }) %>
+  </canvas>
+
+  <!--p><small>Data from <%= @query_result.starts_at %> to <%= @query_result.ends_at %></small></p-->
 <% else %>
   <h1>
     <a href="<%= root_path %>/metrics"><%= t('Metrics') %></a> /
@@ -66,3 +55,5 @@
 
   <div class="alert alert-success"><%= t('NoJobMetricsFound') %></div>
 <% end %>
+
+<script type="text/javascript" src="<%= root_path %>javascripts/metrics.js"></script>
\ No newline at end of file
diff --git a/vendor/gems/sidekiq-7.1.6/web/views/morgue.erb b/vendor/gems/sidekiq-7.2.4/web/views/morgue.erb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/views/morgue.erb
rename to vendor/gems/sidekiq-7.2.4/web/views/morgue.erb
diff --git a/vendor/gems/sidekiq-7.1.6/web/views/queue.erb b/vendor/gems/sidekiq-7.2.4/web/views/queue.erb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/views/queue.erb
rename to vendor/gems/sidekiq-7.2.4/web/views/queue.erb
diff --git a/vendor/gems/sidekiq-7.1.6/web/views/queues.erb b/vendor/gems/sidekiq-7.2.4/web/views/queues.erb
similarity index 81%
rename from vendor/gems/sidekiq-7.1.6/web/views/queues.erb
rename to vendor/gems/sidekiq-7.2.4/web/views/queues.erb
index 290de648cea3018f21410118774694d0d59f8f71..25fee2d0a9208f2634efbf5e217dbc74983b9a4e 100644
--- a/vendor/gems/sidekiq-7.1.6/web/views/queues.erb
+++ b/vendor/gems/sidekiq-7.2.4/web/views/queues.erb
@@ -18,8 +18,12 @@
             <span class="label label-danger"><%= t('Paused') %></span>
           <% end %>
         </td>
-        <td><%= number_with_delimiter(queue.size) %> </td>
-        <td><% queue_latency = queue.latency %><%= number_with_delimiter(queue_latency.round(2)) %><%= (queue_latency < 60) ? '' : " (#{relative_time(Time.at(Time.now.to_f - queue_latency))})" %> </td>
+        <td class="num"><%= number_with_delimiter(queue.size) %> </td>
+        <td class="num">
+          <% queue_latency = queue.latency %>
+          <%= (queue_latency < 60) ? '' : " (#{relative_time(Time.at(Time.now.to_f - queue_latency))})" %>
+          <%= number_with_delimiter(queue_latency, precision: 2) %>
+        </td>
         <td class="delete-confirm">
           <form action="<%=root_path %>queues/<%= CGI.escape(queue.name) %>" method="post">
             <%= csrf_tag %>
diff --git a/vendor/gems/sidekiq-7.1.6/web/views/retries.erb b/vendor/gems/sidekiq-7.2.4/web/views/retries.erb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/views/retries.erb
rename to vendor/gems/sidekiq-7.2.4/web/views/retries.erb
diff --git a/vendor/gems/sidekiq-7.1.6/web/views/retry.erb b/vendor/gems/sidekiq-7.2.4/web/views/retry.erb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/views/retry.erb
rename to vendor/gems/sidekiq-7.2.4/web/views/retry.erb
diff --git a/vendor/gems/sidekiq-7.1.6/web/views/scheduled.erb b/vendor/gems/sidekiq-7.2.4/web/views/scheduled.erb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/views/scheduled.erb
rename to vendor/gems/sidekiq-7.2.4/web/views/scheduled.erb
diff --git a/vendor/gems/sidekiq-7.1.6/web/views/scheduled_job_info.erb b/vendor/gems/sidekiq-7.2.4/web/views/scheduled_job_info.erb
similarity index 100%
rename from vendor/gems/sidekiq-7.1.6/web/views/scheduled_job_info.erb
rename to vendor/gems/sidekiq-7.2.4/web/views/scheduled_job_info.erb