Class: Resque::UniqueByArity::Configuration

Inherits:
Object
  • Object
show all
Defined in:
lib/resque/unique_by_arity/configuration.rb

Overview

This class is for configurations that are per job class, not app-wide. Each setting will default to the global config values.

Direct Known Subclasses

GlobalConfiguration

Constant Summary collapse

VALID_ARITY_VALIDATION_LEVELS =
[:warning, :error, :skip, nil, false].freeze
SKIPPED_ARITY_VALIDATION_LEVELS =
[:skip, nil, false].freeze
DEFAULT_LOG_LEVEL =
:debug

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(**options) ⇒ Configuration

Returns a new instance of Configuration.

Raises:

  • (ArgumentError)


27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/resque/unique_by_arity/configuration.rb', line 27

def initialize(**options)
  @logger = options.key?(:logger) ? options[:logger] : defcon(:logger) || Logger.new(STDOUT)
  @log_level = options.key?(:log_level) ? options[:log_level] : defcon(:log_level) || :debug
  @arity_for_uniqueness = options.key?(:arity_for_uniqueness) ? options[:arity_for_uniqueness] : defcon(:arity_for_uniqueness) || 1
  @arity_validation = options.key?(:arity_validation) ? options[:arity_validation] : defcon(:arity_validation) || :warning
  raise ArgumentError, "Resque::Plugins::UniqueByArity.new requires arity_validation values of #{arity_validation.inspect}, or a class inheriting from Exception, but the value is #{@arity_validation} (#{@arity_validation.class})" unless VALID_ARITY_VALIDATION_LEVELS.include?(@arity_validation) || !@arity_validation.respond_to?(:ancestors) || @arity_validation.ancestors.include?(Exception)

  @ttl = options.key?(:ttl) ? options[:ttl] : defcon(:ttl) || nil
  @lock_after_execution_period = options.key?(:lock_after_execution_period) ? options[:lock_after_execution_period] : defcon(:lock_after_execution_period) || nil
  @runtime_lock_timeout = options.key?(:runtime_lock_timeout) ? options[:runtime_lock_timeout] : defcon(:runtime_lock_timeout) || nil
  @runtime_requeue_interval = options.key?(:runtime_requeue_interval) ? options[:runtime_requeue_interval] : defcon(:runtime_requeue_interval) || nil
  @unique_at_runtime = options.key?(:unique_at_runtime) ? options[:unique_at_runtime] : defcon(:unique_at_runtime) || false
  @unique_at_runtime_key_base = options.key?(:unique_at_runtime_key_base) ? options[:unique_at_runtime_key_base] : defcon(:unique_at_runtime_key_base) || nil
  @unique_in_queue_key_base = options.key?(:unique_in_queue_key_base) ? options[:unique_in_queue_key_base] : defcon(:unique_in_queue_key_base) || nil
  @unique_in_queue = options.key?(:unique_in_queue) ? options[:unique_in_queue] : defcon(:unique_in_queue) || false
  @unique_across_queues = options.key?(:unique_across_queues) ? options[:unique_across_queues] : defcon(:unique_across_queues) || false
  # Can't be both unique in queue and unique across queues, since they
  #   must necessarily use different locking key structures, and therefore
  #   can't both be active.
  raise ArgumentError, "Resque::Plugins::UniqueByArity.new requires either one or none of @unique_across_queues and @unique_in_queue to be true. Having both set to true is non-sensical." if @unique_in_queue && @unique_across_queues
  @debug_mode = !!(options.key?(:debug_mode) ? options[:debug_mode] : defcon(:debug_mode))
  if @debug_mode
    # Make sure there is a logger when in debug_mode
    @logger ||= Logger.new(STDOUT)
  end
end

Instance Attribute Details

#arity_for_uniquenessObject

Returns the value of attribute arity_for_uniqueness.



13
14
15
# File 'lib/resque/unique_by_arity/configuration.rb', line 13

def arity_for_uniqueness
  @arity_for_uniqueness
end

#arity_validationObject

Returns the value of attribute arity_validation.



14
15
16
# File 'lib/resque/unique_by_arity/configuration.rb', line 14

def arity_validation
  @arity_validation
end

#base_klass_nameObject

Returns the value of attribute base_klass_name.



24
25
26
# File 'lib/resque/unique_by_arity/configuration.rb', line 24

def base_klass_name
  @base_klass_name
end

#debug_modeObject

Returns the value of attribute debug_mode.



25
26
27
# File 'lib/resque/unique_by_arity/configuration.rb', line 25

def debug_mode
  @debug_mode
end

#lock_after_execution_periodObject

Returns the value of attribute lock_after_execution_period.



15
16
17
# File 'lib/resque/unique_by_arity/configuration.rb', line 15

def lock_after_execution_period
  @lock_after_execution_period
end

#log_levelObject

Returns the value of attribute log_level.



12
13
14
# File 'lib/resque/unique_by_arity/configuration.rb', line 12

def log_level
  @log_level
end

#loggerObject

Returns the value of attribute logger.



11
12
13
# File 'lib/resque/unique_by_arity/configuration.rb', line 11

def logger
  @logger
end

#runtime_lock_timeoutObject

Returns the value of attribute runtime_lock_timeout.



16
17
18
# File 'lib/resque/unique_by_arity/configuration.rb', line 16

def runtime_lock_timeout
  @runtime_lock_timeout
end

#runtime_requeue_intervalObject

Returns the value of attribute runtime_requeue_interval.



17
18
19
# File 'lib/resque/unique_by_arity/configuration.rb', line 17

def runtime_requeue_interval
  @runtime_requeue_interval
end

#ttlObject

Returns the value of attribute ttl.



23
24
25
# File 'lib/resque/unique_by_arity/configuration.rb', line 23

def ttl
  @ttl
end

#unique_across_queuesObject

Returns the value of attribute unique_across_queues.



22
23
24
# File 'lib/resque/unique_by_arity/configuration.rb', line 22

def unique_across_queues
  @unique_across_queues
end

#unique_at_runtimeObject

Returns the value of attribute unique_at_runtime.



18
19
20
# File 'lib/resque/unique_by_arity/configuration.rb', line 18

def unique_at_runtime
  @unique_at_runtime
end

#unique_at_runtime_key_baseObject

Returns the value of attribute unique_at_runtime_key_base.



19
20
21
# File 'lib/resque/unique_by_arity/configuration.rb', line 19

def unique_at_runtime_key_base
  @unique_at_runtime_key_base
end

#unique_in_queueObject

Returns the value of attribute unique_in_queue.



20
21
22
# File 'lib/resque/unique_by_arity/configuration.rb', line 20

def unique_in_queue
  @unique_in_queue
end

#unique_in_queue_key_baseObject

Returns the value of attribute unique_in_queue_key_base.



21
22
23
# File 'lib/resque/unique_by_arity/configuration.rb', line 21

def unique_in_queue_key_base
  @unique_in_queue_key_base
end

Instance Method Details

#defcon(sym) ⇒ Object



128
129
130
# File 'lib/resque/unique_by_arity/configuration.rb', line 128

def defcon(sym)
  Resque::UniqueByArity.configuration.send(sym)
end

#log(msg) ⇒ Object



65
66
67
# File 'lib/resque/unique_by_arity/configuration.rb', line 65

def log(msg)
  Resque::UniqueByArity.log(msg, self)
end

#skip_arity_validation?Boolean

Returns:

  • (Boolean)


86
87
88
# File 'lib/resque/unique_by_arity/configuration.rb', line 86

def skip_arity_validation?
  SKIPPED_ARITY_VALIDATION_LEVELS.include?(arity_validation)
end

#to_hashObject



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/resque/unique_by_arity/configuration.rb', line 69

def to_hash
  {
    log_level: log_level,
    logger: logger,
    arity_for_uniqueness: arity_for_uniqueness,
    arity_validation: arity_validation,
    base_klass_name: base_klass_name,
    debug_mode: debug_mode,
    lock_after_execution_period: lock_after_execution_period,
    runtime_lock_timeout: runtime_lock_timeout,
    ttl: ttl,
    unique_at_runtime: unique_at_runtime,
    unique_in_queue: unique_in_queue,
    unique_across_queues: unique_across_queues
  }
end

#validateObject



54
55
56
57
58
59
60
61
62
63
# File 'lib/resque/unique_by_arity/configuration.rb', line 54

def validate
  # The default config initialization shouldn't trigger any warnings.
  if base_klass_name && logger
    log "[#{base_klass_name}] :arity_for_uniqueness is set to #{arity_for_uniqueness}, but no uniqueness enforcement was turned on [:unique_at_runtime, :unique_in_queue, :unique_across_queues]" unless unique_at_runtime || unique_in_queue || unique_across_queues
    log "[#{base_klass_name}] :lock_after_execution_period is set to #{lock_after_execution_period}, but :unique_at_runtime is not set" if lock_after_execution_period && !(unique_in_queue || unique_across_queues)
    log "[#{base_klass_name}] :runtime_lock_timeout is set to #{runtime_lock_timeout}, but :unique_at_runtime is not set" if runtime_lock_timeout && !unique_at_runtime
    log "[#{base_klass_name}] :runtime_requeue_interval is set to #{runtime_requeue_interval}, but :unique_at_runtime is not set" if runtime_requeue_interval && !unique_at_runtime
    log "[#{base_klass_name}] :unique_in_queue and :unique_across_queues should not be set at the same time, as :unique_across_queues will always supercede :unique_in_queue" if unique_in_queue && unique_across_queues
  end
end

#validate_arity(klass_string, perform_method) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/resque/unique_by_arity/configuration.rb', line 90

def validate_arity(klass_string, perform_method)
  return true if skip_arity_validation?

  # method.arity -
  #   Returns an indication of the number of arguments accepted by a method.
  #   Returns a non-negative integer for methods that take a fixed number of arguments.
  #   For Ruby methods that take a variable number of arguments, returns -n-1, where n is the number of required arguments.
  #   For methods written in C, returns -1 if the call takes a variable number of arguments.
  # Example:
  #   for perform(opts = {}), method(:perform).arity # => -1
  #   which means that the only valid arity_for_uniqueness is 0
  msg = if perform_method.arity >= 0
          # takes a fixed number of arguments
          # parform(a, b, c) # => arity == 3, so arity for uniqueness can be 0, 1, 2, or 3
          if perform_method.arity < arity_for_uniqueness
            "#{klass_string}.#{perform_method.name} has arity of #{perform_method.arity} which will not work with arity_for_uniqueness of #{arity_for_uniqueness}"
          end
        else
          if perform_method.arity.abs < arity_for_uniqueness
            # parform(a, b, c, opts = {}) # => arity == -4
            #   and in this case arity for uniqueness can be 0, 1, 2, or 3, because 4 of the arguments are required
            "#{klass_string}.#{perform_method.name} has arity of #{perform_method.arity} which will not work with arity_for_uniqueness of #{arity_for_uniqueness}"
          elsif (required_parameter_names = perform_method.parameters.take_while { |a| a[0] == :req }.map { |b| b[1] }).length < arity_for_uniqueness
            "#{klass_string}.#{perform_method.name} has the following required parameters: #{required_parameter_names}, which is not enough to satisfy the configured arity_for_uniqueness of #{arity_for_uniqueness}"
          end
        end
  if msg
    case arity_validation
    when :warning then
      log(ColorizedString[msg].red)
    when :error then
      raise ArgumentError, msg
    else
      raise arity_validation, msg
    end
  end
end