From d279457fd1f03f2899829e8c8f906e6e0b6c0487 Mon Sep 17 00:00:00 2001 From: mhenrixon Date: Sat, 2 Apr 2022 12:41:14 +0200 Subject: [PATCH] Sidekiq seems to be dropping the default [] Keep it to ensure consistency with new sidekiq versions --- lib/sidekiq_unique_jobs/lock_args.rb | 123 +++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/lib/sidekiq_unique_jobs/lock_args.rb b/lib/sidekiq_unique_jobs/lock_args.rb index dfe385d1e..013400c98 100644 --- a/lib/sidekiq_unique_jobs/lock_args.rb +++ b/lib/sidekiq_unique_jobs/lock_args.rb @@ -1,5 +1,128 @@ # frozen_string_literal: true +module SidekiqUniqueJobs + # Handles uniqueness of sidekiq arguments + # + # @author Mikael Henriksson + class LockArgs + include SidekiqUniqueJobs::Logging + include SidekiqUniqueJobs::SidekiqWorkerMethods + include SidekiqUniqueJobs::JSON + + # Convenience method for returning a digest + # @param [Hash] item a Sidekiq job hash + # @return [String] a unique digest + def self.call(item) + new(item).lock_args + end + + # The sidekiq job hash + # @return [Hash] the Sidekiq job hash + attr_reader :item + # + # @!attribute [r] args + # @return [Array] the arguments passed to `perform_async` + attr_reader :args + + # @param [Hash] item a Sidekiq job hash + def initialize(item) + @item = item + @worker_class = item[CLASS] + @args = item[ARGS] + end + + # The unique arguments to use for creating a lock + # @return [Array] the arguments filters by the {#filtered_args} method if {#lock_args_enabled?} + def lock_args + @lock_args ||= filtered_args || [] + end + + # Checks if the worker class has enabled lock_args + # @return [true, false] + def lock_args_enabled? + # return false unless lock_args_method_valid? + + lock_args_method + end + + # Validate that the lock_args_method is acceptable + # @return [true, false] + def lock_args_method_valid? + [NilClass, TrueClass, FalseClass].none? { |klass| lock_args_method.is_a?(klass) } + end + + # Checks if the worker class has disabled lock_args + # @return [true, false] + def lock_args_disabled? + !lock_args_method + end + + # Filters unique arguments by proc or symbol + # @return [Array] {#filter_by_proc} when {#lock_args_method} is a Proc + # @return [Array] {#filter_by_symbol} when {#lock_args_method} is a Symbol + # @return [Array] args unfiltered when neither of the above + def filtered_args + return args if lock_args_disabled? + + json_args = Normalizer.jsonify(args) + + case lock_args_method + when Proc + filter_by_proc(json_args) + when Symbol + filter_by_symbol(json_args) + end + end + + # Filters unique arguments by proc configured in the sidekiq worker + # @param [Array] args the arguments passed to the sidekiq worker + # @return [Array] with the filtered arguments + def filter_by_proc(args) + lock_args_method.call(args) + end + + # Filters unique arguments by method configured in the sidekiq worker + # @param [Array] args the arguments passed to the sidekiq worker + # @return [Array] unfiltered unless {#worker_method_defined?} + # @return [Array] with the filtered arguments + def filter_by_symbol(args) + return args unless worker_method_defined?(lock_args_method) + + worker_class.send(lock_args_method, args) + rescue ArgumentError + raise SidekiqUniqueJobs::InvalidUniqueArguments, + given: args, + worker_class: worker_class, + lock_args_method: lock_args_method + end + + # The method to use for filtering unique arguments + def lock_args_method + @lock_args_method ||= worker_options.slice(LOCK_ARGS_METHOD, UNIQUE_ARGS_METHOD).values.first + @lock_args_method ||= :lock_args if worker_method_defined?(:lock_args) + @lock_args_method ||= :unique_args if worker_method_defined?(:unique_args) + @lock_args_method ||= default_lock_args_method + end + + # The global worker options defined in Sidekiq directly + def default_lock_args_method + default_worker_options[LOCK_ARGS_METHOD] || + default_worker_options[UNIQUE_ARGS_METHOD] + end + + # + # The globally default worker options configured from Sidekiq + # + # + # @return [Hash] + # + def default_worker_options + @default_worker_options ||= Sidekiq.default_worker_options.stringify_keys + end + end +end +# frozen_string_literal: true + module SidekiqUniqueJobs # Handles uniqueness of sidekiq arguments #