sidekiq-unique-jobs 6.0.25 → 7.0.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sidekiq-unique-jobs might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +155 -20
- data/README.md +349 -112
- data/lib/sidekiq-unique-jobs.rb +2 -0
- data/lib/sidekiq_unique_jobs.rb +43 -6
- data/lib/sidekiq_unique_jobs/batch_delete.rb +121 -0
- data/lib/sidekiq_unique_jobs/changelog.rb +71 -0
- data/lib/sidekiq_unique_jobs/cli.rb +20 -29
- data/lib/sidekiq_unique_jobs/config.rb +193 -0
- data/lib/sidekiq_unique_jobs/connection.rb +5 -4
- data/lib/sidekiq_unique_jobs/constants.rb +36 -24
- data/lib/sidekiq_unique_jobs/core_ext.rb +38 -0
- data/lib/sidekiq_unique_jobs/digests.rb +78 -93
- data/lib/sidekiq_unique_jobs/exceptions.rb +152 -8
- data/lib/sidekiq_unique_jobs/job.rb +3 -3
- data/lib/sidekiq_unique_jobs/json.rb +34 -0
- data/lib/sidekiq_unique_jobs/key.rb +93 -0
- data/lib/sidekiq_unique_jobs/lock.rb +295 -0
- data/lib/sidekiq_unique_jobs/lock/base_lock.rb +49 -43
- data/lib/sidekiq_unique_jobs/lock/client_validator.rb +28 -0
- data/lib/sidekiq_unique_jobs/lock/server_validator.rb +27 -0
- data/lib/sidekiq_unique_jobs/lock/until_and_while_executing.rb +8 -17
- data/lib/sidekiq_unique_jobs/lock/until_executed.rb +5 -5
- data/lib/sidekiq_unique_jobs/lock/until_expired.rb +1 -23
- data/lib/sidekiq_unique_jobs/lock/validator.rb +65 -0
- data/lib/sidekiq_unique_jobs/lock/while_executing.rb +12 -8
- data/lib/sidekiq_unique_jobs/lock/while_executing_reject.rb +1 -1
- data/lib/sidekiq_unique_jobs/lock_config.rb +95 -0
- data/lib/sidekiq_unique_jobs/lock_info.rb +68 -0
- data/lib/sidekiq_unique_jobs/locksmith.rb +255 -99
- data/lib/sidekiq_unique_jobs/logging.rb +148 -22
- data/lib/sidekiq_unique_jobs/logging/middleware_context.rb +44 -0
- data/lib/sidekiq_unique_jobs/lua/delete.lua +51 -0
- data/lib/sidekiq_unique_jobs/lua/delete_by_digest.lua +46 -0
- data/lib/sidekiq_unique_jobs/lua/delete_job_by_digest.lua +38 -0
- data/lib/sidekiq_unique_jobs/lua/find_digest_in_queues.lua +26 -0
- data/lib/sidekiq_unique_jobs/lua/find_digest_in_sorted_set.lua +24 -0
- data/lib/sidekiq_unique_jobs/lua/lock.lua +91 -0
- data/lib/sidekiq_unique_jobs/lua/locked.lua +35 -0
- data/lib/sidekiq_unique_jobs/lua/queue.lua +83 -0
- data/lib/sidekiq_unique_jobs/lua/reap_orphans.lua +86 -0
- data/lib/sidekiq_unique_jobs/lua/shared/_common.lua +40 -0
- data/lib/sidekiq_unique_jobs/lua/shared/_current_time.lua +8 -0
- data/lib/sidekiq_unique_jobs/lua/shared/_delete_from_queue.lua +19 -0
- data/lib/sidekiq_unique_jobs/lua/shared/_delete_from_sorted_set.lua +18 -0
- data/lib/sidekiq_unique_jobs/lua/shared/_find_digest_in_queues.lua +46 -0
- data/lib/sidekiq_unique_jobs/lua/shared/_find_digest_in_sorted_set.lua +24 -0
- data/lib/sidekiq_unique_jobs/lua/shared/_hgetall.lua +13 -0
- data/lib/sidekiq_unique_jobs/lua/shared/_upgrades.lua +3 -0
- data/lib/sidekiq_unique_jobs/lua/shared/find_digest_in_sorted_set.lua +24 -0
- data/lib/sidekiq_unique_jobs/lua/unlock.lua +99 -0
- data/lib/sidekiq_unique_jobs/lua/update_version.lua +40 -0
- data/lib/sidekiq_unique_jobs/lua/upgrade.lua +68 -0
- data/lib/sidekiq_unique_jobs/middleware.rb +62 -31
- data/lib/sidekiq_unique_jobs/middleware/client.rb +42 -0
- data/lib/sidekiq_unique_jobs/middleware/server.rb +27 -0
- data/lib/sidekiq_unique_jobs/normalizer.rb +3 -3
- data/lib/sidekiq_unique_jobs/on_conflict.rb +22 -9
- data/lib/sidekiq_unique_jobs/on_conflict/log.rb +8 -4
- data/lib/sidekiq_unique_jobs/on_conflict/reject.rb +59 -13
- data/lib/sidekiq_unique_jobs/on_conflict/replace.rb +42 -13
- data/lib/sidekiq_unique_jobs/on_conflict/reschedule.rb +4 -4
- data/lib/sidekiq_unique_jobs/on_conflict/strategy.rb +24 -5
- data/lib/sidekiq_unique_jobs/options_with_fallback.rb +47 -23
- data/lib/sidekiq_unique_jobs/orphans/manager.rb +100 -0
- data/lib/sidekiq_unique_jobs/orphans/observer.rb +42 -0
- data/lib/sidekiq_unique_jobs/orphans/reaper.rb +201 -0
- data/lib/sidekiq_unique_jobs/profiler.rb +51 -0
- data/lib/sidekiq_unique_jobs/redis.rb +11 -0
- data/lib/sidekiq_unique_jobs/redis/entity.rb +94 -0
- data/lib/sidekiq_unique_jobs/redis/hash.rb +56 -0
- data/lib/sidekiq_unique_jobs/redis/list.rb +32 -0
- data/lib/sidekiq_unique_jobs/redis/set.rb +32 -0
- data/lib/sidekiq_unique_jobs/redis/sorted_set.rb +59 -0
- data/lib/sidekiq_unique_jobs/redis/string.rb +49 -0
- data/lib/sidekiq_unique_jobs/rspec/matchers.rb +19 -0
- data/lib/sidekiq_unique_jobs/rspec/matchers/have_valid_sidekiq_options.rb +43 -0
- data/lib/sidekiq_unique_jobs/{scripts.rb → script.rb} +43 -29
- data/lib/sidekiq_unique_jobs/script/caller.rb +125 -0
- data/lib/sidekiq_unique_jobs/script/template.rb +41 -0
- data/lib/sidekiq_unique_jobs/sidekiq_unique_ext.rb +92 -65
- data/lib/sidekiq_unique_jobs/sidekiq_unique_jobs.rb +166 -28
- data/lib/sidekiq_unique_jobs/sidekiq_worker_methods.rb +10 -11
- data/lib/sidekiq_unique_jobs/testing.rb +47 -15
- data/lib/sidekiq_unique_jobs/time_calculator.rb +103 -0
- data/lib/sidekiq_unique_jobs/timing.rb +58 -0
- data/lib/sidekiq_unique_jobs/unique_args.rb +19 -21
- data/lib/sidekiq_unique_jobs/unlockable.rb +11 -2
- data/lib/sidekiq_unique_jobs/update_version.rb +25 -0
- data/lib/sidekiq_unique_jobs/upgrade_locks.rb +151 -0
- data/lib/sidekiq_unique_jobs/version.rb +3 -1
- data/lib/sidekiq_unique_jobs/version_check.rb +1 -1
- data/lib/sidekiq_unique_jobs/web.rb +25 -19
- data/lib/sidekiq_unique_jobs/web/helpers.rb +98 -6
- data/lib/sidekiq_unique_jobs/web/views/lock.erb +108 -0
- data/lib/sidekiq_unique_jobs/web/views/locks.erb +52 -0
- data/lib/tasks/changelog.rake +4 -3
- metadata +70 -35
- data/lib/sidekiq_unique_jobs/client/middleware.rb +0 -56
- data/lib/sidekiq_unique_jobs/server/middleware.rb +0 -46
- data/lib/sidekiq_unique_jobs/timeout.rb +0 -8
- data/lib/sidekiq_unique_jobs/timeout/calculator.rb +0 -63
- data/lib/sidekiq_unique_jobs/util.rb +0 -103
- data/lib/sidekiq_unique_jobs/web/views/unique_digest.erb +0 -28
- data/lib/sidekiq_unique_jobs/web/views/unique_digests.erb +0 -46
- data/redis/acquire_lock.lua +0 -21
- data/redis/convert_legacy_lock.lua +0 -13
- data/redis/delete.lua +0 -14
- data/redis/delete_by_digest.lua +0 -23
- data/redis/delete_job_by_digest.lua +0 -60
- data/redis/lock.lua +0 -62
- data/redis/release_stale_locks.lua +0 -90
- data/redis/unlock.lua +0 -35
@@ -29,28 +29,21 @@ module SidekiqUniqueJobs
|
|
29
29
|
# The Sidekiq::Worker implementation
|
30
30
|
# @return [Sidekiq::Worker]
|
31
31
|
def worker_class
|
32
|
-
@_worker_class ||= worker_class_constantize
|
32
|
+
@_worker_class ||= worker_class_constantize # rubocop:disable Naming/MemoizedInstanceVariableName
|
33
33
|
end
|
34
34
|
|
35
35
|
# The hook to call after a successful unlock
|
36
36
|
# @return [Proc]
|
37
37
|
def after_unlock_hook
|
38
|
-
|
39
|
-
if @worker_class.respond_to?(:after_unlock)
|
40
|
-
@worker_class.after_unlock # instance method in sidekiq v6
|
41
|
-
elsif worker_class.respond_to?(:after_unlock)
|
42
|
-
worker_class.after_unlock # class method regardless of sidekiq version
|
43
|
-
end
|
44
|
-
end
|
38
|
+
-> { worker_class.after_unlock if worker_method_defined?(:after_unlock) }
|
45
39
|
end
|
46
40
|
|
47
41
|
# Attempt to constantize a string worker_class argument, always
|
48
42
|
# failing back to the original argument when the constant can't be found
|
49
43
|
#
|
50
44
|
# @return [Sidekiq::Worker]
|
51
|
-
def worker_class_constantize(klazz)
|
52
|
-
return klazz
|
53
|
-
return klazz unless klazz.is_a?(String)
|
45
|
+
def worker_class_constantize(klazz = @worker_class)
|
46
|
+
return klazz unless klazz.is_a?(String)
|
54
47
|
|
55
48
|
Object.const_get(klazz)
|
56
49
|
rescue NameError => ex
|
@@ -62,6 +55,12 @@ module SidekiqUniqueJobs
|
|
62
55
|
end
|
63
56
|
end
|
64
57
|
|
58
|
+
#
|
59
|
+
# Returns the default worker options from Sidekiq
|
60
|
+
#
|
61
|
+
#
|
62
|
+
# @return [Hash<Symbol, Object>]
|
63
|
+
#
|
65
64
|
def default_worker_options
|
66
65
|
Sidekiq.default_worker_options
|
67
66
|
end
|
@@ -1,11 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# :nocov:
|
4
|
+
# :nodoc:
|
4
5
|
|
5
6
|
require "sidekiq"
|
6
7
|
require "sidekiq/testing"
|
8
|
+
require "sidekiq_unique_jobs/rspec/matchers"
|
9
|
+
require "sidekiq_unique_jobs/lock/validator"
|
10
|
+
require "sidekiq_unique_jobs/lock/client_validator"
|
11
|
+
require "sidekiq_unique_jobs/lock/server_validator"
|
7
12
|
|
13
|
+
#
|
14
|
+
# See Sidekiq gem for more details
|
15
|
+
#
|
8
16
|
module Sidekiq
|
17
|
+
#
|
18
|
+
# Temporarily turn Sidekiq's options into something different
|
19
|
+
#
|
20
|
+
# @note this method will restore the original options after yielding
|
21
|
+
#
|
22
|
+
# @param [Hash<Symbol, Object>] tmp_config the temporary config to use
|
23
|
+
#
|
9
24
|
def self.use_options(tmp_config = {})
|
10
25
|
old_config = default_worker_options
|
11
26
|
default_worker_options.clear
|
@@ -17,20 +32,37 @@ module Sidekiq
|
|
17
32
|
self.default_worker_options = old_config
|
18
33
|
end
|
19
34
|
|
35
|
+
#
|
36
|
+
# See Sidekiq::Worker in Sidekiq gem for more details
|
37
|
+
#
|
20
38
|
module Worker
|
39
|
+
#
|
40
|
+
# Adds class methods to Sidekiq::Worker
|
41
|
+
#
|
21
42
|
module ClassMethods
|
43
|
+
#
|
44
|
+
# Temporarily turn a workers sidekiq_options into something different
|
45
|
+
#
|
46
|
+
# @note this method will restore the original configuration after yielding
|
47
|
+
#
|
48
|
+
# @param [Hash<Symbol, Object>] tmp_config the temporary config to use
|
49
|
+
#
|
22
50
|
def use_options(tmp_config = {})
|
23
51
|
old_config = get_sidekiq_options
|
24
52
|
sidekiq_options(tmp_config)
|
25
53
|
|
26
54
|
yield
|
27
55
|
ensure
|
56
|
+
self.sidekiq_options_hash = Sidekiq.default_worker_options
|
28
57
|
sidekiq_options(old_config)
|
29
58
|
end
|
30
59
|
|
60
|
+
#
|
61
|
+
# Clears the jobs for this worker and removes all locks
|
62
|
+
#
|
31
63
|
def clear
|
32
64
|
jobs.each do |job|
|
33
|
-
SidekiqUniqueJobs::Unlockable.
|
65
|
+
SidekiqUniqueJobs::Unlockable.unlock(job)
|
34
66
|
end
|
35
67
|
|
36
68
|
Sidekiq::Queues[queue].clear
|
@@ -38,25 +70,25 @@ module Sidekiq
|
|
38
70
|
end
|
39
71
|
end
|
40
72
|
|
73
|
+
#
|
74
|
+
# Prepends deletion of locks to clear_all
|
75
|
+
#
|
41
76
|
module Overrides
|
42
|
-
def
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
alias_method :clear_all_orig, :clear_all
|
47
|
-
alias_method :clear_all, :clear_all_ext
|
48
|
-
end
|
49
|
-
end
|
77
|
+
def sidekiq_options(options = {})
|
78
|
+
SidekiqUniqueJobs.validate_worker!(options) if SidekiqUniqueJobs.config.raise_on_config_error
|
79
|
+
|
80
|
+
super(options)
|
50
81
|
end
|
51
82
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
83
|
+
#
|
84
|
+
# Clears all jobs for this worker and removes all locks
|
85
|
+
#
|
86
|
+
def clear_all
|
87
|
+
super
|
88
|
+
SidekiqUniqueJobs::Digests.new.del(pattern: "*", count: 1_000)
|
57
89
|
end
|
58
90
|
end
|
59
91
|
|
60
|
-
|
92
|
+
prepend Overrides
|
61
93
|
end
|
62
94
|
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SidekiqUniqueJobs
|
4
|
+
# Calculates timeout and expiration
|
5
|
+
#
|
6
|
+
# @author Mikael Henriksson <mikael@zoolutions.se>
|
7
|
+
class TimeCalculator
|
8
|
+
# includes "SidekiqUniqueJobs::SidekiqWorkerMethods"
|
9
|
+
# @!parse include SidekiqUniqueJobs::SidekiqWorkerMethods
|
10
|
+
include SidekiqUniqueJobs::SidekiqWorkerMethods
|
11
|
+
|
12
|
+
# @!attribute [r] item
|
13
|
+
# @return [Hash] the Sidekiq job hash
|
14
|
+
attr_reader :item
|
15
|
+
|
16
|
+
# @param [Hash] item the Sidekiq job hash
|
17
|
+
# @option item [Integer, nil] :lock_ttl the configured lock expiration
|
18
|
+
# @option item [Integer, nil] :lock_timeout the configured lock timeout
|
19
|
+
# @option item [String] :class the class of the sidekiq worker
|
20
|
+
# @option item [Float] :at the unix time the job is scheduled at
|
21
|
+
def initialize(item)
|
22
|
+
@item = item
|
23
|
+
@worker_class = item[CLASS]
|
24
|
+
end
|
25
|
+
|
26
|
+
#
|
27
|
+
# Calculates the time until the job is scheduled starting from now
|
28
|
+
#
|
29
|
+
#
|
30
|
+
# @return [Integer] the number of seconds until job is scheduled
|
31
|
+
#
|
32
|
+
def time_until_scheduled
|
33
|
+
return 0 unless scheduled_at
|
34
|
+
|
35
|
+
scheduled_at.to_i - Time.now.utc.to_i
|
36
|
+
end
|
37
|
+
|
38
|
+
# The time a job is scheduled
|
39
|
+
# @return [Float] the exact unix time the job is scheduled at
|
40
|
+
def scheduled_at
|
41
|
+
@scheduled_at ||= item[AT]
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# Computes lock ttl from job arguments, sidekiq_options.
|
46
|
+
# Falls back to {default_lock_ttl}
|
47
|
+
#
|
48
|
+
# @note this method takes into consideration the time
|
49
|
+
# until a job is scheduled
|
50
|
+
#
|
51
|
+
#
|
52
|
+
# @return [Integer] the number of seconds to live
|
53
|
+
#
|
54
|
+
def lock_ttl
|
55
|
+
@lock_ttl ||= begin
|
56
|
+
ttl = item[LOCK_TTL]
|
57
|
+
ttl ||= worker_options[LOCK_TTL]
|
58
|
+
ttl ||= item[LOCK_EXPIRATION] # TODO: Deprecate at some point
|
59
|
+
ttl ||= worker_options[LOCK_EXPIRATION] # TODO: Deprecate at some point
|
60
|
+
ttl ||= default_lock_ttl
|
61
|
+
ttl && ttl.to_i + time_until_scheduled
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
#
|
66
|
+
# Finds a lock timeout in either of
|
67
|
+
# default worker options, {default_lock_timeout} or provided worker_options
|
68
|
+
#
|
69
|
+
#
|
70
|
+
# @return [Integer, nil]
|
71
|
+
#
|
72
|
+
def lock_timeout
|
73
|
+
@lock_timeout = begin
|
74
|
+
timeout = default_worker_options[LOCK_TIMEOUT]
|
75
|
+
timeout = default_lock_timeout if default_lock_timeout
|
76
|
+
timeout = worker_options[LOCK_TIMEOUT] if worker_options.key?(LOCK_TIMEOUT)
|
77
|
+
timeout
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
#
|
82
|
+
# The configured default_lock_timeout
|
83
|
+
# @see SidekiqUniqueJobs::Config#default_lock_timeout
|
84
|
+
#
|
85
|
+
#
|
86
|
+
# @return [Integer, nil]
|
87
|
+
#
|
88
|
+
def default_lock_timeout
|
89
|
+
SidekiqUniqueJobs.config.default_lock_timeout
|
90
|
+
end
|
91
|
+
|
92
|
+
#
|
93
|
+
# The configured default_lock_ttl
|
94
|
+
# @see SidekiqUniqueJobs::Config#default_lock_ttl
|
95
|
+
#
|
96
|
+
#
|
97
|
+
# @return [Integer, nil]
|
98
|
+
#
|
99
|
+
def default_lock_ttl
|
100
|
+
SidekiqUniqueJobs.config.default_lock_ttl
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SidekiqUniqueJobs
|
4
|
+
# Handles timing of things
|
5
|
+
#
|
6
|
+
# @author Mikael Henriksson <mikael@zoolutions.se>
|
7
|
+
module Timing
|
8
|
+
module_function
|
9
|
+
|
10
|
+
#
|
11
|
+
# Used for timing method calls
|
12
|
+
#
|
13
|
+
#
|
14
|
+
# @return [yield return, Float]
|
15
|
+
#
|
16
|
+
def timed
|
17
|
+
start_time = time_source.call
|
18
|
+
|
19
|
+
[yield, time_source.call - start_time]
|
20
|
+
end
|
21
|
+
|
22
|
+
#
|
23
|
+
# Used to get a current representation of time as Integer
|
24
|
+
#
|
25
|
+
#
|
26
|
+
# @return [Integer]
|
27
|
+
#
|
28
|
+
def time_source
|
29
|
+
-> { (clock_stamp * 1000).to_i }
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# Returns the current time as float
|
34
|
+
#
|
35
|
+
# @see SidekiqUniqueJobs.now_f
|
36
|
+
#
|
37
|
+
# @return [Float]
|
38
|
+
#
|
39
|
+
def now_f
|
40
|
+
SidekiqUniqueJobs.now_f
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# Returns a float representation of the current time.
|
45
|
+
# Either from Process or Time
|
46
|
+
#
|
47
|
+
#
|
48
|
+
# @return [Float]
|
49
|
+
#
|
50
|
+
def clock_stamp
|
51
|
+
if Process.const_defined?("CLOCK_MONOTONIC")
|
52
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
53
|
+
else
|
54
|
+
Time.now.to_f
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -1,9 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "digest"
|
4
|
-
require "openssl"
|
5
|
-
require "sidekiq_unique_jobs/normalizer"
|
6
|
-
|
7
3
|
module SidekiqUniqueJobs
|
8
4
|
# Handles uniqueness of sidekiq arguments
|
9
5
|
#
|
@@ -11,6 +7,7 @@ module SidekiqUniqueJobs
|
|
11
7
|
class UniqueArgs
|
12
8
|
include SidekiqUniqueJobs::Logging
|
13
9
|
include SidekiqUniqueJobs::SidekiqWorkerMethods
|
10
|
+
include SidekiqUniqueJobs::JSON
|
14
11
|
|
15
12
|
# Convenience method for returning a digest
|
16
13
|
# @param [Hash] item a Sidekiq job hash
|
@@ -26,7 +23,7 @@ module SidekiqUniqueJobs
|
|
26
23
|
# @param [Hash] item a Sidekiq job hash
|
27
24
|
def initialize(item)
|
28
25
|
@item = item
|
29
|
-
@worker_class = item[
|
26
|
+
@worker_class = item[CLASS]
|
30
27
|
|
31
28
|
add_uniqueness_to_item
|
32
29
|
end
|
@@ -34,9 +31,9 @@ module SidekiqUniqueJobs
|
|
34
31
|
# Appends the keys unique_prefix, unique_args and {#unique_digest} to the sidekiq job hash {#item}
|
35
32
|
# @return [void]
|
36
33
|
def add_uniqueness_to_item
|
37
|
-
item[
|
38
|
-
item[
|
39
|
-
item[
|
34
|
+
item[UNIQUE_PREFIX] ||= unique_prefix
|
35
|
+
item[UNIQUE_ARGS] = unique_args(item[ARGS])
|
36
|
+
item[UNIQUE_DIGEST] = unique_digest
|
40
37
|
end
|
41
38
|
|
42
39
|
# Memoized unique_digest
|
@@ -48,22 +45,22 @@ module SidekiqUniqueJobs
|
|
48
45
|
# Creates a namespaced unique digest based on the {#digestable_hash} and the {#unique_prefix}
|
49
46
|
# @return [String] a unique digest
|
50
47
|
def create_digest
|
51
|
-
digest =
|
48
|
+
digest = Digest::MD5.hexdigest(dump_json(digestable_hash))
|
52
49
|
"#{unique_prefix}:#{digest}"
|
53
50
|
end
|
54
51
|
|
55
52
|
# A prefix to use as namespace for the {#unique_digest}
|
56
53
|
# @return [String] a unique digest
|
57
54
|
def unique_prefix
|
58
|
-
worker_options[
|
55
|
+
worker_options[UNIQUE_PREFIX] || SidekiqUniqueJobs.config.unique_prefix
|
59
56
|
end
|
60
57
|
|
61
58
|
# Filter a hash to use for digest
|
62
59
|
# @return [Hash] to use for digest
|
63
60
|
def digestable_hash
|
64
|
-
@item.slice(
|
65
|
-
hash.delete(
|
66
|
-
hash.delete(
|
61
|
+
@item.slice(CLASS, QUEUE, UNIQUE_ARGS).tap do |hash|
|
62
|
+
hash.delete(QUEUE) if unique_across_queues?
|
63
|
+
hash.delete(CLASS) if unique_across_workers?
|
67
64
|
end
|
68
65
|
end
|
69
66
|
|
@@ -78,14 +75,13 @@ module SidekiqUniqueJobs
|
|
78
75
|
# Checks if we should disregard the queue when creating the unique digest
|
79
76
|
# @return [true, false]
|
80
77
|
def unique_across_queues?
|
81
|
-
item[
|
82
|
-
item[UNIQUE_ON_ALL_QUEUES_KEY] || worker_options[UNIQUE_ON_ALL_QUEUES_KEY] # TODO: Remove in v 6.1
|
78
|
+
item[UNIQUE_ACROSS_QUEUES] || worker_options[UNIQUE_ACROSS_QUEUES]
|
83
79
|
end
|
84
80
|
|
85
81
|
# Checks if we should disregard the worker when creating the unique digest
|
86
82
|
# @return [true, false]
|
87
83
|
def unique_across_workers?
|
88
|
-
item[
|
84
|
+
item[UNIQUE_ACROSS_WORKERS] || worker_options[UNIQUE_ACROSS_WORKERS]
|
89
85
|
end
|
90
86
|
|
91
87
|
# Checks if the worker class has been enabled for unique_args?
|
@@ -130,21 +126,23 @@ module SidekiqUniqueJobs
|
|
130
126
|
return args unless worker_method_defined?(unique_args_method)
|
131
127
|
|
132
128
|
worker_class.send(unique_args_method, args)
|
133
|
-
rescue ArgumentError
|
134
|
-
|
135
|
-
|
129
|
+
rescue ArgumentError
|
130
|
+
raise SidekiqUniqueJobs::InvalidUniqueArguments,
|
131
|
+
given: args,
|
132
|
+
worker_class: worker_class,
|
133
|
+
unique_args_method: unique_args_method
|
136
134
|
end
|
137
135
|
|
138
136
|
# The method to use for filtering unique arguments
|
139
137
|
def unique_args_method
|
140
|
-
@unique_args_method ||= worker_options[
|
138
|
+
@unique_args_method ||= worker_options[UNIQUE_ARGS]
|
141
139
|
@unique_args_method ||= :unique_args if worker_method_defined?(:unique_args)
|
142
140
|
@unique_args_method ||= default_unique_args_method
|
143
141
|
end
|
144
142
|
|
145
143
|
# The global worker options defined in Sidekiq directly
|
146
144
|
def default_unique_args_method
|
147
|
-
Sidekiq.default_worker_options.stringify_keys[
|
145
|
+
Sidekiq.default_worker_options.stringify_keys[UNIQUE_ARGS]
|
148
146
|
end
|
149
147
|
end
|
150
148
|
end
|
@@ -12,14 +12,23 @@ module SidekiqUniqueJobs
|
|
12
12
|
# @param [Hash] item a Sidekiq job hash
|
13
13
|
def unlock(item)
|
14
14
|
SidekiqUniqueJobs::UniqueArgs.digest(item)
|
15
|
-
SidekiqUniqueJobs::Locksmith.new(item).unlock
|
15
|
+
SidekiqUniqueJobs::Locksmith.new(item).unlock!
|
16
16
|
end
|
17
17
|
|
18
|
-
# Deletes a lock
|
18
|
+
# Deletes a lock unless it has ttl
|
19
19
|
#
|
20
20
|
# This is good for situations when a job is locked by another item
|
21
21
|
# @param [Hash] item a Sidekiq job hash
|
22
22
|
def delete(item)
|
23
|
+
SidekiqUniqueJobs::UniqueArgs.digest(item)
|
24
|
+
SidekiqUniqueJobs::Locksmith.new(item).delete
|
25
|
+
end
|
26
|
+
|
27
|
+
# Deletes a lock regardless of if it was locked or has ttl.
|
28
|
+
#
|
29
|
+
# This is good for situations when a job is locked by another item
|
30
|
+
# @param [Hash] item a Sidekiq job hash
|
31
|
+
def delete!(item)
|
23
32
|
SidekiqUniqueJobs::UniqueArgs.digest(item)
|
24
33
|
SidekiqUniqueJobs::Locksmith.new(item).delete!
|
25
34
|
end
|