lib/sidekiq/rescue/dsl.rb
# frozen_string_literal: true module Sidekiq module Rescue # This module is included into the job class to provide the Dsl for # configuring rescue options. module Dsl def self.included(base) base.extend(ClassMethods) base.sidekiq_class_attribute(:sidekiq_rescue_options) end # Module containing the Dsl methods module ClassMethods # Configure rescue options for the job. # @param error [StandardError] The error class to rescue. # @param error [Array<StandardError>] The error classes to rescue. # @param delay [Integer, Float, Proc] The delay in seconds before retrying the job. # @param limit [Integer] The maximum number of retries. # @return [void] # @raise [ArgumentError] if error is not a StandardError # @raise [ArgumentError] if error is not an array of StandardError # @raise [ArgumentError] if delay is not an Integer or Float # @raise [ArgumentError] if limit is not an Integer # @example # sidekiq_rescue NetworkError, delay: 60, limit: 10 def sidekiq_rescue(*errors, delay: Sidekiq::Rescue.config.delay, limit: Sidekiq::Rescue.config.limit) unpacked_errors = validate_and_unpack_error_argument(errors) validate_delay_argument(delay) validate_limit_argument(limit) assign_sidekiq_rescue_options(unpacked_errors, delay, limit) end def sidekiq_rescue_options_for(error) sidekiq_rescue_options&.find { |k, _v| k.include?(error) }&.last end private def validate_and_unpack_error_argument(error) error_arg_valid = error.any? && error.flatten.all? { |e| e < StandardError } if error.is_a?(Array) return error.flatten if error_arg_valid raise ArgumentError, "error must be an ancestor of StandardError" end def validate_delay_argument(delay) return if delay.nil? return if delay.is_a?(Integer) || delay.is_a?(Float) if delay.is_a?(Proc) raise ArgumentError, "delay proc must accept counter as argument" if delay.arity.zero? return end raise ArgumentError, "delay must be integer, float or proc" end def validate_limit_argument(limit) raise ArgumentError, "limit must be integer" if limit && !limit.is_a?(Integer) end def assign_sidekiq_rescue_options(errors, delay, limit) self.sidekiq_rescue_options ||= {} self.sidekiq_rescue_options.merge!(errors => { delay: delay, limit: limit }) end end end # Alias for Dsl; TODO: remove in 1.0.0 # @deprecated # @see Dsl DSL = Dsl end end