sidekiq-unique-jobs 8.0.9 → 8.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +39 -2
  3. data/README.md +56 -43
  4. data/lib/sidekiq_unique_jobs/cli.rb +2 -2
  5. data/lib/sidekiq_unique_jobs/config.rb +51 -32
  6. data/lib/sidekiq_unique_jobs/digests.rb +1 -1
  7. data/lib/sidekiq_unique_jobs/exceptions.rb +2 -2
  8. data/lib/sidekiq_unique_jobs/lock/base_lock.rb +1 -1
  9. data/lib/sidekiq_unique_jobs/lock/while_executing.rb +1 -1
  10. data/lib/sidekiq_unique_jobs/lock.rb +1 -1
  11. data/lib/sidekiq_unique_jobs/lock_args.rb +3 -3
  12. data/lib/sidekiq_unique_jobs/lock_digest.rb +6 -1
  13. data/lib/sidekiq_unique_jobs/lock_ttl.rb +28 -6
  14. data/lib/sidekiq_unique_jobs/locksmith.rb +13 -8
  15. data/lib/sidekiq_unique_jobs/logging.rb +2 -2
  16. data/lib/sidekiq_unique_jobs/lua/delete.lua +6 -5
  17. data/lib/sidekiq_unique_jobs/lua/lock.lua +16 -7
  18. data/lib/sidekiq_unique_jobs/lua/queue.lua +9 -8
  19. data/lib/sidekiq_unique_jobs/lua/shared/_delete_from_queue.lua +10 -10
  20. data/lib/sidekiq_unique_jobs/lua/shared/_delete_from_sorted_set.lua +20 -10
  21. data/lib/sidekiq_unique_jobs/lua/unlock.lua +10 -9
  22. data/lib/sidekiq_unique_jobs/on_conflict/reject.rb +10 -1
  23. data/lib/sidekiq_unique_jobs/on_conflict/replace.rb +3 -3
  24. data/lib/sidekiq_unique_jobs/on_conflict/reschedule.rb +1 -1
  25. data/lib/sidekiq_unique_jobs/on_conflict.rb +2 -2
  26. data/lib/sidekiq_unique_jobs/orphans/manager.rb +3 -3
  27. data/lib/sidekiq_unique_jobs/orphans/ruby_reaper.rb +4 -5
  28. data/lib/sidekiq_unique_jobs/reflections.rb +3 -3
  29. data/lib/sidekiq_unique_jobs/sidekiq_unique_ext.rb +2 -2
  30. data/lib/sidekiq_unique_jobs/sidekiq_unique_jobs.rb +4 -4
  31. data/lib/sidekiq_unique_jobs/sidekiq_worker_methods.rb +1 -1
  32. data/lib/sidekiq_unique_jobs/testing.rb +2 -2
  33. data/lib/sidekiq_unique_jobs/version.rb +1 -1
  34. data/lib/sidekiq_unique_jobs/web/helpers.rb +29 -1
  35. data/lib/sidekiq_unique_jobs/web.rb +38 -30
  36. metadata +5 -8
@@ -66,12 +66,34 @@ module SidekiqUniqueJobs
66
66
  # @return [Integer] the number of seconds to live
67
67
  #
68
68
  def calculate
69
- ttl = item[LOCK_TTL]
70
- ttl ||= job_options[LOCK_TTL]
71
- ttl ||= item[LOCK_EXPIRATION] # TODO: Deprecate at some point
72
- ttl ||= job_options[LOCK_EXPIRATION] # TODO: Deprecate at some point
73
- ttl ||= SidekiqUniqueJobs.config.lock_ttl
74
- ttl && (ttl.to_i + time_until_scheduled)
69
+ ttl = fetch_ttl
70
+ return unless ttl
71
+
72
+ timing = calculate_timing(ttl)
73
+ return unless timing
74
+
75
+ timing.to_i + time_until_scheduled
76
+ end
77
+
78
+ private
79
+
80
+ def fetch_ttl
81
+ item[LOCK_TTL] ||
82
+ job_options[LOCK_TTL] ||
83
+ item[LOCK_EXPIRATION] || # TODO: Deprecate at some point
84
+ job_options[LOCK_EXPIRATION] || # TODO: Deprecate at some point
85
+ SidekiqUniqueJobs.config.lock_ttl
86
+ end
87
+
88
+ def calculate_timing(ttl)
89
+ case ttl
90
+ when String, Numeric
91
+ ttl
92
+ when Proc
93
+ ttl.call(item[ARGS])
94
+ when Symbol
95
+ job_class.send(ttl, item[ARGS])
96
+ end
75
97
  end
76
98
  end
77
99
  end
@@ -4,7 +4,7 @@ module SidekiqUniqueJobs
4
4
  # Lock manager class that handles all the various locks
5
5
  #
6
6
  # @author Mikael Henriksson <mikael@mhenrixon.com>
7
- class Locksmith # rubocop:disable Metrics/ClassLength
7
+ class Locksmith
8
8
  # includes "SidekiqUniqueJobs::Connection"
9
9
  # @!parse include SidekiqUniqueJobs::Connection
10
10
  include SidekiqUniqueJobs::Connection
@@ -82,7 +82,7 @@ module SidekiqUniqueJobs
82
82
  # Deletes the lock regardless of if it has a pttl set
83
83
  #
84
84
  def delete!
85
- call_script(:delete, key.to_a, [job_id, config.pttl, config.type, config.limit]).to_i.positive?
85
+ call_script(:delete, key.to_a, argv).to_i.positive?
86
86
  end
87
87
 
88
88
  #
@@ -243,7 +243,7 @@ module SidekiqUniqueJobs
243
243
  # @return [nil] when lock was not possible
244
244
  # @return [Object] whatever the block returns when lock was acquired
245
245
  #
246
- def primed_async(conn, wait = nil, &block) # rubocop:disable Metrics/MethodLength
246
+ def primed_async(conn, wait = nil, &block)
247
247
  timeout = (wait || config.timeout).to_i
248
248
  timeout = 1 if timeout.zero?
249
249
 
@@ -251,10 +251,10 @@ module SidekiqUniqueJobs
251
251
  concurrent_timeout = add_drift(timeout)
252
252
 
253
253
  reflect(:debug, :timeouts, item,
254
- timeouts: {
255
- brpoplpush_timeout: brpoplpush_timeout,
256
- concurrent_timeout: concurrent_timeout,
257
- })
254
+ timeouts: {
255
+ brpoplpush_timeout: brpoplpush_timeout,
256
+ concurrent_timeout: concurrent_timeout,
257
+ })
258
258
 
259
259
  # NOTE: When debugging, change .value to .value!
260
260
  primed_jid = Concurrent::Promises
@@ -362,7 +362,11 @@ module SidekiqUniqueJobs
362
362
  end
363
363
 
364
364
  def argv
365
- [job_id, config.pttl, config.type, config.limit]
365
+ [job_id, config.pttl, config.type, config.limit, lock_score]
366
+ end
367
+
368
+ def lock_score
369
+ item[AT].to_s
366
370
  end
367
371
 
368
372
  def lock_info
@@ -375,6 +379,7 @@ module SidekiqUniqueJobs
375
379
  TYPE => config.type,
376
380
  LOCK_ARGS => item[LOCK_ARGS],
377
381
  TIME => now_f,
382
+ AT => item[AT],
378
383
  )
379
384
  end
380
385
 
@@ -223,8 +223,8 @@ module SidekiqUniqueJobs
223
223
  end
224
224
 
225
225
  def fake_logger_context(_context)
226
- logger.warn "Don't know how to setup the logging context. Please open a feature request:" \
227
- " https://github.com/mhenrixon/sidekiq-unique-jobs/issues/new?template=feature_request.md"
226
+ logger.warn "Don't know how to setup the logging context. Please open a feature request: " \
227
+ "https://github.com/mhenrixon/sidekiq-unique-jobs/issues/new?template=feature_request.md"
228
228
 
229
229
  yield
230
230
  end
@@ -13,14 +13,15 @@ local job_id = ARGV[1]
13
13
  local pttl = tonumber(ARGV[2])
14
14
  local lock_type = ARGV[3]
15
15
  local limit = tonumber(ARGV[4])
16
+ local lock_score = ARGV[5]
16
17
  -------- END lock arguments -----------
17
18
 
18
19
  -------- BEGIN injected arguments --------
19
- local current_time = tonumber(ARGV[5])
20
- local debug_lua = tostring(ARGV[6]) == "1"
21
- local max_history = tonumber(ARGV[7])
22
- local script_name = tostring(ARGV[8]) .. ".lua"
23
- local redisversion = tostring(ARGV[9])
20
+ local current_time = tonumber(ARGV[6])
21
+ local debug_lua = tostring(ARGV[7]) == "1"
22
+ local max_history = tonumber(ARGV[8])
23
+ local script_name = tostring(ARGV[9]) .. ".lua"
24
+ local redisversion = tostring(ARGV[10])
24
25
  --------- END injected arguments ---------
25
26
 
26
27
  -------- BEGIN local functions --------
@@ -15,15 +15,16 @@ local job_id = ARGV[1]
15
15
  local pttl = tonumber(ARGV[2])
16
16
  local lock_type = ARGV[3]
17
17
  local limit = tonumber(ARGV[4])
18
+ local lock_score = ARGV[5]
18
19
  -------- END lock arguments -----------
19
20
 
20
21
 
21
22
  -------- BEGIN injected arguments --------
22
- local current_time = tonumber(ARGV[5])
23
- local debug_lua = tostring(ARGV[6]) == "1"
24
- local max_history = tonumber(ARGV[7])
25
- local script_name = tostring(ARGV[8]) .. ".lua"
26
- local redisversion = ARGV[9]
23
+ local current_time = tonumber(ARGV[6])
24
+ local debug_lua = tostring(ARGV[7]) == "1"
25
+ local max_history = tonumber(ARGV[8])
26
+ local script_name = tostring(ARGV[9]) .. ".lua"
27
+ local redisversion = ARGV[10]
27
28
  --------- END injected arguments ---------
28
29
 
29
30
 
@@ -62,8 +63,16 @@ if lock_type == "until_expired" and pttl and pttl > 0 then
62
63
  log_debug("ZADD", expiring_digests, current_time + pttl, digest)
63
64
  redis.call("ZADD", expiring_digests, current_time + pttl, digest)
64
65
  else
65
- log_debug("ZADD", digests, current_time, digest)
66
- redis.call("ZADD", digests, current_time, digest)
66
+ local score
67
+
68
+ if #lock_score == 0 then
69
+ score = current_time
70
+ else
71
+ score = lock_score
72
+ end
73
+
74
+ log_debug("ZADD", digests, score, digest)
75
+ redis.call("ZADD", digests, score, digest)
67
76
  end
68
77
 
69
78
  log_debug("HSET", locked, job_id, current_time)
@@ -10,18 +10,19 @@ local digests = KEYS[7]
10
10
 
11
11
 
12
12
  -------- BEGIN lock arguments ---------
13
- local job_id = ARGV[1] -- The job_id that was previously primed
14
- local pttl = tonumber(ARGV[2])
15
- local lock_type = ARGV[3]
16
- local limit = tonumber(ARGV[4])
13
+ local job_id = ARGV[1] -- The job_id that was previously primed
14
+ local pttl = tonumber(ARGV[2])
15
+ local lock_type = ARGV[3]
16
+ local limit = tonumber(ARGV[4])
17
+ local lock_score = ARGV[5]
17
18
  -------- END lock arguments -----------
18
19
 
19
20
 
20
21
  -------- BEGIN injected arguments --------
21
- local current_time = tonumber(ARGV[5])
22
- local debug_lua = tostring(ARGV[6]) == "1"
23
- local max_history = tonumber(ARGV[7])
24
- local script_name = tostring(ARGV[8]) .. ".lua"
22
+ local current_time = tonumber(ARGV[6])
23
+ local debug_lua = tostring(ARGV[7]) == "1"
24
+ local max_history = tonumber(ARGV[8])
25
+ local script_name = tostring(ARGV[9]) .. ".lua"
25
26
  --------- END injected arguments ---------
26
27
 
27
28
 
@@ -1,22 +1,22 @@
1
1
  local function delete_from_queue(queue, digest)
2
- local per = 50
3
- local total = redis.call("LLEN", queue)
4
- local index = 0
5
- local result = nil
2
+ local total = redis.call("LLEN", queue)
3
+ local per = 50
4
+
5
+ for index = 0, total, per do
6
+ local items = redis.call("LRANGE", queue, index, index + per - 1)
6
7
 
7
- while (index < total) do
8
- local items = redis.call("LRANGE", queue, index, index + per -1)
9
8
  if #items == 0 then
10
9
  break
11
10
  end
11
+
12
12
  for _, item in pairs(items) do
13
13
  if string.find(item, digest) then
14
14
  redis.call("LREM", queue, 1, item)
15
- result = item
16
- break
15
+
16
+ return item
17
17
  end
18
18
  end
19
- index = index + per
20
19
  end
21
- return result
20
+
21
+ return nil
22
22
  end
@@ -1,19 +1,29 @@
1
1
  local function delete_from_sorted_set(name, digest)
2
- local per = 50
3
- local total = redis.call("zcard", name)
4
- local index = 0
5
- local result
2
+ local score = redis.call("ZSCORE", "uniquejobs:digests", digest)
3
+ local total = redis.call("ZCARD", name)
4
+ local per = 50
5
+
6
+ for offset = 0, total, per do
7
+ local items
8
+
9
+ if score then
10
+ items = redis.call("ZRANGE", name, score, "+inf", "BYSCORE", "LIMIT", offset, per)
11
+ else
12
+ items = redis.call("ZRANGE", name, offset, offset + per -1)
13
+ end
14
+
15
+ if #items == 0 then
16
+ break
17
+ end
6
18
 
7
- while (index < total) do
8
- local items = redis.call("ZRANGE", name, index, index + per -1)
9
19
  for _, item in pairs(items) do
10
20
  if string.find(item, digest) then
11
21
  redis.call("ZREM", name, item)
12
- result = item
13
- break
22
+
23
+ return item
14
24
  end
15
25
  end
16
- index = index + per
17
26
  end
18
- return result
27
+
28
+ return nil
19
29
  end
@@ -10,19 +10,20 @@ local digests = KEYS[7]
10
10
 
11
11
 
12
12
  -------- BEGIN lock arguments ---------
13
- local job_id = ARGV[1]
14
- local pttl = tonumber(ARGV[2])
15
- local lock_type = ARGV[3]
16
- local limit = tonumber(ARGV[4])
13
+ local job_id = ARGV[1]
14
+ local pttl = tonumber(ARGV[2])
15
+ local lock_type = ARGV[3]
16
+ local limit = tonumber(ARGV[4])
17
+ local lock_score = ARGV[5]
17
18
  -------- END lock arguments -----------
18
19
 
19
20
 
20
21
  -------- BEGIN injected arguments --------
21
- local current_time = tonumber(ARGV[5])
22
- local debug_lua = tostring(ARGV[6]) == "1"
23
- local max_history = tonumber(ARGV[7])
24
- local script_name = tostring(ARGV[8]) .. ".lua"
25
- local redisversion = ARGV[9]
22
+ local current_time = tonumber(ARGV[6])
23
+ local debug_lua = tostring(ARGV[7]) == "1"
24
+ local max_history = tonumber(ARGV[8])
25
+ local script_name = tostring(ARGV[9]) .. ".lua"
26
+ local redisversion = ARGV[10]
26
27
  --------- END injected arguments ---------
27
28
 
28
29
 
@@ -28,7 +28,16 @@ module SidekiqUniqueJobs
28
28
  # @return [false] when Sidekiq::Deadset#kill does not take multiple arguments
29
29
  #
30
30
  def kill_with_options?
31
- Sidekiq::DeadSet.instance_method(:kill).arity > 1
31
+ kill_arity = Sidekiq::DeadSet.instance_method(:kill).arity
32
+ # Method#arity returns:
33
+ # 1. a nonnegative number for methods that take a fixed number of arguments.
34
+ # 2. A negative number if it takes a variable number of arguments.
35
+ # Keyword arguments are considered a single argument, and are considered optional unless one of the kwargs is
36
+ # required.
37
+ # Therefore, to determine if `Sidekiq::DeadSet#kill` accepts options beyond the single positional payload
38
+ # argument, we need to check whether the absolute value of the arity is greater than 1.
39
+ # See: https://apidock.com/ruby/Method/arity
40
+ kill_arity > 1 || kill_arity < -1
32
41
  end
33
42
 
34
43
  #
@@ -21,7 +21,7 @@ module SidekiqUniqueJobs
21
21
  # @param [Hash] item sidekiq job hash
22
22
  #
23
23
  def initialize(item, redis_pool = nil)
24
- super(item, redis_pool)
24
+ super
25
25
  @queue = item[QUEUE]
26
26
  @lock_digest = item[LOCK_DIGEST]
27
27
  end
@@ -54,8 +54,8 @@ module SidekiqUniqueJobs
54
54
  #
55
55
  def delete_job_by_digest
56
56
  call_script(:delete_job_by_digest,
57
- keys: ["#{QUEUE}:#{queue}", SCHEDULE, RETRY],
58
- argv: [lock_digest])
57
+ keys: ["#{QUEUE}:#{queue}", SCHEDULE, RETRY],
58
+ argv: [lock_digest])
59
59
  end
60
60
 
61
61
  #
@@ -13,7 +13,7 @@ module SidekiqUniqueJobs
13
13
 
14
14
  # @param [Hash] item sidekiq job hash
15
15
  def initialize(item, redis_pool = nil)
16
- super(item, redis_pool)
16
+ super
17
17
  self.job_class = item[CLASS]
18
18
  end
19
19
 
@@ -33,8 +33,8 @@ module SidekiqUniqueJobs
33
33
 
34
34
  strategies.fetch(strategy.to_sym) do
35
35
  SidekiqUniqueJobs.logger.warn(
36
- "No matching implementation for strategy: #{strategy}, returning OnConflict::NullStrategy." \
37
- " Available strategies are (#{strategies.inspect})",
36
+ "No matching implementation for strategy: #{strategy}, returning OnConflict::NullStrategy. " \
37
+ "Available strategies are (#{strategies.inspect})",
38
38
  )
39
39
 
40
40
  OnConflict::NullStrategy
@@ -32,7 +32,7 @@ module SidekiqUniqueJobs
32
32
  #
33
33
  # @return [SidekiqUniqueJobs::TimerTask] the task that was started
34
34
  #
35
- def start(test_task = nil) # rubocop:disable
35
+ def start(test_task = nil)
36
36
  return if disabled?
37
37
  return if registered?
38
38
 
@@ -73,7 +73,7 @@ module SidekiqUniqueJobs
73
73
  # @return [<type>] <description>
74
74
  #
75
75
  def task
76
- @task ||= default_task # rubocop:disable ThreadSafety/InstanceVariableInClassMethod
76
+ @task ||= default_task # rubocop:disable ThreadSafety/ClassInstanceVariable
77
77
  end
78
78
 
79
79
  #
@@ -101,7 +101,7 @@ module SidekiqUniqueJobs
101
101
  # @return [void]
102
102
  #
103
103
  def task=(task)
104
- @task = task # rubocop:disable ThreadSafety/InstanceVariableInClassMethod
104
+ @task = task # rubocop:disable ThreadSafety/ClassInstanceVariable
105
105
  end
106
106
 
107
107
  #
@@ -9,7 +9,6 @@ module SidekiqUniqueJobs
9
9
  #
10
10
  # @author Mikael Henriksson <mikael@mhenrixon.com>
11
11
  #
12
- # rubocop:disable Metrics/ClassLength
13
12
  class RubyReaper < Reaper
14
13
  include SidekiqUniqueJobs::Timing
15
14
 
@@ -57,7 +56,7 @@ module SidekiqUniqueJobs
57
56
  # @param [Redis] conn a connection to redis
58
57
  #
59
58
  def initialize(conn)
60
- super(conn)
59
+ super
61
60
  @digests = SidekiqUniqueJobs::Digests.new
62
61
  @scheduled = Redis::SortedSet.new(SCHEDULE)
63
62
  @retried = Redis::SortedSet.new(RETRY)
@@ -107,7 +106,7 @@ module SidekiqUniqueJobs
107
106
  #
108
107
  # @return [Array<String>] an array of orphaned digests
109
108
  #
110
- def orphans # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
109
+ def orphans
111
110
  orphans = []
112
111
  page = 0
113
112
  per = reaper_count * 2
@@ -197,7 +196,7 @@ module SidekiqUniqueJobs
197
196
  end
198
197
  end
199
198
 
200
- def active?(digest) # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
199
+ def active?(digest)
201
200
  Sidekiq.redis do |conn|
202
201
  procs = conn.sscan("processes").to_a
203
202
  return false if procs.empty?
@@ -253,7 +252,7 @@ module SidekiqUniqueJobs
253
252
  conn.sscan("queues").each(&block)
254
253
  end
255
254
 
256
- def entries(conn, queue, &block) # rubocop:disable Metrics/MethodLength
255
+ def entries(conn, queue, &block)
257
256
  queue_key = "queue:#{queue}"
258
257
  initial_size = conn.llen(queue_key)
259
258
  deleted_size = 0
@@ -50,15 +50,15 @@ module SidekiqUniqueJobs
50
50
  #
51
51
  # @return [void] <description>
52
52
  #
53
- def dispatch(reflection, *args) # rubocop:disable Metrics/MethodLength
53
+ def dispatch(reflection, *args)
54
54
  if (block = @reflections[reflection])
55
55
  block.call(*args)
56
56
 
57
57
  if DEPRECATIONS.key?(reflection)
58
58
  replacement, removal_version = DEPRECATIONS[reflection]
59
59
  SidekiqUniqueJobs::Deprecation.warn(
60
- "#{reflection} is deprecated and will be removed in version #{removal_version}." \
61
- " Use #{replacement} instead.",
60
+ "#{reflection} is deprecated and will be removed in version #{removal_version}. " \
61
+ "Use #{replacement} instead.",
62
62
  )
63
63
  end
64
64
  elsif misconfigured?(reflection)
@@ -60,7 +60,7 @@ module Sidekiq
60
60
  #
61
61
  def delete(score, job_id)
62
62
  entry = find_job(job_id)
63
- SidekiqUniqueJobs::Unlockable.delete!(entry.item) if super(score, job_id)
63
+ SidekiqUniqueJobs::Unlockable.delete!(entry.item) if super
64
64
  entry
65
65
  end
66
66
  end
@@ -132,7 +132,7 @@ module Sidekiq
132
132
  # @param [String] value a sidekiq job hash
133
133
  #
134
134
  def delete_by_value(name, value)
135
- SidekiqUniqueJobs::Unlockable.delete!(Sidekiq.load_json(value)) if super(name, value)
135
+ SidekiqUniqueJobs::Unlockable.delete!(Sidekiq.load_json(value)) if super
136
136
  end
137
137
  end
138
138
 
@@ -4,7 +4,7 @@
4
4
  # Contains configuration and utility methods that belongs top level
5
5
  #
6
6
  # @author Mikael Henriksson <mikael@mhenrixon.com>
7
- module SidekiqUniqueJobs # rubocop:disable Metrics/ModuleLength
7
+ module SidekiqUniqueJobs
8
8
  include SidekiqUniqueJobs::Connection
9
9
  extend SidekiqUniqueJobs::JSON
10
10
 
@@ -17,7 +17,7 @@ module SidekiqUniqueJobs # rubocop:disable Metrics/ModuleLength
17
17
  # @return [SidekiqUniqueJobs::Config] the gem configuration
18
18
  #
19
19
  def config
20
- @config ||= reset! # rubocop:disable ThreadSafety/InstanceVariableInClassMethod
20
+ @config ||= reset! # rubocop:disable ThreadSafety/ClassInstanceVariable
21
21
  end
22
22
 
23
23
  #
@@ -108,7 +108,7 @@ module SidekiqUniqueJobs # rubocop:disable Metrics/ModuleLength
108
108
  # @return [SidekiqUniqueJobs::Config] a default gem configuration
109
109
  #
110
110
  def reset!
111
- @config = SidekiqUniqueJobs::Config.default # rubocop:disable ThreadSafety/InstanceVariableInClassMethod
111
+ @config = SidekiqUniqueJobs::Config.default # rubocop:disable ThreadSafety/ClassInstanceVariable
112
112
  end
113
113
 
114
114
  #
@@ -288,7 +288,7 @@ module SidekiqUniqueJobs # rubocop:disable Metrics/ModuleLength
288
288
  # @return [Reflections]
289
289
  #
290
290
  def reflections
291
- @reflections ||= Reflections.new # rubocop:disable ThreadSafety/InstanceVariableInClassMethod
291
+ @reflections ||= Reflections.new # rubocop:disable ThreadSafety/ClassInstanceVariable
292
292
  end
293
293
 
294
294
  #
@@ -39,7 +39,7 @@ module SidekiqUniqueJobs
39
39
 
40
40
  # The hook to call after a successful unlock
41
41
  # @return [Proc]
42
- def after_unlock_hook # rubocop:disable Metrics/MethodLength
42
+ def after_unlock_hook
43
43
  lambda do
44
44
  if @original_job_class.respond_to?(:after_unlock)
45
45
  # instance method in sidekiq v6
@@ -21,7 +21,7 @@ module Sidekiq
21
21
  #
22
22
  # @param [Hash<Symbol, Object>] tmp_config the temporary config to use
23
23
  #
24
- def self.use_options(tmp_config = {}) # rubocop:disable Metrics/MethodLength
24
+ def self.use_options(tmp_config = {})
25
25
  if respond_to?(:default_job_options)
26
26
  default_job_options.clear
27
27
  self.default_job_options = tmp_config
@@ -87,7 +87,7 @@ module Sidekiq
87
87
  def sidekiq_options(options = {})
88
88
  SidekiqUniqueJobs.validate_worker!(options) if SidekiqUniqueJobs.config.raise_on_config_error
89
89
 
90
- super(options)
90
+ super
91
91
  end
92
92
 
93
93
  #
@@ -3,5 +3,5 @@
3
3
  module SidekiqUniqueJobs
4
4
  #
5
5
  # @return [String] the current SidekiqUniqueJobs version
6
- VERSION = "8.0.9"
6
+ VERSION = "8.0.11"
7
7
  end
@@ -116,7 +116,7 @@ module SidekiqUniqueJobs
116
116
  #
117
117
  # @return a redirect to the new subpath
118
118
  #
119
- def redirect_to(subpath)
119
+ def safe_redirect_to(subpath)
120
120
  if respond_to?(:to)
121
121
  # Sinatra-based web UI
122
122
  redirect to(subpath)
@@ -170,6 +170,34 @@ module SidekiqUniqueJobs
170
170
  Time.parse(time.to_s)
171
171
  end
172
172
  end
173
+
174
+ # Copied from sidekiq for compatibility with older versions
175
+
176
+ # stuff after ? or form input
177
+ # uses String keys, no Symbols!
178
+ def safe_url_params(key)
179
+ return url_params(key) if Sidekiq::MAJOR >= 8
180
+
181
+ if key.is_a?(Symbol)
182
+ warn do
183
+ "URL parameter `#{key}` should be accessed via String, not Symbol (at #{caller(3..3).first})"
184
+ end
185
+ end
186
+ request.params[key.to_s]
187
+ end
188
+
189
+ # variables embedded in path, `/metrics/:name`
190
+ # uses Symbol keys, no Strings!
191
+ def safe_route_params(key)
192
+ return route_params(key) if Sidekiq::MAJOR >= 8
193
+
194
+ if key.is_a?(String)
195
+ warn do
196
+ "Route parameter `#{key}` should be accessed via Symbol, not String (at #{caller(3..3).first})"
197
+ end
198
+ end
199
+ env["rack.route_params"][key.to_sym]
200
+ end
173
201
  end
174
202
  end
175
203
  end