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
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SidekiqUniqueJobs
|
4
|
+
module Orphans
|
5
|
+
#
|
6
|
+
# Manages the orphan reaper
|
7
|
+
#
|
8
|
+
# @author Mikael Henriksson <mikael@zoolutions.se>
|
9
|
+
#
|
10
|
+
class Manager
|
11
|
+
include SidekiqUniqueJobs::Connection
|
12
|
+
include SidekiqUniqueJobs::Logging
|
13
|
+
|
14
|
+
#
|
15
|
+
# Starts a separate thread that periodically reaps orphans
|
16
|
+
#
|
17
|
+
#
|
18
|
+
# @return [Concurrent::TimerTask] the task that was started
|
19
|
+
#
|
20
|
+
def self.start
|
21
|
+
with_logging_context do
|
22
|
+
logger.info("Starting Reaper")
|
23
|
+
task.add_observer(Observer.new)
|
24
|
+
task.execute
|
25
|
+
task
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
# Stops the thread that reaps orphans
|
31
|
+
#
|
32
|
+
#
|
33
|
+
# @return [Boolean]
|
34
|
+
#
|
35
|
+
def self.stop
|
36
|
+
with_logging_context do
|
37
|
+
logger.info("Stopping Reaper")
|
38
|
+
task.shutdown
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# The task that runs the reaper
|
44
|
+
#
|
45
|
+
#
|
46
|
+
# @return [<type>] <description>
|
47
|
+
#
|
48
|
+
def self.task
|
49
|
+
@task ||= Concurrent::TimerTask.new(timer_task_options) do
|
50
|
+
with_logging_context do
|
51
|
+
redis do |conn|
|
52
|
+
Orphans::Reaper.call(conn)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
#
|
59
|
+
# Arguments passed on to the timer task
|
60
|
+
#
|
61
|
+
#
|
62
|
+
# @return [Hash]
|
63
|
+
#
|
64
|
+
def self.timer_task_options
|
65
|
+
{ run_now: true,
|
66
|
+
execution_interval: reaper_interval,
|
67
|
+
timeout_interval: reaper_timeout }
|
68
|
+
end
|
69
|
+
|
70
|
+
#
|
71
|
+
# @see SidekiqUniqueJobs::Config#reaper_interval
|
72
|
+
#
|
73
|
+
def self.reaper_interval
|
74
|
+
SidekiqUniqueJobs.config.reaper_interval
|
75
|
+
end
|
76
|
+
|
77
|
+
#
|
78
|
+
# @see SidekiqUniqueJobs::Config#reaper_timeout
|
79
|
+
#
|
80
|
+
def self.reaper_timeout
|
81
|
+
SidekiqUniqueJobs.config.reaper_timeout
|
82
|
+
end
|
83
|
+
|
84
|
+
#
|
85
|
+
# A context to use for all log entries
|
86
|
+
#
|
87
|
+
#
|
88
|
+
# @return [Hash] when logger responds to `:with_context`
|
89
|
+
# @return [String] when logger does not responds to `:with_context`
|
90
|
+
#
|
91
|
+
def self.logging_context
|
92
|
+
if logger_context_hash?
|
93
|
+
{ "uniquejobs" => "reaper" }
|
94
|
+
else
|
95
|
+
"uniquejobs=orphan-reaper"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SidekiqUniqueJobs
|
4
|
+
#
|
5
|
+
# Class DeleteOrphans provides deletion of orphaned digests
|
6
|
+
#
|
7
|
+
# @note this is a much slower version of the lua script but does not crash redis
|
8
|
+
#
|
9
|
+
# @author Mikael Henriksson <mikael@zoolutions.se>
|
10
|
+
#
|
11
|
+
module Orphans
|
12
|
+
#
|
13
|
+
# Observes the Orphan::Manager and provides information about each execution
|
14
|
+
#
|
15
|
+
# @author Mikael Henriksson <mikael@zoolutions.se>
|
16
|
+
#
|
17
|
+
class Observer
|
18
|
+
include SidekiqUniqueJobs::Logging
|
19
|
+
|
20
|
+
#
|
21
|
+
# Runs every time the {Manager} executes the TimerTask
|
22
|
+
# used for logging information about the reaping
|
23
|
+
#
|
24
|
+
# @param [Time] time the time of the execution
|
25
|
+
# @param [Object] result the result of the execution
|
26
|
+
# @param [Exception] ex any error raised from the TimerTask
|
27
|
+
#
|
28
|
+
# @return [<type>] <description>
|
29
|
+
#
|
30
|
+
def update(time, result, ex)
|
31
|
+
if result
|
32
|
+
log_info("(#{time}) Execution successfully returned #{result}")
|
33
|
+
elsif ex.is_a?(Concurrent::TimeoutError)
|
34
|
+
log_warn("(#{time}) Execution timed out")
|
35
|
+
else
|
36
|
+
log_info("(#{time}) Cleanup failed with error #{ex.message}")
|
37
|
+
log_error(ex)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,201 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SidekiqUniqueJobs
|
4
|
+
module Orphans
|
5
|
+
#
|
6
|
+
# Class DeleteOrphans provides deletion of orphaned digests
|
7
|
+
#
|
8
|
+
# @note this is a much slower version of the lua script but does not crash redis
|
9
|
+
#
|
10
|
+
# @author Mikael Henriksson <mikael@zoolutions.se>
|
11
|
+
#
|
12
|
+
class Reaper
|
13
|
+
include SidekiqUniqueJobs::Connection
|
14
|
+
include SidekiqUniqueJobs::Script::Caller
|
15
|
+
include SidekiqUniqueJobs::Logging
|
16
|
+
|
17
|
+
#
|
18
|
+
# Execute deletion of orphaned digests
|
19
|
+
#
|
20
|
+
# @param [Redis] conn nil a connection to redis
|
21
|
+
#
|
22
|
+
# @return [void]
|
23
|
+
#
|
24
|
+
def self.call(conn = nil)
|
25
|
+
return new(conn).call if conn
|
26
|
+
|
27
|
+
redis { |rcon| new(rcon).call }
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_reader :conn, :digests, :scheduled, :retried
|
31
|
+
|
32
|
+
#
|
33
|
+
# Initialize a new instance of DeleteOrphans
|
34
|
+
#
|
35
|
+
# @param [Redis] conn a connection to redis
|
36
|
+
#
|
37
|
+
def initialize(conn)
|
38
|
+
@conn = conn
|
39
|
+
@digests = SidekiqUniqueJobs::Digests.new
|
40
|
+
@scheduled = Redis::SortedSet.new(SCHEDULE)
|
41
|
+
@retried = Redis::SortedSet.new(RETRY)
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# Convenient access to the global configuration
|
46
|
+
#
|
47
|
+
#
|
48
|
+
# @return [SidekiqUniqueJobs::Config]
|
49
|
+
#
|
50
|
+
def config
|
51
|
+
SidekiqUniqueJobs.config
|
52
|
+
end
|
53
|
+
|
54
|
+
#
|
55
|
+
# The reaper that was configured
|
56
|
+
#
|
57
|
+
#
|
58
|
+
# @return [Symbol]
|
59
|
+
#
|
60
|
+
def reaper
|
61
|
+
config.reaper
|
62
|
+
end
|
63
|
+
|
64
|
+
#
|
65
|
+
# The number of locks to reap at a time
|
66
|
+
#
|
67
|
+
#
|
68
|
+
# @return [Integer]
|
69
|
+
#
|
70
|
+
def reaper_count
|
71
|
+
config.reaper_count
|
72
|
+
end
|
73
|
+
|
74
|
+
#
|
75
|
+
# Delete orphaned digests
|
76
|
+
#
|
77
|
+
#
|
78
|
+
# @return [Integer] the number of reaped locks
|
79
|
+
#
|
80
|
+
def call
|
81
|
+
case reaper
|
82
|
+
when :ruby
|
83
|
+
execute_ruby_reaper
|
84
|
+
when :lua
|
85
|
+
execute_lua_reaper
|
86
|
+
else
|
87
|
+
log_fatal(":#{reaper} is invalid for `SidekiqUnqiueJobs.config.reaper`")
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
#
|
92
|
+
# Executes the ruby reaper
|
93
|
+
#
|
94
|
+
#
|
95
|
+
# @return [Integer] the number of deleted locks
|
96
|
+
#
|
97
|
+
def execute_ruby_reaper
|
98
|
+
BatchDelete.call(orphans, conn)
|
99
|
+
end
|
100
|
+
|
101
|
+
#
|
102
|
+
# Executes the lua reaper
|
103
|
+
#
|
104
|
+
#
|
105
|
+
# @return [Integer] the number of deleted locks
|
106
|
+
#
|
107
|
+
def execute_lua_reaper
|
108
|
+
call_script(
|
109
|
+
:reap_orphans,
|
110
|
+
conn,
|
111
|
+
keys: [SidekiqUniqueJobs::DIGESTS, SidekiqUniqueJobs::SCHEDULE, SidekiqUniqueJobs::RETRY],
|
112
|
+
argv: [reaper_count],
|
113
|
+
)
|
114
|
+
end
|
115
|
+
|
116
|
+
#
|
117
|
+
# Find orphaned digests
|
118
|
+
#
|
119
|
+
#
|
120
|
+
# @return [Array<String>] an array of orphaned digests
|
121
|
+
#
|
122
|
+
def orphans
|
123
|
+
conn.zrevrange(digests.key, 0, -1).each_with_object([]) do |digest, result|
|
124
|
+
next if belongs_to_job?(digest)
|
125
|
+
|
126
|
+
result << digest
|
127
|
+
break if result.size >= reaper_count
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
#
|
132
|
+
# Checks if the digest has a matching job.
|
133
|
+
# 1. It checks the scheduled set
|
134
|
+
# 2. It checks the retry set
|
135
|
+
# 3. It goes through all queues
|
136
|
+
#
|
137
|
+
#
|
138
|
+
# @param [String] digest the digest to search for
|
139
|
+
#
|
140
|
+
# @return [true] when either of the checks return true
|
141
|
+
# @return [false] when no job was found for this digest
|
142
|
+
#
|
143
|
+
def belongs_to_job?(digest)
|
144
|
+
scheduled?(digest) || retried?(digest) || enqueued?(digest)
|
145
|
+
end
|
146
|
+
|
147
|
+
#
|
148
|
+
# Checks if the digest exists in the Sidekiq::ScheduledSet
|
149
|
+
#
|
150
|
+
# @param [String] digest the current digest
|
151
|
+
#
|
152
|
+
# @return [true] when digest exists in scheduled set
|
153
|
+
#
|
154
|
+
def scheduled?(digest)
|
155
|
+
in_sorted_set?(SCHEDULE, digest)
|
156
|
+
end
|
157
|
+
|
158
|
+
#
|
159
|
+
# Checks if the digest exists in the Sidekiq::RetrySet
|
160
|
+
#
|
161
|
+
# @param [String] digest the current digest
|
162
|
+
#
|
163
|
+
# @return [true] when digest exists in retry set
|
164
|
+
#
|
165
|
+
def retried?(digest)
|
166
|
+
in_sorted_set?(RETRY, digest)
|
167
|
+
end
|
168
|
+
|
169
|
+
#
|
170
|
+
# Checks if the digest exists in a Sidekiq::Queue
|
171
|
+
#
|
172
|
+
# @param [String] digest the current digest
|
173
|
+
#
|
174
|
+
# @return [true] when digest exists in any queue
|
175
|
+
#
|
176
|
+
#
|
177
|
+
def enqueued?(digest)
|
178
|
+
if (result = call_script(:find_digest_in_queues, conn, keys: [digest]))
|
179
|
+
log_debug("#{digest} found in #{result}")
|
180
|
+
true
|
181
|
+
else
|
182
|
+
log_debug("#{digest} NOT found in any queues")
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
#
|
187
|
+
# Checks a sorted set for the existance of this digest
|
188
|
+
#
|
189
|
+
#
|
190
|
+
# @param [String] key the key for the sorted set
|
191
|
+
# @param [String] digest the digest to scan for
|
192
|
+
#
|
193
|
+
# @return [true] when found
|
194
|
+
# @return [false] when missing
|
195
|
+
#
|
196
|
+
def in_sorted_set?(key, digest)
|
197
|
+
conn.zscan_each(key, match: "*#{digest}*", count: 1).to_a.any?
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SidekiqUniqueJobs
|
4
|
+
#
|
5
|
+
# Class MethodProfiler provides method level profiling
|
6
|
+
#
|
7
|
+
# @author Mikael Henriksson <mikael@zoolutions.se>
|
8
|
+
#
|
9
|
+
class Profiler
|
10
|
+
def self.patch(klass, methods, name) # rubocop:disable Metrics/MethodLength
|
11
|
+
patches = methods.map do |method_name|
|
12
|
+
<<~RUBY
|
13
|
+
unless defined?(#{method_name}__mp_unpatched)
|
14
|
+
alias_method :#{method_name}__mp_unpatched, :#{method_name}
|
15
|
+
def #{method_name}(*args, &blk)
|
16
|
+
unless prof = Thread.current[:_method_profiler]
|
17
|
+
return #{method_name}__mp_unpatched(*args, &blk)
|
18
|
+
end
|
19
|
+
begin
|
20
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
21
|
+
#{method_name}__mp_unpatched(*args, &blk)
|
22
|
+
ensure
|
23
|
+
data = (prof[:#{name}] ||= {duration: 0.0, calls: 0})
|
24
|
+
data[:duration] += Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
|
25
|
+
data[:calls] += 1
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
RUBY
|
30
|
+
end.join("\n")
|
31
|
+
|
32
|
+
klass.class_eval patches
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.start
|
36
|
+
Thread.current[:_method_profiler] = {
|
37
|
+
__start: Process.clock_gettime(Process::CLOCK_MONOTONIC),
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.stop
|
42
|
+
finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
43
|
+
return unless (data = Thread.current[:_method_profiler])
|
44
|
+
|
45
|
+
Thread.current[:_method_profiler] = nil
|
46
|
+
start = data.delete(:__start)
|
47
|
+
data[:total_duration] = finish - start
|
48
|
+
data
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SidekiqUniqueJobs
|
4
|
+
module Redis
|
5
|
+
#
|
6
|
+
# Class Entity functions as a base class for redis types
|
7
|
+
#
|
8
|
+
# @author Mikael Henriksson <mikael@zoolutions.se>
|
9
|
+
#
|
10
|
+
class Entity
|
11
|
+
# includes "SidekiqUniqueJobs::Logging"
|
12
|
+
# @!parse include SidekiqUniqueJobs::Logging
|
13
|
+
include SidekiqUniqueJobs::Logging
|
14
|
+
|
15
|
+
# includes "SidekiqUniqueJobs::Script::Caller"
|
16
|
+
# @!parse include SidekiqUniqueJobs::Script::Caller
|
17
|
+
include SidekiqUniqueJobs::Script::Caller
|
18
|
+
|
19
|
+
# includes "SidekiqUniqueJobs::JSON"
|
20
|
+
# @!parse include SidekiqUniqueJobs::JSON
|
21
|
+
include SidekiqUniqueJobs::JSON
|
22
|
+
|
23
|
+
# includes "SidekiqUniqueJobs::Timing"
|
24
|
+
# @!parse include SidekiqUniqueJobs::Timing
|
25
|
+
include SidekiqUniqueJobs::Timing
|
26
|
+
|
27
|
+
#
|
28
|
+
# @!attribute [r] key
|
29
|
+
# @return [String] the redis key for this entity
|
30
|
+
attr_reader :key
|
31
|
+
|
32
|
+
#
|
33
|
+
# Initialize a new Entity
|
34
|
+
#
|
35
|
+
# @param [String] key the redis key for this entity
|
36
|
+
#
|
37
|
+
def initialize(key)
|
38
|
+
@key = key
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# Checks if the key for this entity exists in redis
|
43
|
+
#
|
44
|
+
#
|
45
|
+
# @return [true] when exists
|
46
|
+
# @return [false] when not exists
|
47
|
+
#
|
48
|
+
def exist?
|
49
|
+
redis { |conn| conn.exists(key) }
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# The number of microseconds until the key expires
|
54
|
+
#
|
55
|
+
#
|
56
|
+
# @return [Integer] expiration in milliseconds
|
57
|
+
#
|
58
|
+
def pttl
|
59
|
+
redis { |conn| conn.pttl(key) }
|
60
|
+
end
|
61
|
+
|
62
|
+
#
|
63
|
+
# The number of seconds until the key expires
|
64
|
+
#
|
65
|
+
#
|
66
|
+
# @return [Integer] expiration in seconds
|
67
|
+
#
|
68
|
+
def ttl
|
69
|
+
redis { |conn| conn.ttl(key) }
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# Check if the entity has expiration
|
74
|
+
#
|
75
|
+
#
|
76
|
+
# @return [true] when entity is set to exire
|
77
|
+
# @return [false] when entity isn't expiring
|
78
|
+
#
|
79
|
+
def expires?
|
80
|
+
pttl.positive? || ttl.positive?
|
81
|
+
end
|
82
|
+
|
83
|
+
#
|
84
|
+
# Returns the number of entries in this entity
|
85
|
+
#
|
86
|
+
#
|
87
|
+
# @return [Integer] 0
|
88
|
+
#
|
89
|
+
def count
|
90
|
+
0
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|