Class: SidekiqUniqueJobs::UniqueArgs

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Normalizer
Defined in:
lib/sidekiq_unique_jobs/unique_args.rb

Overview

This class exists to be testable and the entire api should be considered private rubocop:disable ClassLength

Constant Summary collapse

CLASS_NAME =
'SidekiqUniqueJobs::UniqueArgs'.freeze

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Normalizer

jsonify

Constructor Details

#initialize(job) ⇒ UniqueArgs

Returns a new instance of UniqueArgs.



19
20
21
22
23
24
25
26
27
# File 'lib/sidekiq_unique_jobs/unique_args.rb', line 19

def initialize(job)
  Sidekiq::Logging.with_context(CLASS_NAME) do
    @item = job
    @worker_class ||= worker_class_constantize(@item[CLASS_KEY])
    @item[UNIQUE_PREFIX_KEY] ||= unique_prefix
    @item[UNIQUE_ARGS_KEY] = unique_args(@item[ARGS_KEY]) # SIC! Calculate unique_args unconditionally
    @item[UNIQUE_DIGEST_KEY] ||= unique_digest
  end
end

Class Method Details

.digest(item) ⇒ Object



15
16
17
# File 'lib/sidekiq_unique_jobs/unique_args.rb', line 15

def self.digest(item)
  new(item).unique_digest
end

Instance Method Details

#digestable_hashObject



43
44
45
46
47
48
49
50
51
52
53
# File 'lib/sidekiq_unique_jobs/unique_args.rb', line 43

def digestable_hash
  hash = @item.slice(CLASS_KEY, QUEUE_KEY, UNIQUE_ARGS_KEY)

  if unique_on_all_queues?
    logger.debug do
      "uniqueness specified across all queues (deleting queue: #{@item[QUEUE_KEY]} from hash)"
    end
    hash.delete(QUEUE_KEY)
  end
  hash
end

#filter_by_proc(args) ⇒ Object



104
105
106
107
108
109
110
111
112
# File 'lib/sidekiq_unique_jobs/unique_args.rb', line 104

def filter_by_proc(args)
  if unique_args_method.nil?
    warn { "#{__method__} : Proc was nil, returning args as is #{args} -> #{filter_args}" }
    return args
  end
  filter_args = unique_args_method.call(args)
  logger.debug { "#{__method__} : #{args} -> #{filter_args}" }
  filter_args
end

#filter_by_symbol(args) ⇒ Object



114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/sidekiq_unique_jobs/unique_args.rb', line 114

def filter_by_symbol(args)
  unless @worker_class.respond_to?(unique_args_method)
    logger.warn do
      "#{__method__} : #{unique_args_method}) not defined in #{@worker_class} " \
           "returning #{args} unchanged"
    end
    return args
  end

  filter_args = @worker_class.send(unique_args_method, args)
  logger.debug { "#{__method__} : #{unique_args_method}(#{args}) => #{filter_args}" }
  filter_args
end

#filtered_args(args) ⇒ Object

Filters unique arguments by proc or symbol returns provided arguments for other configurations



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/sidekiq_unique_jobs/unique_args.rb', line 88

def filtered_args(args)
  return args if args.empty?
  json_args = Normalizer.jsonify(args)
  logger.debug { "#filtered_args #{args} => #{json_args}" }

  case unique_args_method
  when Proc
    filter_by_proc(json_args)
  when Symbol
    filter_by_symbol(json_args)
  else
    logger.debug { 'arguments not filtered (the combined arguments count towards uniqueness)' }
    json_args
  end
end

#sidekiq_worker_class?Boolean

Returns:

  • (Boolean)


77
78
79
80
81
82
83
84
# File 'lib/sidekiq_unique_jobs/unique_args.rb', line 77

def sidekiq_worker_class?
  if @worker_class.respond_to?(:get_sidekiq_options)
    true
  else
    logger.debug { "#{@worker_class} does not respond to :get_sidekiq_options" }
    nil
  end
end

#unique_args(args) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
# File 'lib/sidekiq_unique_jobs/unique_args.rb', line 55

def unique_args(args)
  if unique_args_enabled?
    filtered_args(args)
  else
    logger.debug { "#{__method__} : unique arguments disabled" }
    args
  end
rescue NameError
  # fallback to not filtering args when class can't be instantiated
  return args
end

#unique_args_enabled?Boolean

Returns:

  • (Boolean)


72
73
74
75
# File 'lib/sidekiq_unique_jobs/unique_args.rb', line 72

def unique_args_enabled?
  return unless sidekiq_worker_class?
  unique_args_method # && !unique_args_method.is_a?(Boolean)
end

#unique_args_methodObject



128
129
130
131
132
# File 'lib/sidekiq_unique_jobs/unique_args.rb', line 128

def unique_args_method
  @unique_args_method ||= @worker_class.get_sidekiq_options[UNIQUE_ARGS_KEY] if sidekiq_worker_class?
  @unique_args_method ||= :unique_args if @worker_class.respond_to?(:unique_args)
  @unique_args_method ||= Sidekiq.default_worker_options.stringify_keys[UNIQUE_ARGS_KEY]
end

#unique_digestObject



29
30
31
32
33
34
35
36
# File 'lib/sidekiq_unique_jobs/unique_args.rb', line 29

def unique_digest
  @unique_digest ||= begin
    digest = Digest::MD5.hexdigest(Sidekiq.dump_json(digestable_hash))
    digest = "#{unique_prefix}:#{digest}"
    logger.debug { "#{__method__} : #{digestable_hash} into #{digest}" }
    digest
  end
end

#unique_on_all_queues?Boolean

Returns:

  • (Boolean)


67
68
69
70
# File 'lib/sidekiq_unique_jobs/unique_args.rb', line 67

def unique_on_all_queues?
  return unless sidekiq_worker_class?
  @item[UNIQUE_ON_ALL_QUEUES_KEY] || @worker_class.get_sidekiq_options[UNIQUE_ON_ALL_QUEUES_KEY]
end

#unique_prefixObject



38
39
40
41
# File 'lib/sidekiq_unique_jobs/unique_args.rb', line 38

def unique_prefix
  return config.unique_prefix unless sidekiq_worker_class?
  @worker_class.get_sidekiq_options[UNIQUE_PREFIX_KEY] || config.unique_prefix
end