sidekiq-unique-jobs 6.0.6 → 6.0.7
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.
Potentially problematic release.
This version of sidekiq-unique-jobs might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +1 -1
- data/.travis.yml +3 -5
- data/Appraisals +4 -0
- data/CHANGELOG.md +10 -0
- data/README.md +1 -1
- data/lib/sidekiq_unique_jobs.rb +3 -3
- data/lib/sidekiq_unique_jobs/client/middleware.rb +7 -3
- data/lib/sidekiq_unique_jobs/constants.rb +2 -0
- data/lib/sidekiq_unique_jobs/job.rb +29 -0
- data/lib/sidekiq_unique_jobs/lock/base_lock.rb +13 -17
- data/lib/sidekiq_unique_jobs/lock/until_and_while_executing.rb +1 -0
- data/lib/sidekiq_unique_jobs/lock/until_executed.rb +1 -0
- data/lib/sidekiq_unique_jobs/lock/until_executing.rb +1 -1
- data/lib/sidekiq_unique_jobs/lock/until_expired.rb +1 -0
- data/lib/sidekiq_unique_jobs/lock/while_executing.rb +1 -0
- data/lib/sidekiq_unique_jobs/locksmith.rb +2 -0
- data/lib/sidekiq_unique_jobs/logging.rb +5 -0
- data/lib/sidekiq_unique_jobs/on_conflict/replace.rb +6 -1
- data/lib/sidekiq_unique_jobs/options_with_fallback.rb +6 -6
- data/lib/sidekiq_unique_jobs/server/middleware.rb +9 -3
- data/lib/sidekiq_unique_jobs/sidekiq_worker_methods.rb +2 -0
- data/lib/sidekiq_unique_jobs/timeout/calculator.rb +2 -1
- data/lib/sidekiq_unique_jobs/unique_args.rb +2 -0
- data/lib/sidekiq_unique_jobs/util.rb +4 -0
- data/lib/sidekiq_unique_jobs/version.rb +1 -1
- data/lib/sidekiq_unique_jobs/web/helpers.rb +1 -0
- data/redis/delete_job_by_digest.lua +6 -4
- data/redis/unlock.lua +1 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 10e850f31b0ccdb3fb851cd075ab25ff6121245c7b0eace83e7075b637bbccf2
|
4
|
+
data.tar.gz: 6b6d7592acd4822c915b54c29d4fde9715709edbececdd7ff3324401ce8cfb8c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c68d91eaa41ab900ab2063a1a7f514283743f11546fff0ba479869c4479c8ff2ccb1b4d04636dcc6bb8f9dd8345562a09c488380dcadd5e1d1fb745eb5ec3564
|
7
|
+
data.tar.gz: a36b53f36718f17e2ab4f25d5456aae403e51a53cecdacd142c26dc28c177f147bce6c960db8b9ce31328c621ab0379251e27b0fed9b0de04d3175e23d8134e3
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
data/.travis.yml
CHANGED
@@ -8,13 +8,10 @@ dist: trusty
|
|
8
8
|
sudo: required
|
9
9
|
language: ruby
|
10
10
|
cache: bundler
|
11
|
+
services:
|
12
|
+
- redis-server
|
11
13
|
|
12
14
|
before_install:
|
13
|
-
- sudo rm -rf /etc/apt/sources.list.d/rwky-redis.list
|
14
|
-
- sudo add-apt-repository ppa:chris-lea/redis-server -y
|
15
|
-
- sudo apt-get update -qy
|
16
|
-
- sudo apt-get install redis-server
|
17
|
-
- sudo service redis-server start
|
18
15
|
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
19
16
|
- chmod +x ./cc-test-reporter
|
20
17
|
before_script:
|
@@ -42,6 +39,7 @@ gemfile:
|
|
42
39
|
- gemfiles/sidekiq_4.2.gemfile
|
43
40
|
- gemfiles/sidekiq_5.0.gemfile
|
44
41
|
- gemfiles/sidekiq_5.1.gemfile
|
42
|
+
- gemfiles/sidekiq_5.2.gemfile
|
45
43
|
|
46
44
|
notifications:
|
47
45
|
email:
|
data/Appraisals
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
## v6.0.6
|
2
|
+
|
3
|
+
- Fixes a bug with the command line utility ([#321](https://github.com/mhenrixon/sidekiq-unique-jobs/pull/321))
|
4
|
+
- Internal refactoring to improve performance ([#318](https://github.com/mhenrixon/sidekiq-unique-jobs/pull/318))
|
5
|
+
- Adds coverage for retrying jobs
|
6
|
+
|
7
|
+
## v6.0.5
|
8
|
+
|
9
|
+
- Fixes a bug with keys not being deleted ([#317](https://github.com/mhenrixon/sidekiq-unique-jobs/pull/317))
|
10
|
+
|
1
11
|
## v6.0.4
|
2
12
|
|
3
13
|
- Prevent locks from stealing each other (#316)
|
data/README.md
CHANGED
@@ -443,7 +443,7 @@ RSpec.describe Workers::CoolOne do
|
|
443
443
|
|
444
444
|
it 'prevents duplicate jobs from being scheduled' do
|
445
445
|
SidekiqUniqueJobs.use_config(enabled: true) do
|
446
|
-
expect(described_class.
|
446
|
+
expect(described_class.perform_in(3600, 1)).not_to eq(nil)
|
447
447
|
expect(described_class.perform_async(1)).to eq(nil)
|
448
448
|
end
|
449
449
|
end
|
data/lib/sidekiq_unique_jobs.rb
CHANGED
@@ -11,6 +11,7 @@ require 'sidekiq_unique_jobs/logging'
|
|
11
11
|
require 'sidekiq_unique_jobs/sidekiq_worker_methods'
|
12
12
|
require 'sidekiq_unique_jobs/connection'
|
13
13
|
require 'sidekiq_unique_jobs/exceptions'
|
14
|
+
require 'sidekiq_unique_jobs/job'
|
14
15
|
require 'sidekiq_unique_jobs/util'
|
15
16
|
require 'sidekiq_unique_jobs/digests'
|
16
17
|
require 'sidekiq_unique_jobs/cli'
|
@@ -42,8 +43,7 @@ module SidekiqUniqueJobs
|
|
42
43
|
|
43
44
|
module_function
|
44
45
|
|
45
|
-
Concurrent::MutableStruct.new(
|
46
|
-
'Config',
|
46
|
+
Config = Concurrent::MutableStruct.new(
|
47
47
|
:default_lock_timeout,
|
48
48
|
:enabled,
|
49
49
|
:unique_prefix,
|
@@ -53,7 +53,7 @@ module SidekiqUniqueJobs
|
|
53
53
|
# The current configuration (See: {.configure} on how to configure)
|
54
54
|
def config
|
55
55
|
# Arguments here need to match the definition of the new class (see above)
|
56
|
-
@config ||=
|
56
|
+
@config ||= Config.new(
|
57
57
|
0,
|
58
58
|
true,
|
59
59
|
'uniquejobs',
|
@@ -38,13 +38,17 @@ module SidekiqUniqueJobs
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def locked?
|
41
|
-
|
42
|
-
|
43
|
-
|
41
|
+
SidekiqUniqueJobs::Job.add_uniqueness(item)
|
42
|
+
Sidekiq::Logging.with_context(logging_context(self.class, item)) do
|
43
|
+
locked = lock.lock
|
44
|
+
warn_about_duplicate unless locked
|
45
|
+
locked
|
46
|
+
end
|
44
47
|
end
|
45
48
|
|
46
49
|
def warn_about_duplicate
|
47
50
|
return unless log_duplicate_payload?
|
51
|
+
|
48
52
|
log_warn "payload is not unique #{item}"
|
49
53
|
end
|
50
54
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SidekiqUniqueJobs
|
4
|
+
# Utility class to append uniqueness to the sidekiq job hash
|
5
|
+
#
|
6
|
+
# @author Mikael Henriksson <mikael@zoolutions.se>
|
7
|
+
module Job
|
8
|
+
extend self # rubocop:disable Style/ModuleFunction
|
9
|
+
|
10
|
+
# Adds timeout, expiration, unique_args, unique_prefix and unique_digest to the sidekiq job hash
|
11
|
+
# @return [void] nothing returned here matters
|
12
|
+
def add_uniqueness(item)
|
13
|
+
add_timeout_and_expiration(item)
|
14
|
+
add_unique_args_and_digest(item)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def add_timeout_and_expiration(item)
|
20
|
+
calculator = SidekiqUniqueJobs::Timeout::Calculator.new(item)
|
21
|
+
item[LOCK_TIMEOUT_KEY] = calculator.lock_timeout
|
22
|
+
item[LOCK_EXPIRATION_KEY] = calculator.lock_expiration
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_unique_args_and_digest(item)
|
26
|
+
SidekiqUniqueJobs::UniqueArgs.digest(item)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -13,9 +13,10 @@ module SidekiqUniqueJobs
|
|
13
13
|
# @param [Proc] callback the callback to use after unlock
|
14
14
|
# @param [Sidekiq::RedisConnection, ConnectionPool] redis_pool the redis connection
|
15
15
|
def initialize(item, callback, redis_pool = nil)
|
16
|
-
@item =
|
16
|
+
@item = item
|
17
17
|
@callback = callback
|
18
18
|
@redis_pool = redis_pool
|
19
|
+
add_uniqueness_when_missing # Used to ease testing
|
19
20
|
end
|
20
21
|
|
21
22
|
# Handles locking of sidekiq jobs.
|
@@ -65,6 +66,14 @@ module SidekiqUniqueJobs
|
|
65
66
|
|
66
67
|
private
|
67
68
|
|
69
|
+
def add_uniqueness_when_missing
|
70
|
+
return if item.key?(UNIQUE_DIGEST_KEY)
|
71
|
+
|
72
|
+
# The below should only be done to ease testing
|
73
|
+
# in production this will be done by the middleware
|
74
|
+
SidekiqUniqueJobs::Job.add_uniqueness(item)
|
75
|
+
end
|
76
|
+
|
68
77
|
def call_strategy
|
69
78
|
@attempt += 1
|
70
79
|
strategy.call { lock if replace? }
|
@@ -99,27 +108,14 @@ module SidekiqUniqueJobs
|
|
99
108
|
def with_cleanup
|
100
109
|
yield
|
101
110
|
rescue Sidekiq::Shutdown
|
102
|
-
|
111
|
+
log_info('Sidekiq is shutting down, the job `should` be put back on the queue. Keeping the lock!')
|
103
112
|
raise
|
104
113
|
else
|
105
114
|
unlock_with_callback
|
106
115
|
end
|
107
116
|
|
108
|
-
def prepare_item(item)
|
109
|
-
calculator = SidekiqUniqueJobs::Timeout::Calculator.new(item)
|
110
|
-
item[LOCK_TIMEOUT_KEY] = calculator.lock_timeout
|
111
|
-
item[LOCK_EXPIRATION_KEY] = calculator.lock_expiration
|
112
|
-
SidekiqUniqueJobs::UniqueArgs.digest(item)
|
113
|
-
item
|
114
|
-
end
|
115
|
-
|
116
|
-
def notify_about_manual_unlock
|
117
|
-
log_fatal("the unique_key: #{item[UNIQUE_DIGEST_KEY]} needs to be unlocked manually")
|
118
|
-
false
|
119
|
-
end
|
120
|
-
|
121
117
|
def unlock_with_callback
|
122
|
-
return
|
118
|
+
return log_warn('might need to be unlocked manually') unless unlock
|
123
119
|
|
124
120
|
callback_safely
|
125
121
|
item[JID_KEY]
|
@@ -128,7 +124,7 @@ module SidekiqUniqueJobs
|
|
128
124
|
def callback_safely
|
129
125
|
callback&.call
|
130
126
|
rescue StandardError
|
131
|
-
log_warn(
|
127
|
+
log_warn('unlocked successfully but the #after_unlock callback failed!')
|
132
128
|
raise
|
133
129
|
end
|
134
130
|
|
@@ -4,7 +4,7 @@ module SidekiqUniqueJobs
|
|
4
4
|
class Lock
|
5
5
|
# Locks jobs until {#execute} starts
|
6
6
|
# - Locks on perform_in or perform_async
|
7
|
-
# - Unlocks
|
7
|
+
# - Unlocks before yielding to the worker's perform method
|
8
8
|
#
|
9
9
|
# @author Mikael Henriksson <mikael@zoolutions.se>
|
10
10
|
class UntilExecuting < BaseLock
|
@@ -37,6 +37,7 @@ module SidekiqUniqueJobs
|
|
37
37
|
# Deletes the lock unless it has an expiration set
|
38
38
|
def delete
|
39
39
|
return if expiration
|
40
|
+
|
40
41
|
delete!
|
41
42
|
end
|
42
43
|
|
@@ -72,6 +73,7 @@ module SidekiqUniqueJobs
|
|
72
73
|
def unlock(token = nil)
|
73
74
|
token ||= jid
|
74
75
|
return false unless locked?(token)
|
76
|
+
|
75
77
|
unlock!(token)
|
76
78
|
end
|
77
79
|
|
@@ -49,5 +49,10 @@ module SidekiqUniqueJobs
|
|
49
49
|
def log_fatal(message_or_exception = nil, &block)
|
50
50
|
logger.fatal(message_or_exception, &block)
|
51
51
|
end
|
52
|
+
|
53
|
+
def logging_context(middleware_class, job_hash)
|
54
|
+
digest = job_hash['unique_digest']
|
55
|
+
"#{middleware_class} #{"DIG-#{digest}" if digest}"
|
56
|
+
end
|
52
57
|
end
|
53
58
|
end
|
@@ -19,13 +19,18 @@ module SidekiqUniqueJobs
|
|
19
19
|
# @yield to retry the lock after deleting the old one
|
20
20
|
def call(&block)
|
21
21
|
return unless delete_job_by_digest
|
22
|
+
|
22
23
|
delete_lock
|
23
24
|
block&.call
|
24
25
|
end
|
25
26
|
|
26
27
|
# Delete the job from either schedule, retry or the queue
|
27
28
|
def delete_job_by_digest
|
28
|
-
Scripts.call(
|
29
|
+
Scripts.call(
|
30
|
+
:delete_job_by_digest,
|
31
|
+
nil,
|
32
|
+
keys: ["#{QUEUE_KEY}:#{queue}", SCHEDULE_SET, RETRY_SET], argv: [unique_digest],
|
33
|
+
)
|
29
34
|
end
|
30
35
|
|
31
36
|
# Delete the keys belonging to the job
|
@@ -11,12 +11,12 @@ module SidekiqUniqueJobs
|
|
11
11
|
module OptionsWithFallback
|
12
12
|
LOCKS = {
|
13
13
|
until_and_while_executing: SidekiqUniqueJobs::Lock::UntilAndWhileExecuting,
|
14
|
-
until_executed:
|
15
|
-
until_executing:
|
16
|
-
until_expired:
|
17
|
-
until_timeout:
|
18
|
-
while_executing:
|
19
|
-
while_executing_reject:
|
14
|
+
until_executed: SidekiqUniqueJobs::Lock::UntilExecuted,
|
15
|
+
until_executing: SidekiqUniqueJobs::Lock::UntilExecuting,
|
16
|
+
until_expired: SidekiqUniqueJobs::Lock::UntilExpired,
|
17
|
+
until_timeout: SidekiqUniqueJobs::Lock::UntilExpired,
|
18
|
+
while_executing: SidekiqUniqueJobs::Lock::WhileExecuting,
|
19
|
+
while_executing_reject: SidekiqUniqueJobs::Lock::WhileExecutingReject,
|
20
20
|
}.freeze
|
21
21
|
|
22
22
|
def self.included(base)
|
@@ -6,6 +6,7 @@ module SidekiqUniqueJobs
|
|
6
6
|
#
|
7
7
|
# @author Mikael Henriksson <mikael@zoolutions.se>
|
8
8
|
class Middleware
|
9
|
+
include Logging
|
9
10
|
include OptionsWithFallback
|
10
11
|
|
11
12
|
# Runs the server middleware
|
@@ -21,13 +22,18 @@ module SidekiqUniqueJobs
|
|
21
22
|
@queue = queue
|
22
23
|
return yield if unique_disabled?
|
23
24
|
|
24
|
-
|
25
|
-
|
25
|
+
SidekiqUniqueJobs::Job.add_uniqueness(item)
|
26
|
+
Sidekiq::Logging.with_context(logging_context(self.class, item)) do
|
27
|
+
lock.execute do
|
28
|
+
yield
|
29
|
+
end
|
26
30
|
end
|
27
31
|
end
|
28
32
|
|
29
|
-
|
33
|
+
private
|
30
34
|
|
35
|
+
# The sidekiq job hash
|
36
|
+
# @return [Hash] the Sidekiq job hash
|
31
37
|
attr_reader :item
|
32
38
|
end
|
33
39
|
end
|
@@ -15,6 +15,7 @@ module SidekiqUniqueJobs
|
|
15
15
|
# @return [Hash] of the worker class sidekiq options
|
16
16
|
def worker_options
|
17
17
|
return {} unless sidekiq_worker_class?
|
18
|
+
|
18
19
|
worker_class.get_sidekiq_options.stringify_keys
|
19
20
|
end
|
20
21
|
|
@@ -43,6 +44,7 @@ module SidekiqUniqueJobs
|
|
43
44
|
# @return [Sidekiq::Worker]
|
44
45
|
def worker_class_constantize(klazz = @worker_class)
|
45
46
|
return klazz unless klazz.is_a?(String)
|
47
|
+
|
46
48
|
Object.const_get(klazz)
|
47
49
|
rescue NameError => ex
|
48
50
|
case ex.message
|
@@ -25,6 +25,7 @@ module SidekiqUniqueJobs
|
|
25
25
|
# @return [Integer] the number of seconds until job is scheduled
|
26
26
|
def time_until_scheduled
|
27
27
|
return 0 unless scheduled_at
|
28
|
+
|
28
29
|
scheduled_at.to_i - Time.now.utc.to_i
|
29
30
|
end
|
30
31
|
|
@@ -39,7 +40,7 @@ module SidekiqUniqueJobs
|
|
39
40
|
@lock_expiration ||= begin
|
40
41
|
expiration = item[LOCK_EXPIRATION_KEY]
|
41
42
|
expiration ||= worker_options[LOCK_EXPIRATION_KEY]
|
42
|
-
expiration && expiration + time_until_scheduled
|
43
|
+
expiration && expiration.to_i + time_until_scheduled
|
43
44
|
end
|
44
45
|
end
|
45
46
|
|
@@ -70,6 +70,7 @@ module SidekiqUniqueJobs
|
|
70
70
|
# @return [Array] the arguments filters by the {#filtered_args} method if {#unique_args_enabled?}
|
71
71
|
def unique_args(args)
|
72
72
|
return filtered_args(args) if unique_args_enabled?
|
73
|
+
|
73
74
|
args
|
74
75
|
end
|
75
76
|
|
@@ -99,6 +100,7 @@ module SidekiqUniqueJobs
|
|
99
100
|
# @return [Array] args unfiltered when neither of the above
|
100
101
|
def filtered_args(args)
|
101
102
|
return args if args.empty?
|
103
|
+
|
102
104
|
json_args = Normalizer.jsonify(args)
|
103
105
|
|
104
106
|
case unique_args_method
|
@@ -20,6 +20,7 @@ module SidekiqUniqueJobs
|
|
20
20
|
# @return [Array<String>] an array with active unique keys
|
21
21
|
def keys(pattern = SCAN_PATTERN, count = DEFAULT_COUNT)
|
22
22
|
return redis(&:keys) if pattern.nil?
|
23
|
+
|
23
24
|
redis { |conn| conn.scan_each(match: prefix(pattern), count: count).to_a }
|
24
25
|
end
|
25
26
|
|
@@ -44,6 +45,7 @@ module SidekiqUniqueJobs
|
|
44
45
|
# @return [Integer] the number of keys deleted
|
45
46
|
def del(pattern = SCAN_PATTERN, count = 0)
|
46
47
|
raise ArgumentError, 'Please provide a number of keys to delete greater than zero' if count.zero?
|
48
|
+
|
47
49
|
pattern = suffix(pattern)
|
48
50
|
|
49
51
|
log_debug { "Deleting keys by: #{pattern}" }
|
@@ -84,11 +86,13 @@ module SidekiqUniqueJobs
|
|
84
86
|
def prefix(key)
|
85
87
|
return key if unique_prefix.nil?
|
86
88
|
return key if key.start_with?("#{unique_prefix}:")
|
89
|
+
|
87
90
|
"#{unique_prefix}:#{key}"
|
88
91
|
end
|
89
92
|
|
90
93
|
def suffix(key)
|
91
94
|
return "#{key}*" unless key.end_with?(':*')
|
95
|
+
|
92
96
|
key
|
93
97
|
end
|
94
98
|
|
@@ -1,5 +1,7 @@
|
|
1
|
-
local queue =
|
2
|
-
local
|
1
|
+
local queue = KEYS[1]
|
2
|
+
local schedule_set = KEYS[2]
|
3
|
+
local retry_set = KEYS[3]
|
4
|
+
local unique_digest = ARGV[1]
|
3
5
|
|
4
6
|
local function delete_from_sorted_set(name, digest)
|
5
7
|
local per = 50
|
@@ -49,10 +51,10 @@ if result then
|
|
49
51
|
return result
|
50
52
|
end
|
51
53
|
|
52
|
-
result = delete_from_sorted_set(
|
54
|
+
result = delete_from_sorted_set(schedule_set, unique_digest)
|
53
55
|
if result then
|
54
56
|
return result
|
55
57
|
end
|
56
58
|
|
57
|
-
result = delete_from_sorted_set(
|
59
|
+
result = delete_from_sorted_set(retry_set, unique_digest)
|
58
60
|
return result
|
data/redis/unlock.lua
CHANGED
@@ -10,7 +10,6 @@ local expiration = tonumber(ARGV[2])
|
|
10
10
|
|
11
11
|
redis.call('HDEL', grabbed_key, token)
|
12
12
|
redis.call('SREM', unique_keys, unique_digest)
|
13
|
-
local available_count = redis.call('LPUSH', available_key, token)
|
14
13
|
|
15
14
|
if expiration then
|
16
15
|
redis.log(redis.LOG_DEBUG, "signal_locks.lua - expiring stale locks")
|
@@ -29,5 +28,5 @@ else
|
|
29
28
|
redis.call('DEL', unique_digest) -- TODO: Legacy support (Remove in v6.1)
|
30
29
|
end
|
31
30
|
|
32
|
-
return
|
31
|
+
return redis.call('LPUSH', available_key, token)
|
33
32
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidekiq-unique-jobs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.0.
|
4
|
+
version: 6.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mikael Henriksson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-11-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -273,6 +273,7 @@ files:
|
|
273
273
|
- lib/sidekiq_unique_jobs/core_ext.rb
|
274
274
|
- lib/sidekiq_unique_jobs/digests.rb
|
275
275
|
- lib/sidekiq_unique_jobs/exceptions.rb
|
276
|
+
- lib/sidekiq_unique_jobs/job.rb
|
276
277
|
- lib/sidekiq_unique_jobs/lock/base_lock.rb
|
277
278
|
- lib/sidekiq_unique_jobs/lock/until_and_while_executing.rb
|
278
279
|
- lib/sidekiq_unique_jobs/lock/until_executed.rb
|