From c72904fd34d644d32a48e5fc9cf9a44bfd7362a2 Mon Sep 17 00:00:00 2001 From: mhenrixon Date: Wed, 24 Jan 2024 09:58:13 +0200 Subject: [PATCH] fix: inline redis_script --- Gemfile | 3 +- lib/sidekiq_unique_jobs.rb | 8 +- lib/sidekiq_unique_jobs/changelog.rb | 2 +- lib/sidekiq_unique_jobs/redis_script.rb | 58 +++++++++ .../redis_script/client.rb | 94 +++++++++++++ .../redis_script/config.rb | 68 ++++++++++ lib/sidekiq_unique_jobs/redis_script/dsl.rb | 60 +++++++++ .../redis_script/logging.rb | 95 ++++++++++++++ .../redis_script/lua_error.rb | 96 ++++++++++++++ .../redis_script/script.rb | 80 ++++++++++++ .../redis_script/scripts.rb | 123 ++++++++++++++++++ .../redis_script/template.rb | 41 ++++++ .../redis_script/timing.rb | 35 +++++ lib/sidekiq_unique_jobs/script.rb | 2 +- .../sidekiq_unique_jobs.rb | 2 +- sidekiq-unique-jobs.gemspec | 1 - spec/sidekiq_unique_jobs/web_spec.rb | 5 +- spec/support/sidekiq_meta.rb | 2 +- spec/support/sidekiq_unique_jobs/testing.rb | 4 +- 19 files changed, 765 insertions(+), 14 deletions(-) create mode 100644 lib/sidekiq_unique_jobs/redis_script.rb create mode 100644 lib/sidekiq_unique_jobs/redis_script/client.rb create mode 100644 lib/sidekiq_unique_jobs/redis_script/config.rb create mode 100644 lib/sidekiq_unique_jobs/redis_script/dsl.rb create mode 100644 lib/sidekiq_unique_jobs/redis_script/logging.rb create mode 100644 lib/sidekiq_unique_jobs/redis_script/lua_error.rb create mode 100644 lib/sidekiq_unique_jobs/redis_script/script.rb create mode 100644 lib/sidekiq_unique_jobs/redis_script/scripts.rb create mode 100644 lib/sidekiq_unique_jobs/redis_script/template.rb create mode 100644 lib/sidekiq_unique_jobs/redis_script/timing.rb diff --git a/Gemfile b/Gemfile index 341ee59d9..4d7f30c02 100644 --- a/Gemfile +++ b/Gemfile @@ -12,8 +12,7 @@ gem "faraday-retry" gem "gem-release" gem "github-markup" gem "rack-test" -gem "rake", "13.0.3" -gem "reek", ">= 5.3" +gem "rake" gem "rspec" gem "rspec-benchmark" gem "rspec-html-matchers" diff --git a/lib/sidekiq_unique_jobs.rb b/lib/sidekiq_unique_jobs.rb index 6de4a18d0..c3b3a37e7 100644 --- a/lib/sidekiq_unique_jobs.rb +++ b/lib/sidekiq_unique_jobs.rb @@ -1,20 +1,22 @@ # frozen_string_literal: true -require "brpoplpush/redis_script" +require "concurrent/executor/ruby_single_thread_executor" require "concurrent/future" -require "concurrent/promises" require "concurrent/map" require "concurrent/mutable_struct" +require "concurrent/promises" require "concurrent/timer_task" -require "concurrent/executor/ruby_single_thread_executor" require "digest" require "digest/sha1" require "erb" require "forwardable" require "json" require "pathname" +require "redis_client" require "sidekiq" +require "sidekiq_unique_jobs/redis_script" + require "sidekiq_unique_jobs/deprecation" require "sidekiq_unique_jobs/reflections" require "sidekiq_unique_jobs/reflectable" diff --git a/lib/sidekiq_unique_jobs/changelog.rb b/lib/sidekiq_unique_jobs/changelog.rb index 6910d50d9..f3825b00c 100644 --- a/lib/sidekiq_unique_jobs/changelog.rb +++ b/lib/sidekiq_unique_jobs/changelog.rb @@ -59,7 +59,7 @@ def page(cursor: 0, pattern: "*", page_size: 100) # NOTE: When debugging, check the last item in the returned array. [ total_size.to_i, - result[0].to_i, # next_cursor + result[0].to_i, # next_cursor result[1].map { |entry| load_json(entry) }.select { |entry| entry.is_a?(Hash) }, ] end diff --git a/lib/sidekiq_unique_jobs/redis_script.rb b/lib/sidekiq_unique_jobs/redis_script.rb new file mode 100644 index 000000000..aae4cc1ed --- /dev/null +++ b/lib/sidekiq_unique_jobs/redis_script.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true + +require "sidekiq_unique_jobs/redis_script/template" +require "sidekiq_unique_jobs/redis_script/lua_error" +require "sidekiq_unique_jobs/redis_script/script" +require "sidekiq_unique_jobs/redis_script/scripts" +require "sidekiq_unique_jobs/redis_script/config" +require "sidekiq_unique_jobs/redis_script/timing" +require "sidekiq_unique_jobs/redis_script/logging" +require "sidekiq_unique_jobs/redis_script/dsl" +require "sidekiq_unique_jobs/redis_script/client" + +module SidekiqUniqueJobs + # Interface to dealing with .lua files + # + # @author Mikael Henriksson + module RedisScript + module_function + + include SidekiqUniqueJobs::RedisScript::DSL + + # + # The current logger + # + # + # @return [Logger] the configured logger + # + def logger + config.logger + end + + # + # Set a new logger + # + # @param [Logger] other another logger + # + # @return [Logger] the new logger + # + def logger=(other) + config.logger = other + end + + # + # Execute the given script_name + # + # + # @param [Symbol] script_name the name of the lua script + # @param [Array] keys script keys + # @param [Array] argv script arguments + # @param [Redis] conn the redis connection to use + # + # @return value from script + # + def execute(script_name, conn, keys: [], argv: []) + Client.execute(script_name, conn, keys: keys, argv: argv) + end + end +end diff --git a/lib/sidekiq_unique_jobs/redis_script/client.rb b/lib/sidekiq_unique_jobs/redis_script/client.rb new file mode 100644 index 000000000..66b606b0c --- /dev/null +++ b/lib/sidekiq_unique_jobs/redis_script/client.rb @@ -0,0 +1,94 @@ +# frozen_string_literal: true + +module SidekiqUniqueJobs + module RedisScript + # Interface to dealing with .lua files + # + # @author Mikael Henriksson + class Client + include SidekiqUniqueJobs::RedisScript::Timing + + # + # @!attribute [r] logger + # @return [Logger] an instance of a logger + attr_reader :logger + # + # @!attribute [r] file_name + # @return [String] The name of the file to execute + attr_reader :config + # + # @!attribute [r] scripts + # @return [Scripts] the collection with loaded scripts + attr_reader :scripts + + def initialize(config) + @config = config + @logger = config.logger + @scripts = Scripts.fetch(config.scripts_path) + end + + # + # Execute a lua script with the provided script_name + # + # @note this method is recursive if we need to load a lua script + # that wasn't previously loaded. + # + # @param [Symbol] script_name the name of the script to execute + # @param [Redis] conn the redis connection to use for execution + # @param [Array] keys script keys + # @param [Array] argv script arguments + # + # @return value from script + # + def execute(script_name, conn, keys: [], argv: []) + result, elapsed = timed do + scripts.execute(script_name, conn, keys: keys, argv: argv) + end + + logger.debug("Executed #{script_name}.lua in #{elapsed}ms") + result + rescue ::Redis::CommandError => ex + handle_error(script_name, conn, ex) do + execute(script_name, conn, keys: keys, argv: argv) + end + end + + private + + # + # Handle errors to allow retrying errors that need retrying + # + # @param [Redis::CommandError] ex exception to handle + # + # @return [void] + # + # @yieldreturn [void] yields back to the caller when NOSCRIPT is raised + def handle_error(script_name, conn, ex) + case ex.message + when /NOSCRIPT/ + handle_noscript(script_name) { return yield } + when /BUSY/ + handle_busy(conn) { return yield } + end + + raise unless LuaError.intercepts?(ex) + + script = scripts.fetch(script_name, conn) + raise LuaError.new(ex, script) + end + + def handle_noscript(script_name) + scripts.delete(script_name) + yield + end + + def handle_busy(conn) + scripts.kill(conn) + rescue ::Redis::CommandError => ex + logger.warn(ex) + ensure + yield + end + end + end +end diff --git a/lib/sidekiq_unique_jobs/redis_script/config.rb b/lib/sidekiq_unique_jobs/redis_script/config.rb new file mode 100644 index 000000000..1ab4a8518 --- /dev/null +++ b/lib/sidekiq_unique_jobs/redis_script/config.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +module SidekiqUniqueJobs + module RedisScript + # + # Class holding gem configuration + # + # @author Mikael Henriksson + class Config + # + # @!attribute [r] logger + # @return [Logger] a logger to use for debugging + attr_reader :logger + # + # @!attribute [r] scripts_path + # @return [Pathname] a directory with lua scripts + attr_reader :scripts_path + + # + # Initialize a new instance of {Config} + # + # + def initialize + @conn = RedisClient.new + @logger = Logger.new($stdout) + @scripts_path = nil + end + + # + # Sets a value for scripts_path + # + # @param [String, Pathname] obj + # + # @raise [ArgumentError] when directory does not exist + # @raise [ArgumentError] when argument isn't supported + # + # @return [Pathname] + # + def scripts_path=(obj) + raise ArgumentError, "#{obj} should be a Pathname or String" unless obj.is_a?(Pathname) || obj.is_a?(String) + raise ArgumentError, "#{obj} does not exist" unless Dir.exist?(obj.to_s) + + @scripts_path = + case obj + when String + Pathname.new(obj) + else + obj + end + end + + # + # Sets a value for logger + # + # @param [Logger] obj a logger to use + # + # @raise [ArgumentError] when given argument isn't a Logger + # + # @return [Logger] + # + def logger=(obj) + raise ArgumentError, "#{obj} should be a Logger" unless obj.is_a?(Logger) + + @logger = obj + end + end + end +end diff --git a/lib/sidekiq_unique_jobs/redis_script/dsl.rb b/lib/sidekiq_unique_jobs/redis_script/dsl.rb new file mode 100644 index 000000000..bf3eed12b --- /dev/null +++ b/lib/sidekiq_unique_jobs/redis_script/dsl.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +module SidekiqUniqueJobs + module RedisScript + # Interface to dealing with .lua files + # + # @author Mikael Henriksson + module DSL + MUTEX = Mutex.new + + def self.included(base) + base.class_eval do + extend ClassMethods + end + end + + # + # Module ClassMethods extends the base class with necessary methods + # + # @author Mikael Henriksson + # + module ClassMethods + def execute(file_name, conn, keys: [], argv: []) + SidekiqUniqueJobs::RedisScript::Client + .new(config) + .execute(file_name, conn, keys: keys, argv: argv) + end + + # Configure the gem + # + # This is usually called once at startup of an application + # @param [Hash] options global gem options + # @option options [String, Pathname] :path + # @option options [Logger] :logger (default is Logger.new(STDOUT)) + # @yield control to the caller when given block + def configure(options = {}) + if block_given? + yield config + else + options.each do |key, val| + config.send(:"#{key}=", val) + end + end + end + + # + # The current configuration (See: {.configure} on how to configure) + # + # + # @return [RedisScript::Config] the gem configuration + # + def config + MUTEX.synchronize do + @config ||= Config.new + end + end + end + end + end +end diff --git a/lib/sidekiq_unique_jobs/redis_script/logging.rb b/lib/sidekiq_unique_jobs/redis_script/logging.rb new file mode 100644 index 000000000..e844cfab7 --- /dev/null +++ b/lib/sidekiq_unique_jobs/redis_script/logging.rb @@ -0,0 +1,95 @@ +# frozen_string_literal: true + +module SidekiqUniqueJobs + module RedisScript + # Utility module for reducing the number of uses of logger. + # + # @author Mikael Henriksson + module Logging + def self.included(base) + base.send(:extend, self) + end + + # + # A convenience method for using the configured gem logger + # + # @see RedisScript#.logger + # + # @return [Logger] + # + def logger + SidekiqUniqueJobs::RedisScript.logger + end + + # + # Logs a message at debug level + # + # @param [String, Exception] message_or_exception the message or exception to log + # + # @return [void] + # + # @yield [String, Exception] the message or exception to use for log message + # + def log_debug(message_or_exception = nil, &block) + logger.debug(message_or_exception, &block) + nil + end + + # + # Logs a message at info level + # + # @param [String, Exception] message_or_exception the message or exception to log + # + # @return [void] + # + # @yield [String, Exception] the message or exception to use for log message + # + def log_info(message_or_exception = nil, &block) + logger.info(message_or_exception, &block) + nil + end + + # + # Logs a message at warn level + # + # @param [String, Exception] message_or_exception the message or exception to log + # + # @return [void] + # + # @yield [String, Exception] the message or exception to use for log message + # + def log_warn(message_or_exception = nil, &block) + logger.warn(message_or_exception, &block) + nil + end + + # + # Logs a message at error level + # + # @param [String, Exception] message_or_exception the message or exception to log + # + # @return [void] + # + # @yield [String, Exception] the message or exception to use for log message + # + def log_error(message_or_exception = nil, &block) + logger.error(message_or_exception, &block) + nil + end + + # + # Logs a message at fatal level + # + # @param [String, Exception] message_or_exception the message or exception to log + # + # @return [void] + # + # @yield [String, Exception] the message or exception to use for log message + # + def log_fatal(message_or_exception = nil, &block) + logger.fatal(message_or_exception, &block) + nil + end + end + end +end diff --git a/lib/sidekiq_unique_jobs/redis_script/lua_error.rb b/lib/sidekiq_unique_jobs/redis_script/lua_error.rb new file mode 100644 index 000000000..891af8591 --- /dev/null +++ b/lib/sidekiq_unique_jobs/redis_script/lua_error.rb @@ -0,0 +1,96 @@ +# frozen_string_literal: true + +module SidekiqUniqueJobs + module RedisScript + # + # Misconfiguration is raised when gem is misconfigured + # + # @author Mikael Henriksson + # + class Misconfiguration < RuntimeError + end + + # LuaError raised on errors in Lua scripts + # + # @author Mikael Henriksson + class LuaError < RuntimeError + # Reformats errors raised by redis representing failures while executing + # a lua script. The default errors have confusing messages and backtraces, + # and a type of +RuntimeError+. This class improves the message and + # modifies the backtrace to include the lua script itself in a reasonable + # way. + + PATTERN = /ERR Error (compiling|running) script \(.*?\): .*?:(\d+): (.*)/.freeze + LIB_PATH = File.expand_path("..", __dir__).freeze + CONTEXT_LINE_NUMBER = 2 + + attr_reader :error, :file, :content + + # Is this error one that should be reformatted? + # + # @param error [StandardError] the original error raised by redis + # @return [Boolean] is this an error that should be reformatted? + def self.intercepts?(error) + PATTERN.match?(error.message) + end + + # Initialize a new {LuaError} from an existing redis error, adjusting + # the message and backtrace in the process. + # + # @param error [StandardError] the original error raised by redis + # @param script [Script] a DTO with information about the script + # + def initialize(error, script) + @error = error + @file = script.path + @content = script.source + @backtrace = @error.backtrace + + @error.message.match(PATTERN) do |regexp_match| + line_number = regexp_match[2].to_i + message = regexp_match[3] + error_context = generate_error_context(content, line_number) + + super("#{message}\n\n#{error_context}\n\n") + set_backtrace(generate_backtrace(file, line_number)) + end + end + + private + + # :nocov: + def generate_error_context(content, line_number) + lines = content.lines.to_a + beginning_line_number = [1, line_number - CONTEXT_LINE_NUMBER].max + ending_line_number = [lines.count, line_number + CONTEXT_LINE_NUMBER].min + line_number_width = ending_line_number.to_s.length + + (beginning_line_number..ending_line_number).map do |number| + indicator = (number == line_number) ? "=>" : " " + formatted_number = format("%#{line_number_width}d", number) + " #{indicator} #{formatted_number}: #{lines[number - 1]}" + end.join.chomp + end + + # :nocov: + def generate_backtrace(file, line_number) + pre_gem = backtrace_before_entering_gem(@backtrace) + index_of_first_gem_line = (@backtrace.size - pre_gem.size - 1) + + pre_gem.unshift(@backtrace[index_of_first_gem_line]) + pre_gem.unshift("#{file}:#{line_number}") + pre_gem + end + + # :nocov: + def backtrace_before_entering_gem(backtrace) + backtrace.reverse.take_while { |line| !line_from_gem(line) }.reverse + end + + # :nocov: + def line_from_gem(line) + line.split(":").first.include?(LIB_PATH) + end + end + end +end diff --git a/lib/sidekiq_unique_jobs/redis_script/script.rb b/lib/sidekiq_unique_jobs/redis_script/script.rb new file mode 100644 index 000000000..aca98b15d --- /dev/null +++ b/lib/sidekiq_unique_jobs/redis_script/script.rb @@ -0,0 +1,80 @@ +# frozen_string_literal: true + +module SidekiqUniqueJobs + module RedisScript + # Interface to dealing with .lua files + # + # @author Mikael Henriksson + class Script + def self.load(name, root_path, conn) + script = new(name: name, root_path: root_path) + script.load(conn) + end + + # + # @!attribute [r] script_name + # @return [Symbol, String] the name of the script without extension + attr_reader :name + # + # @!attribute [r] script_path + # @return [String] the path to the script on disk + attr_reader :path + # + # @!attribute [r] root_path + # @return [Pathname] + attr_reader :root_path + # + # @!attribute [r] source + # @return [String] the source code of the lua script + attr_reader :source + # + # @!attribute [rw] sha + # @return [String] the sha of the script + attr_reader :sha + # + # @!attribute [rw] call_count + # @return [Integer] the number of times the script was called/executed + attr_reader :call_count + + def initialize(name:, root_path:) + @name = name + @root_path = root_path + @path = root_path.join("#{name}.lua").to_s + @source = render_file + @sha = compiled_sha + @call_count = 0 + end + + def ==(other) + sha == compiled_sha && compiled_sha == other.sha + end + + def increment_call_count + @call_count += 1 + end + + def changed? + compiled_sha != sha + end + + def render_file + Template.new(root_path).render(path) + end + + def compiled_sha + Digest::SHA1.hexdigest(source) + end + + def load(conn) + @sha = + if conn.respond_to?(:namespace) + conn.redis.script(:load, source) + else + conn.script(:load, source) + end + + self + end + end + end +end diff --git a/lib/sidekiq_unique_jobs/redis_script/scripts.rb b/lib/sidekiq_unique_jobs/redis_script/scripts.rb new file mode 100644 index 000000000..507b7ee87 --- /dev/null +++ b/lib/sidekiq_unique_jobs/redis_script/scripts.rb @@ -0,0 +1,123 @@ +# frozen_string_literal: true + +module SidekiqUniqueJobs + module RedisScript + # Interface to dealing with .lua files + # + # @author Mikael Henriksson + class Scripts + # + # @return [Concurrent::Map] a map with configured script paths + SCRIPT_PATHS = Concurrent::Map.new + + # + # Fetch a scripts configuration for path + # + # @param [Pathname] root_path the path to scripts + # + # @return [Scripts] a collection of scripts + # + def self.fetch(root_path) + if (scripts = SCRIPT_PATHS.get(root_path)) + return scripts + end + + create(root_path) + end + + # + # Create a new scripts collection based on path + # + # @param [Pathname] root_path the path to scripts + # + # @return [Scripts] a collection of scripts + # + def self.create(root_path) + scripts = new(root_path) + store(scripts) + end + + # + # Store the scripts collection in memory + # + # @param [Scripts] scripts the path to scripts + # + # @return [Scripts] the scripts instance that was stored + # + def self.store(scripts) + SCRIPT_PATHS.put(scripts.root_path, scripts) + scripts + end + + # + # @!attribute [r] scripts + # @return [Concurrent::Map] a collection of loaded scripts + attr_reader :scripts + + # + # @!attribute [r] root_path + # @return [Pathname] the path to the directory with lua scripts + attr_reader :root_path + + def initialize(path) + raise ArgumentError, "path needs to be a Pathname" unless path.is_a?(Pathname) + + @scripts = Concurrent::Map.new + @root_path = path + end + + def fetch(name, conn) + if (script = scripts.get(name.to_sym)) + return script + end + + load(name, conn) + end + + def load(name, conn) + script = Script.load(name, root_path, conn) + scripts.put(name.to_sym, script) + + script + end + + def delete(script) + if script.is_a?(Script) + scripts.delete(script.name) + else + scripts.delete(script.to_sym) + end + end + + def kill(conn) + if conn.respond_to?(:namespace) + conn.redis.script(:kill) + else + conn.script(:kill) + end + end + + # + # Execute a lua script with given name + # + # @note this method is recursive if we need to load a lua script + # that wasn't previously loaded. + # + # @param [Symbol] name the name of the script to execute + # @param [Redis] conn the redis connection to use for execution + # @param [Array] keys script keys + # @param [Array] argv script arguments + # + # @return value from script + # + def execute(name, conn, keys: [], argv: []) + script = fetch(name, conn) + conn.evalsha(script.sha, keys, argv) + end + + def count + scripts.keys.size + end + end + end +end diff --git a/lib/sidekiq_unique_jobs/redis_script/template.rb b/lib/sidekiq_unique_jobs/redis_script/template.rb new file mode 100644 index 000000000..4a321e2ff --- /dev/null +++ b/lib/sidekiq_unique_jobs/redis_script/template.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +module SidekiqUniqueJobs + # Interface to dealing with .lua files + # + # @author Mikael Henriksson + module RedisScript + # + # Class Template provides LUA script partial template rendering + # + # @author Mikael Henriksson + # + class Template + def initialize(script_path) + @script_path = script_path + end + + # + # Renders a Lua script and includes any partials in that file + # all `<%= include_partial '' %>` replaced with the actual contents of the partial + # + # @param [Pathname] pathname the path to the + # + # @return [String] the rendered Luascript + # + def render(pathname) + @partial_templates ||= {} + ::ERB.new(File.read(pathname)).result(binding) + end + + # helper method to include a lua partial within another lua script + # + def include_partial(relative_path) + return if @partial_templates.key?(relative_path) + + @partial_templates[relative_path] = nil + render(Pathname.new("#{@script_path}/#{relative_path}")) + end + end + end +end diff --git a/lib/sidekiq_unique_jobs/redis_script/timing.rb b/lib/sidekiq_unique_jobs/redis_script/timing.rb new file mode 100644 index 000000000..048eeeedb --- /dev/null +++ b/lib/sidekiq_unique_jobs/redis_script/timing.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +module SidekiqUniqueJobs + module RedisScript + # Handles timing> of things + # + # @author Mikael Henriksson + module Timing + module_function + + # + # Used for timing method calls + # + # + # @return [yield return, Float] + # + def timed + start_time = now + + [yield, now - start_time] + end + + # + # Returns a float representation of the current time. + # Either from Process or Time + # + # + # @return [Float] + # + def now + (Process.clock_gettime(Process::CLOCK_MONOTONIC) * 1000).to_i + end + end + end +end diff --git a/lib/sidekiq_unique_jobs/script.rb b/lib/sidekiq_unique_jobs/script.rb index 28bf36e59..c5e53cb67 100644 --- a/lib/sidekiq_unique_jobs/script.rb +++ b/lib/sidekiq_unique_jobs/script.rb @@ -5,7 +5,7 @@ module SidekiqUniqueJobs # # @author Mikael Henriksson module Script - include Brpoplpush::RedisScript::DSL + include SidekiqUniqueJobs::RedisScript::DSL configure do |config| config.scripts_path = Pathname.new(__FILE__).dirname.join("lua") diff --git a/lib/sidekiq_unique_jobs/sidekiq_unique_jobs.rb b/lib/sidekiq_unique_jobs/sidekiq_unique_jobs.rb index 923ff501d..7e1528d0a 100644 --- a/lib/sidekiq_unique_jobs/sidekiq_unique_jobs.rb +++ b/lib/sidekiq_unique_jobs/sidekiq_unique_jobs.rb @@ -186,7 +186,7 @@ def configure(options = {}) yield config else options.each do |key, val| - config.send("#{key}=", val) + config.send(:"#{key}=", val) end end end diff --git a/sidekiq-unique-jobs.gemspec b/sidekiq-unique-jobs.gemspec index 5573ca8b5..e0d188392 100644 --- a/sidekiq-unique-jobs.gemspec +++ b/sidekiq-unique-jobs.gemspec @@ -42,7 +42,6 @@ Gem::Specification.new do |spec| spec.required_ruby_version = ">= 2.7" - spec.add_dependency "brpoplpush-redis_script", "> 0.1.1", "<= 2.0.0" spec.add_dependency "concurrent-ruby", "~> 1.0", ">= 1.0.5" spec.add_dependency "sidekiq", ">= 7.0.0", "< 8.0.0" spec.add_dependency "thor", ">= 1.0", "< 3.0" diff --git a/spec/sidekiq_unique_jobs/web_spec.rb b/spec/sidekiq_unique_jobs/web_spec.rb index f711f9f3c..a84744a91 100644 --- a/spec/sidekiq_unique_jobs/web_spec.rb +++ b/spec/sidekiq_unique_jobs/web_spec.rb @@ -2,6 +2,7 @@ require "sidekiq_unique_jobs/web" require "rack/test" +require "rack/session" require "rspec-html-matchers" RSpec.describe SidekiqUniqueJobs::Web do @@ -15,8 +16,8 @@ def app domain: "foo.com", path: "/", expire_after: 2_592_000, - secret: "change_me", - old_secret: "also_change_me" + secret: "change_me" * 10, + old_secret: "also_change_me" * 10 run Sidekiq::Web end diff --git a/spec/support/sidekiq_meta.rb b/spec/support/sidekiq_meta.rb index 10ef6d95c..f927a7808 100644 --- a/spec/support/sidekiq_meta.rb +++ b/spec/support/sidekiq_meta.rb @@ -19,7 +19,7 @@ if (sidekiq = example.metadata.fetch(:sidekiq, :disable)) sidekiq = :fake if sidekiq == true - Sidekiq::Testing.send("#{sidekiq}!") + Sidekiq::Testing.send(:"#{sidekiq}!") end if (sidekiq_ver = example.metadata[:sidekiq_ver]) diff --git a/spec/support/sidekiq_unique_jobs/testing.rb b/spec/support/sidekiq_unique_jobs/testing.rb index 19f3d0138..765521bec 100644 --- a/spec/support/sidekiq_unique_jobs/testing.rb +++ b/spec/support/sidekiq_unique_jobs/testing.rb @@ -75,8 +75,8 @@ def lastsave redis(&:lastsave) end - def monitor(&block) - redis { |conn| conn.monitor(&block) } + def monitor(...) + redis { |conn| conn.monitor(...) } end def save