redis_queued_locks 1.13.0 → 1.14.0
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +0 -1
- data/.ruby-version +1 -1
- data/CHANGELOG.md +14 -1
- data/README.md +361 -102
- data/Rakefile +1 -1
- data/Steepfile +0 -1
- data/lib/redis_queued_locks/acquirer/acquire_lock.rb +7 -7
- data/lib/redis_queued_locks/acquirer/release_all_locks.rb +3 -3
- data/lib/redis_queued_locks/acquirer/release_lock.rb +3 -3
- data/lib/redis_queued_locks/acquirer/release_locks_of.rb +211 -0
- data/lib/redis_queued_locks/acquirer.rb +1 -0
- data/lib/redis_queued_locks/client.rb +155 -2
- data/lib/redis_queued_locks/config/dsl.rb +9 -9
- data/lib/redis_queued_locks/config.rb +15 -10
- data/lib/redis_queued_locks/errors.rb +3 -3
- data/lib/redis_queued_locks/utilities.rb +9 -0
- data/lib/redis_queued_locks/version.rb +2 -2
- data/lib/redis_queued_locks.rb +0 -1
- data/rbs_collection.lock.yaml +1 -13
- data/rbs_collection.yaml +2 -1
- data/sig/manifest.yml +0 -1
- data/sig/redis_queued_locks/acquirer/acquire_lock.rbs +1 -0
- data/sig/redis_queued_locks/acquirer/release_locks_of.rbs +46 -0
- data/sig/redis_queued_locks/client.rbs +40 -0
- data/sig/redis_queued_locks/utilities.rbs +1 -0
- metadata +4 -2
data/Rakefile
CHANGED
data/Steepfile
CHANGED
|
@@ -17,6 +17,8 @@ module RedisQueuedLocks::Acquirer::AcquireLock
|
|
|
17
17
|
require_relative 'acquire_lock/try_to_lock'
|
|
18
18
|
require_relative 'acquire_lock/dequeue_from_lock_queue'
|
|
19
19
|
|
|
20
|
+
# @since 1.14.0
|
|
21
|
+
extend RedisQueuedLocks::Utilities
|
|
20
22
|
# @since 1.0.0
|
|
21
23
|
extend TryToLock
|
|
22
24
|
# @since 1.0.0
|
|
@@ -157,7 +159,7 @@ module RedisQueuedLocks::Acquirer::AcquireLock
|
|
|
157
159
|
#
|
|
158
160
|
# @api private
|
|
159
161
|
# @since 1.0.0
|
|
160
|
-
# @version 1.
|
|
162
|
+
# @version 1.14.0
|
|
161
163
|
def acquire_lock(
|
|
162
164
|
redis,
|
|
163
165
|
lock_name,
|
|
@@ -309,7 +311,7 @@ module RedisQueuedLocks::Acquirer::AcquireLock
|
|
|
309
311
|
detailed_acq_timeout_error,
|
|
310
312
|
on_timeout: acq_dequeue
|
|
311
313
|
) do
|
|
312
|
-
acq_start_time =
|
|
314
|
+
acq_start_time = clock_gettime
|
|
313
315
|
|
|
314
316
|
# Step 2.1: cyclically try to obtain the lock
|
|
315
317
|
while acq_process[:should_try]
|
|
@@ -358,7 +360,7 @@ module RedisQueuedLocks::Acquirer::AcquireLock
|
|
|
358
360
|
# @type var ok: bool
|
|
359
361
|
# @type var result: Symbol|Hash[Symbol,untyped]
|
|
360
362
|
|
|
361
|
-
acq_end_time =
|
|
363
|
+
acq_end_time = clock_gettime
|
|
362
364
|
acq_time = ((acq_end_time - acq_start_time) / 1_000.0).ceil(2)
|
|
363
365
|
|
|
364
366
|
# Step X: save the intermediate results to the result observer
|
|
@@ -491,7 +493,7 @@ module RedisQueuedLocks::Acquirer::AcquireLock
|
|
|
491
493
|
# Step 3.a: acquired successfully => run logic or return the result of acquirement
|
|
492
494
|
if block_given?
|
|
493
495
|
begin
|
|
494
|
-
yield_time =
|
|
496
|
+
yield_time = clock_gettime
|
|
495
497
|
|
|
496
498
|
ttl_shift = (
|
|
497
499
|
(yield_time - acq_process[:acq_end_time]) / 1_000.0 -
|
|
@@ -524,9 +526,7 @@ module RedisQueuedLocks::Acquirer::AcquireLock
|
|
|
524
526
|
&block
|
|
525
527
|
)
|
|
526
528
|
ensure
|
|
527
|
-
acq_process[:rel_time] =
|
|
528
|
-
::Process::CLOCK_MONOTONIC, :microsecond
|
|
529
|
-
)
|
|
529
|
+
acq_process[:rel_time] = clock_gettime
|
|
530
530
|
acq_process[:hold_time] = (
|
|
531
531
|
(acq_process[:rel_time] - acq_process[:acq_end_time]) / 1_000.0
|
|
532
532
|
).ceil(2)
|
|
@@ -71,7 +71,7 @@ module RedisQueuedLocks::Acquirer::ReleaseAllLocks
|
|
|
71
71
|
#
|
|
72
72
|
# @api private
|
|
73
73
|
# @since 1.0.0
|
|
74
|
-
# @version 1.
|
|
74
|
+
# @version 1.14.0
|
|
75
75
|
def release_all_locks(
|
|
76
76
|
redis,
|
|
77
77
|
batch_size,
|
|
@@ -87,14 +87,14 @@ module RedisQueuedLocks::Acquirer::ReleaseAllLocks
|
|
|
87
87
|
instr_sampler,
|
|
88
88
|
instr_sample_this
|
|
89
89
|
)
|
|
90
|
-
rel_start_time =
|
|
90
|
+
rel_start_time = clock_gettime
|
|
91
91
|
fully_release_all_locks(redis, batch_size) => { ok:, result: } # steep:ignore
|
|
92
92
|
|
|
93
93
|
# @type var ok: bool
|
|
94
94
|
# @type var result: Hash[Symbol,Integer]
|
|
95
95
|
|
|
96
96
|
time_at = Time.now.to_f
|
|
97
|
-
rel_end_time =
|
|
97
|
+
rel_end_time = clock_gettime
|
|
98
98
|
rel_time = ((rel_end_time - rel_start_time) / 1_000.0).ceil(2)
|
|
99
99
|
|
|
100
100
|
instr_sampled = RedisQueuedLocks::Instrument.should_instrument?(
|
|
@@ -71,7 +71,7 @@ module RedisQueuedLocks::Acquirer::ReleaseLock
|
|
|
71
71
|
#
|
|
72
72
|
# @api private
|
|
73
73
|
# @since 1.0.0
|
|
74
|
-
# @version 1.
|
|
74
|
+
# @version 1.14.0
|
|
75
75
|
# rubocop:disable Metrics/MethodLength
|
|
76
76
|
def release_lock(
|
|
77
77
|
redis,
|
|
@@ -90,14 +90,14 @@ module RedisQueuedLocks::Acquirer::ReleaseLock
|
|
|
90
90
|
lock_key = RedisQueuedLocks::Resource.prepare_lock_key(lock_name)
|
|
91
91
|
lock_key_queue = RedisQueuedLocks::Resource.prepare_lock_queue(lock_name)
|
|
92
92
|
|
|
93
|
-
rel_start_time =
|
|
93
|
+
rel_start_time = clock_gettime
|
|
94
94
|
fully_release_lock(redis, lock_key, lock_key_queue) => { ok:, result: } # steep:ignore
|
|
95
95
|
|
|
96
96
|
# @type var ok: bool
|
|
97
97
|
# @type var result: Hash[Symbol,Symbol]
|
|
98
98
|
|
|
99
99
|
time_at = Time.now.to_f
|
|
100
|
-
rel_end_time =
|
|
100
|
+
rel_end_time = clock_gettime
|
|
101
101
|
rel_time = ((rel_end_time - rel_start_time) / 1_000.0).ceil(2)
|
|
102
102
|
|
|
103
103
|
instr_sampled = RedisQueuedLocks::Instrument.should_instrument?(
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# @api private
|
|
4
|
+
# @since 1.14.0
|
|
5
|
+
module RedisQueuedLocks::Acquirer::ReleaseLocksOf
|
|
6
|
+
# @since 1.14.0
|
|
7
|
+
extend RedisQueuedLocks::Utilities
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
# Release all queues and locks that belong to the given host and its associated acquirer.
|
|
11
|
+
#
|
|
12
|
+
# @param refused_host_id [String]
|
|
13
|
+
# A host whose locks and queues should be released.
|
|
14
|
+
# @param refused_acquirer_id [String]
|
|
15
|
+
# An acquirer (of the passed host) whose locks and queues should be released.
|
|
16
|
+
# @param redis [RedisClient]
|
|
17
|
+
# Redis connection client.
|
|
18
|
+
# @param lock_scan_size [Integer]
|
|
19
|
+
# The number of lock keys that should be released in a time.
|
|
20
|
+
# Affects the RubyVM memmory (cuz each found lock will be temporary stored in memory for
|
|
21
|
+
# subsequent removal from redis in one query at a time).
|
|
22
|
+
# @param queue_scan_size [Integer]
|
|
23
|
+
# The number of lock queues that should be scanned removing an acquirer from them (at a time).
|
|
24
|
+
# @param logger [::Logger,#debug]
|
|
25
|
+
# - Logger object used from `configuration` layer (see config['logger']);
|
|
26
|
+
# - See RedisQueuedLocks::Logging::VoidLogger for example;
|
|
27
|
+
# @param isntrumenter [#notify]
|
|
28
|
+
# See RedisQueuedLocks::Instrument::ActiveSupport for example.
|
|
29
|
+
# @param instrument [NilClass,Any]
|
|
30
|
+
# - Custom instrumentation data wich will be passed to the instrumenter's payload
|
|
31
|
+
# with :instrument key;
|
|
32
|
+
# @param log_sampling_enabled [Boolean]
|
|
33
|
+
# - enables <log sampling>: only the configured percent of RQL cases will be logged;
|
|
34
|
+
# - disabled by default;
|
|
35
|
+
# - works in tandem with <config['log_sampling_percent']> and <config['log_sampler']>;
|
|
36
|
+
# @param log_sampling_percent [Integer]
|
|
37
|
+
# - the percent of cases that should be logged;
|
|
38
|
+
# - take an effect when <config['log_sampling_enalbed']> is true;
|
|
39
|
+
# - works in tandem with <config['log_sampling_enabled']> and <config['log_sampler']> configs;
|
|
40
|
+
# @param log_sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
|
|
41
|
+
# - percent-based log sampler that decides should be RQL case logged or not;
|
|
42
|
+
# - works in tandem with <config['log_sampling_enabled']> and
|
|
43
|
+
# <config['log_sampling_percent']> configs;
|
|
44
|
+
# - based on the ultra simple percent-based (weight-based) algorithm that uses
|
|
45
|
+
# SecureRandom.rand method so the algorithm error is ~(0%..13%);
|
|
46
|
+
# - you can provide your own log sampler with bettter algorithm that should realize
|
|
47
|
+
# `sampling_happened?(percent) => boolean` interface
|
|
48
|
+
# (see `RedisQueuedLocks::Logging::Sampler` for example);
|
|
49
|
+
# @param log_sample_this [Boolean]
|
|
50
|
+
# - marks the method that everything should be logged despite the enabled log sampling;
|
|
51
|
+
# - makes sense when log sampling is enabled;
|
|
52
|
+
# @param instr_sampling_enabled [Boolean]
|
|
53
|
+
# - enables <instrumentaion sampling>: only the configured percent
|
|
54
|
+
# of RQL cases will be instrumented;
|
|
55
|
+
# - disabled by default;
|
|
56
|
+
# - works in tandem with <config['instr_sampling_percent']> and <config['instr_sampler']>;
|
|
57
|
+
# @param instr_sampling_percent [Integer]
|
|
58
|
+
# - the percent of cases that should be instrumented;
|
|
59
|
+
# - take an effect when <config['instr_sampling_enalbed']> is true;
|
|
60
|
+
# - works in tandem with <config['instr_sampling_enabled']>
|
|
61
|
+
# and <config['instr_sampler']> configs;
|
|
62
|
+
# @param instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
|
|
63
|
+
# - percent-based log sampler that decides should be RQL case instrumented or not;
|
|
64
|
+
# - works in tandem with <config['instr_sampling_enabled']> and
|
|
65
|
+
# <config['instr_sampling_percent']> configs;
|
|
66
|
+
# - based on the ultra simple percent-based (weight-based) algorithm that uses
|
|
67
|
+
# SecureRandom.rand method so the algorithm error is ~(0%..13%);
|
|
68
|
+
# - you can provide your own log sampler with bettter algorithm that should realize
|
|
69
|
+
# `sampling_happened?(percent) => boolean` interface
|
|
70
|
+
# (see `RedisQueuedLocks::Instrument::Sampler` for example);
|
|
71
|
+
# @param instr_sample_this [Boolean]
|
|
72
|
+
# - marks the method that everything should be instrumneted
|
|
73
|
+
# despite the enabled instrumentation sampling;
|
|
74
|
+
# - makes sense when instrumentation sampling is enabled;
|
|
75
|
+
# @return [Hash<Symbol,Any>]
|
|
76
|
+
# Format: { ok: true, result: Hash<Symbol,Numeric> }
|
|
77
|
+
#
|
|
78
|
+
# @api private
|
|
79
|
+
# @since 1.14.0
|
|
80
|
+
# rubocop:disable Metrics/MethodLength
|
|
81
|
+
def release_locks_of(
|
|
82
|
+
refused_host_id,
|
|
83
|
+
refused_acquirer_id,
|
|
84
|
+
redis,
|
|
85
|
+
lock_scan_size,
|
|
86
|
+
queue_scan_size,
|
|
87
|
+
logger,
|
|
88
|
+
instrumenter,
|
|
89
|
+
instrument,
|
|
90
|
+
log_sampling_enabled,
|
|
91
|
+
log_sampling_percent,
|
|
92
|
+
log_sampler,
|
|
93
|
+
log_sample_this,
|
|
94
|
+
instr_sampling_enabled,
|
|
95
|
+
instr_sampling_percent,
|
|
96
|
+
instr_sampler,
|
|
97
|
+
instr_sample_this
|
|
98
|
+
) # TODO: move from SCAN to indexes :thinking:
|
|
99
|
+
rel_start_time = clock_gettime
|
|
100
|
+
|
|
101
|
+
# steep:ignore:start
|
|
102
|
+
fully_release_locks_of(
|
|
103
|
+
refused_host_id,
|
|
104
|
+
refused_acquirer_id,
|
|
105
|
+
redis,
|
|
106
|
+
lock_scan_size,
|
|
107
|
+
queue_scan_size
|
|
108
|
+
) => { ok:, result: }
|
|
109
|
+
# steep:ignore:end
|
|
110
|
+
|
|
111
|
+
# @type var ok: bool
|
|
112
|
+
# @type var result: Hash[Symbol,Integer]
|
|
113
|
+
|
|
114
|
+
time_at = Time.now.to_f
|
|
115
|
+
rel_end_time = clock_gettime
|
|
116
|
+
rel_time = ((rel_end_time - rel_start_time) / 1_000.0).ceil(2)
|
|
117
|
+
|
|
118
|
+
instr_sampled = RedisQueuedLocks::Instrument.should_instrument?(
|
|
119
|
+
instr_sampling_enabled,
|
|
120
|
+
instr_sample_this,
|
|
121
|
+
instr_sampling_percent,
|
|
122
|
+
instr_sampler
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
run_non_critical do
|
|
126
|
+
instrumenter.notify('redis_queued_locks.release_locks_of', {
|
|
127
|
+
at: time_at,
|
|
128
|
+
rel_time: rel_time,
|
|
129
|
+
rel_key_cnt: result[:rel_key_cnt],
|
|
130
|
+
tch_queue_cnt: result[:tch_queue_cnt]
|
|
131
|
+
})
|
|
132
|
+
end if instr_sampled
|
|
133
|
+
|
|
134
|
+
{
|
|
135
|
+
ok: true,
|
|
136
|
+
result: {
|
|
137
|
+
rel_key_cnt: result[:rel_key_cnt],
|
|
138
|
+
tch_queue_cnt: result[:tch_queue_cnt],
|
|
139
|
+
rel_time: rel_time
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
end
|
|
143
|
+
# rubocop:enable Metrics/MethodLength
|
|
144
|
+
|
|
145
|
+
private
|
|
146
|
+
|
|
147
|
+
# @param refused_host_id [String]
|
|
148
|
+
# @param refused_acquirer_id [String]
|
|
149
|
+
# @param redis [RedisClient]
|
|
150
|
+
# @param lock_scan_size [Integer]
|
|
151
|
+
# @param queue_scan_size [Integer]
|
|
152
|
+
# @return [Hash<Symbol,Boolean|Hash<Symbol,Integer>>]
|
|
153
|
+
# - Example: { ok: true, result: { rel_key_cnt: 12345, tch_queue_cnt: 321 } }
|
|
154
|
+
#
|
|
155
|
+
# @api private
|
|
156
|
+
# @since 1.14.0
|
|
157
|
+
# rubocop:disable Metrics/MethodLength
|
|
158
|
+
def fully_release_locks_of(
|
|
159
|
+
refused_host_id,
|
|
160
|
+
refused_acquirer_id,
|
|
161
|
+
redis,
|
|
162
|
+
lock_scan_size,
|
|
163
|
+
queue_scan_size
|
|
164
|
+
)
|
|
165
|
+
# TODO: some indexing approach isntead of <scan>
|
|
166
|
+
rel_key_cnt = 0
|
|
167
|
+
tch_queue_cnt = 0
|
|
168
|
+
|
|
169
|
+
redis.with do |rconn|
|
|
170
|
+
# Step A: drop locks of the passed host/acquirer
|
|
171
|
+
refused_locks = Set.new #: Set[String]
|
|
172
|
+
rconn.scan(
|
|
173
|
+
'MATCH',
|
|
174
|
+
RedisQueuedLocks::Resource::LOCK_PATTERN,
|
|
175
|
+
count: lock_scan_size
|
|
176
|
+
) do |lock_key|
|
|
177
|
+
acquirer_id, host_id = rconn.call('HMGET', lock_key, 'acq_id', 'hst_id')
|
|
178
|
+
if refused_host_id == host_id && refused_acquirer_id == acquirer_id
|
|
179
|
+
refused_locks << lock_key
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
if refused_locks.size >= lock_scan_size
|
|
183
|
+
# NOTE: steep can not recognize the `*`-splat operator on Set objects
|
|
184
|
+
rconn.call('DEL', *refused_locks) # steep:ignore
|
|
185
|
+
rel_key_cnt += refused_locks.size
|
|
186
|
+
refused_locks.clear
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
if refused_locks.any?
|
|
191
|
+
# NOTE: steep can not recognize the `*`-splat operator on Set objects
|
|
192
|
+
rconn.call('DEL', *refused_locks) # steep:ignore
|
|
193
|
+
rel_key_cnt += refused_locks.size
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Step B: drop passed host/acquirer from lock queues
|
|
197
|
+
rconn.scan(
|
|
198
|
+
'MATCH',
|
|
199
|
+
RedisQueuedLocks::Resource::LOCK_QUEUE_PATTERN,
|
|
200
|
+
count: queue_scan_size
|
|
201
|
+
) do |lock_queue|
|
|
202
|
+
res = rconn.call('ZREM', lock_queue, refused_acquirer_id)
|
|
203
|
+
tch_queue_cnt += 1 if res != 0
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
{ ok: true, result: { rel_key_cnt:, tch_queue_cnt: } }
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
# rubocop:enable Metrics/MethodLength
|
|
211
|
+
end
|
|
@@ -6,6 +6,7 @@ module RedisQueuedLocks::Acquirer
|
|
|
6
6
|
require_relative 'acquirer/acquire_lock'
|
|
7
7
|
require_relative 'acquirer/release_lock'
|
|
8
8
|
require_relative 'acquirer/release_all_locks'
|
|
9
|
+
require_relative 'acquirer/release_locks_of'
|
|
9
10
|
require_relative 'acquirer/is_locked'
|
|
10
11
|
require_relative 'acquirer/is_queued'
|
|
11
12
|
require_relative 'acquirer/lock_info'
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# @api public
|
|
4
4
|
# @since 1.0.0
|
|
5
|
+
# @version 1.14.0
|
|
5
6
|
# rubocop:disable Metrics/ClassLength
|
|
6
7
|
class RedisQueuedLocks::Client
|
|
7
8
|
# @return [RedisClient]
|
|
@@ -27,7 +28,7 @@ class RedisQueuedLocks::Client
|
|
|
27
28
|
# @return [RedisQueuedLocks::Config]
|
|
28
29
|
#
|
|
29
30
|
# @api public
|
|
30
|
-
# @since
|
|
31
|
+
# @since 1.13.0
|
|
31
32
|
attr_reader :config
|
|
32
33
|
|
|
33
34
|
# @param redis_client [RedisClient]
|
|
@@ -52,7 +53,7 @@ class RedisQueuedLocks::Client
|
|
|
52
53
|
# @return [void]
|
|
53
54
|
#
|
|
54
55
|
# @api public
|
|
55
|
-
# @since
|
|
56
|
+
# @since 1.13.0
|
|
56
57
|
def configure(&configuration)
|
|
57
58
|
config.configure(&configuration)
|
|
58
59
|
end
|
|
@@ -577,6 +578,8 @@ class RedisQueuedLocks::Client
|
|
|
577
578
|
identity
|
|
578
579
|
)
|
|
579
580
|
end
|
|
581
|
+
alias_method :current_acq_id, :current_acquirer_id
|
|
582
|
+
alias_method :acq_id, :current_acquirer_id
|
|
580
583
|
|
|
581
584
|
# Retrun the current host identifier.
|
|
582
585
|
#
|
|
@@ -608,6 +611,8 @@ class RedisQueuedLocks::Client
|
|
|
608
611
|
identity
|
|
609
612
|
)
|
|
610
613
|
end
|
|
614
|
+
alias_method :current_hst_id, :current_host_id
|
|
615
|
+
alias_method :hst_id, :current_host_id
|
|
611
616
|
|
|
612
617
|
# Return the list of possible host identifiers that can be reached from the current ractor.
|
|
613
618
|
#
|
|
@@ -739,6 +744,154 @@ class RedisQueuedLocks::Client
|
|
|
739
744
|
end
|
|
740
745
|
alias_method :release_locks, :clear_locks
|
|
741
746
|
|
|
747
|
+
# Release all locks of the passed acquirer/host and remove this acquirer/host from all queues;
|
|
748
|
+
#
|
|
749
|
+
# This is a cleanup helper intended for operational and debugging scenarios (for example: your
|
|
750
|
+
# current puma request thread is killed by Rack::Timeout and you need to cleanup all zombie RQL
|
|
751
|
+
# locks and lock reuqests obtained during the request processing).
|
|
752
|
+
#
|
|
753
|
+
# Identifiers can be extracted via:
|
|
754
|
+
# - `#current_host_id`
|
|
755
|
+
# - `#current_acquirer_id`
|
|
756
|
+
# - `#possible_host_ids`
|
|
757
|
+
# - lock data (extracted from Redis via #lock_info, #locks_info, #queue_info, #queues_info)
|
|
758
|
+
#
|
|
759
|
+
# @option host_id [String] Host identifier whose locks/queues should be released.
|
|
760
|
+
# @option acquirer_id [String] Acquirer identifier, associated with the `host_id`.
|
|
761
|
+
# @option lock_scan_size [Integer]
|
|
762
|
+
# @option queue_scan_size [Integer]
|
|
763
|
+
# @option logger [::Logger,#debug]
|
|
764
|
+
# @option instrumenter [#notify] See `config['instrumenter']` docs for details.
|
|
765
|
+
# @option instrument [NilClass,Any]
|
|
766
|
+
# @option log_sampling_enabled [Boolean]
|
|
767
|
+
# @option log_sampling_percent [Integer]
|
|
768
|
+
# @option log_sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
|
|
769
|
+
# @option log_sample_this [Boolean]
|
|
770
|
+
# @option instr_sampling_enabled [Boolean]
|
|
771
|
+
# @option instr_sampling_percent [Integer]
|
|
772
|
+
# @option instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
|
|
773
|
+
# @option instr_sample_this [Boolean]
|
|
774
|
+
# @return [Hash<Symbol,Boolean|Hash<Symbol,Numeric>>]
|
|
775
|
+
# Example: { ok: true, result: { rel_key_cnt: 100, tch_queue_cnt: 2, rel_time: 0.01 } }
|
|
776
|
+
#
|
|
777
|
+
# @example Release locks of the current process:
|
|
778
|
+
# client.clear_locks_of(
|
|
779
|
+
# host_id: client.current_host_id,
|
|
780
|
+
# acquirer_id: client.current_acquirer_id
|
|
781
|
+
# )
|
|
782
|
+
#
|
|
783
|
+
# @example Release locks of a different host/acquirer:
|
|
784
|
+
# client.clear_locks_of(
|
|
785
|
+
# host_id: "rql:hst:62681/2016/2032/b30ec5e4bea10512",
|
|
786
|
+
# acquirer_id: "ral:acq:62681/2016/2024/2032/b30ec5e4bea10512"
|
|
787
|
+
# )
|
|
788
|
+
#
|
|
789
|
+
# @see #clear_current_locks
|
|
790
|
+
# @see #current_host_id
|
|
791
|
+
# @see #current_acquirer_id
|
|
792
|
+
# @see #possible_host_ids
|
|
793
|
+
# @see #lock_info
|
|
794
|
+
# @see #locks_info
|
|
795
|
+
# @see #queue_info
|
|
796
|
+
# @see #queues_info
|
|
797
|
+
#
|
|
798
|
+
# @api public
|
|
799
|
+
# @since 1.14.0
|
|
800
|
+
def clear_locks_of(
|
|
801
|
+
host_id:,
|
|
802
|
+
acquirer_id:,
|
|
803
|
+
lock_scan_size: config['clear_locks_of__lock_scan_size'], # steep:ignore
|
|
804
|
+
queue_scan_size: config['clear_locks_of__queue_scan_size'], # steep:ingore
|
|
805
|
+
logger: config['logger'], # steep:ignore
|
|
806
|
+
instrumenter: config['instrumenter'], # steep:ignore
|
|
807
|
+
instrument: nil,
|
|
808
|
+
log_sampling_enabled: config['log_sampling_enabled'], # steep:ignore
|
|
809
|
+
log_sampling_percent: config['log_sampling_percent'], # steep:ignore
|
|
810
|
+
log_sampler: config['log_sampler'], # steep:ignore
|
|
811
|
+
log_sample_this: false,
|
|
812
|
+
instr_sampling_enabled: config['instr_sampling_enabled'], # steep:ignore
|
|
813
|
+
instr_sampling_percent: config['instr_sampling_percent'], # steep:ignore
|
|
814
|
+
instr_sampler: config['instr_sampler'], # steep:ignore
|
|
815
|
+
instr_sample_this: false
|
|
816
|
+
)
|
|
817
|
+
RedisQueuedLocks::Acquirer::ReleaseLocksOf.release_locks_of(
|
|
818
|
+
host_id,
|
|
819
|
+
acquirer_id,
|
|
820
|
+
redis_client,
|
|
821
|
+
lock_scan_size,
|
|
822
|
+
queue_scan_size,
|
|
823
|
+
logger,
|
|
824
|
+
instrumenter,
|
|
825
|
+
instrument,
|
|
826
|
+
log_sampling_enabled,
|
|
827
|
+
log_sampling_percent,
|
|
828
|
+
log_sampler,
|
|
829
|
+
log_sample_this,
|
|
830
|
+
instr_sampling_enabled,
|
|
831
|
+
instr_sampling_percent,
|
|
832
|
+
instr_sampler,
|
|
833
|
+
instr_sample_this
|
|
834
|
+
)
|
|
835
|
+
end
|
|
836
|
+
alias_method :release_locks_of, :clear_locks_of
|
|
837
|
+
|
|
838
|
+
# Release all locks of the current acquirer/host and
|
|
839
|
+
# remove the current acquirer/host from all queues;
|
|
840
|
+
#
|
|
841
|
+
# @option batch_size [Integer]
|
|
842
|
+
# @option logger [::Logger,#debug]
|
|
843
|
+
# @option instrumenter [#notify] See `config['instrumenter']` docs for details.
|
|
844
|
+
# @option instrument [NilClass,Any]
|
|
845
|
+
# @option log_sampling_enabled [Boolean]
|
|
846
|
+
# @option log_sampling_percent [Integer]
|
|
847
|
+
# @option log_sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
|
|
848
|
+
# @option log_sample_this [Boolean]
|
|
849
|
+
# @option instr_sampling_enabled [Boolean]
|
|
850
|
+
# @option instr_sampling_percent [Integer]
|
|
851
|
+
# @option instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
|
|
852
|
+
# @option instr_sample_this [Boolean]
|
|
853
|
+
# @return [Hash<Symbol,Boolean|Hash<Symbol,Numeric>>]
|
|
854
|
+
# Example: { ok: true, result: { rel_key_cnt: 100, tch_queue_cnt: 2, rel_time: 0.01 } }
|
|
855
|
+
#
|
|
856
|
+
# @see #clear_locks_of
|
|
857
|
+
#
|
|
858
|
+
# @api public
|
|
859
|
+
# @since 1.14.0
|
|
860
|
+
def clear_current_locks(
|
|
861
|
+
lock_scan_size: config['clear_locks_of__lock_scan_size'], # steep:ignore
|
|
862
|
+
queue_scan_size: config['clear_locks_of__queue_scan_size'], # steep:ingore
|
|
863
|
+
logger: config['logger'], # steep:ignore
|
|
864
|
+
instrumenter: config['instrumenter'], # steep:ignore
|
|
865
|
+
instrument: nil,
|
|
866
|
+
log_sampling_enabled: config['log_sampling_enabled'], # steep:ignore
|
|
867
|
+
log_sampling_percent: config['log_sampling_percent'], # steep:ignore
|
|
868
|
+
log_sampler: config['log_sampler'], # steep:ignore
|
|
869
|
+
log_sample_this: false,
|
|
870
|
+
instr_sampling_enabled: config['instr_sampling_enabled'], # steep:ignore
|
|
871
|
+
instr_sampling_percent: config['instr_sampling_percent'], # steep:ignore
|
|
872
|
+
instr_sampler: config['instr_sampler'], # steep:ignore
|
|
873
|
+
instr_sample_this: false
|
|
874
|
+
)
|
|
875
|
+
clear_locks_of(
|
|
876
|
+
host_id: current_host_id,
|
|
877
|
+
acquirer_id: current_acquirer_id,
|
|
878
|
+
lock_scan_size:,
|
|
879
|
+
queue_scan_size:,
|
|
880
|
+
logger:,
|
|
881
|
+
instrumenter:,
|
|
882
|
+
instrument:,
|
|
883
|
+
log_sampling_enabled:,
|
|
884
|
+
log_sampling_percent:,
|
|
885
|
+
log_sampler:,
|
|
886
|
+
log_sample_this:,
|
|
887
|
+
instr_sampling_enabled:,
|
|
888
|
+
instr_sampling_percent:,
|
|
889
|
+
instr_sampler:,
|
|
890
|
+
instr_sample_this:
|
|
891
|
+
)
|
|
892
|
+
end
|
|
893
|
+
alias_method :release_current_locks, :clear_current_locks
|
|
894
|
+
|
|
742
895
|
# @option scan_size [Integer]
|
|
743
896
|
# The batch of scanned keys for Redis'es SCAN command.
|
|
744
897
|
# @option with_info [Boolean]
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# @api private
|
|
4
|
-
# @since
|
|
4
|
+
# @since 1.13.0
|
|
5
5
|
module RedisQueuedLocks::Config::DSL
|
|
6
6
|
# @api private
|
|
7
|
-
# @since
|
|
7
|
+
# @since 1.13.0
|
|
8
8
|
module ClassMethods
|
|
9
9
|
# NOTE:
|
|
10
10
|
# 1. Style/DefWithParentheses rubocop's cop incorrectly drops `()` from method definition
|
|
@@ -15,7 +15,7 @@ module RedisQueuedLocks::Config::DSL
|
|
|
15
15
|
# @return [Hash<String,Block>]
|
|
16
16
|
#
|
|
17
17
|
# @api private
|
|
18
|
-
# @since
|
|
18
|
+
# @since 1.13.0
|
|
19
19
|
def config_setters()= @config_setters # rubocop:disable Style/DefWithParentheses
|
|
20
20
|
|
|
21
21
|
# NOTE:
|
|
@@ -27,7 +27,7 @@ module RedisQueuedLocks::Config::DSL
|
|
|
27
27
|
# @return [Hash<String,Block>]
|
|
28
28
|
#
|
|
29
29
|
# @api private
|
|
30
|
-
# @since
|
|
30
|
+
# @since 1.13.0
|
|
31
31
|
def config_validators()= @config_validators # rubocop:disable Style/DefWithParentheses
|
|
32
32
|
|
|
33
33
|
# @param config_key [String]
|
|
@@ -35,7 +35,7 @@ module RedisQueuedLocks::Config::DSL
|
|
|
35
35
|
# @return [Bool]
|
|
36
36
|
#
|
|
37
37
|
# @api private
|
|
38
|
-
# @since
|
|
38
|
+
# @since 1.13.0
|
|
39
39
|
def validate(config_key, &validator)
|
|
40
40
|
config_validators[config_key] = validator
|
|
41
41
|
end
|
|
@@ -45,7 +45,7 @@ module RedisQueuedLocks::Config::DSL
|
|
|
45
45
|
# @return [void]
|
|
46
46
|
#
|
|
47
47
|
# @api private
|
|
48
|
-
# @since
|
|
48
|
+
# @since 1.13.0
|
|
49
49
|
def setting(config_key, config_value)
|
|
50
50
|
config_setters[config_key] = proc do |config|
|
|
51
51
|
config[config_key] = config_value
|
|
@@ -57,7 +57,7 @@ module RedisQueuedLocks::Config::DSL
|
|
|
57
57
|
# @return [Hash<String,Blcok>]
|
|
58
58
|
#
|
|
59
59
|
# @api private
|
|
60
|
-
# @since
|
|
60
|
+
# @since 1.13.0
|
|
61
61
|
def config_setters
|
|
62
62
|
self.class.config_setters # steep:ignore
|
|
63
63
|
end
|
|
@@ -65,7 +65,7 @@ module RedisQueuedLocks::Config::DSL
|
|
|
65
65
|
# @return [Hash<String,Blcok>]
|
|
66
66
|
#
|
|
67
67
|
# @api private
|
|
68
|
-
# @since
|
|
68
|
+
# @since 1.13.0
|
|
69
69
|
def config_validators
|
|
70
70
|
self.class.config_validators # steep:ignore
|
|
71
71
|
end
|
|
@@ -76,7 +76,7 @@ module RedisQueuedLocks::Config::DSL
|
|
|
76
76
|
# @return [void]
|
|
77
77
|
#
|
|
78
78
|
# @api private
|
|
79
|
-
# @since
|
|
79
|
+
# @since 1.13.0
|
|
80
80
|
def included(child_klass)
|
|
81
81
|
child_klass.instance_variable_set(
|
|
82
82
|
:@config_setters,
|