redis_queued_locks 1.4.0 → 1.6.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/CHANGELOG.md +10 -0
- data/README.md +178 -10
- data/lib/redis_queued_locks/acquier/acquire_lock/try_to_lock.rb +34 -19
- data/lib/redis_queued_locks/acquier/acquire_lock/yield_expire.rb +10 -2
- data/lib/redis_queued_locks/acquier/acquire_lock.rb +72 -14
- data/lib/redis_queued_locks/acquier/clear_dead_requests.rb +21 -1
- data/lib/redis_queued_locks/acquier/extend_lock_ttl.rb +23 -1
- data/lib/redis_queued_locks/acquier/release_all_locks.rb +57 -4
- data/lib/redis_queued_locks/acquier/release_lock.rb +57 -3
- data/lib/redis_queued_locks/client.rb +186 -18
- data/lib/redis_queued_locks/instrument/sampler.rb +27 -0
- data/lib/redis_queued_locks/instrument.rb +47 -0
- data/lib/redis_queued_locks/logging/sampler.rb +28 -0
- data/lib/redis_queued_locks/logging.rb +47 -0
- data/lib/redis_queued_locks/utilities.rb +1 -0
- data/lib/redis_queued_locks/version.rb +2 -2
- metadata +5 -3
@@ -86,6 +86,41 @@ module RedisQueuedLocks::Acquier::AcquireLock
|
|
86
86
|
# - `:extendable_work_through`;
|
87
87
|
# - `:wait_for_lock`;
|
88
88
|
# - `:dead_locking`;
|
89
|
+
# @option log_sampling_enabled [Boolean]
|
90
|
+
# - enables <log sampling>: only the configured percent of RQL cases will be logged;
|
91
|
+
# - disabled by default;
|
92
|
+
# - works in tandem with <config.log_sampling_percent and <log.sampler>;
|
93
|
+
# @option log_sampling_percent [Integer]
|
94
|
+
# - the percent of cases that should be logged;
|
95
|
+
# - take an effect when <config.log_sampling_enalbed> is true;
|
96
|
+
# - works in tandem with <config.log_sampling_enabled> and <config.log_sampler> configs;
|
97
|
+
# @option log_sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
|
98
|
+
# - percent-based log sampler that decides should be RQL case logged or not;
|
99
|
+
# - works in tandem with <config.log_sampling_enabled> and
|
100
|
+
# <config.log_sampling_percent> configs;
|
101
|
+
# - based on the ultra simple percent-based (weight-based) algorithm that uses
|
102
|
+
# SecureRandom.rand method so the algorithm error is ~(0%..13%);
|
103
|
+
# - you can provide your own log sampler with bettter algorithm that should realize
|
104
|
+
# `sampling_happened?(percent) => boolean` interface
|
105
|
+
# (see `RedisQueuedLocks::Logging::Sampler` for example);
|
106
|
+
# @option instr_sampling_enabled [Boolean]
|
107
|
+
# - enables <instrumentaion sampling>: only the configured percent
|
108
|
+
# of RQL cases will be instrumented;
|
109
|
+
# - disabled by default;
|
110
|
+
# - works in tandem with <config.instr_sampling_percent and <log.instr_sampler>;
|
111
|
+
# @option instr_sampling_percent [Integer]
|
112
|
+
# - the percent of cases that should be instrumented;
|
113
|
+
# - take an effect when <config.instr_sampling_enalbed> is true;
|
114
|
+
# - works in tandem with <config.instr_sampling_enabled> and <config.instr_sampler> configs;
|
115
|
+
# @option instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
|
116
|
+
# - percent-based log sampler that decides should be RQL case instrumented or not;
|
117
|
+
# - works in tandem with <config.instr_sampling_enabled> and
|
118
|
+
# <config.instr_sampling_percent> configs;
|
119
|
+
# - based on the ultra simple percent-based (weight-based) algorithm that uses
|
120
|
+
# SecureRandom.rand method so the algorithm error is ~(0%..13%);
|
121
|
+
# - you can provide your own log sampler with bettter algorithm that should realize
|
122
|
+
# `sampling_happened?(percent) => boolean` interface
|
123
|
+
# (see `RedisQueuedLocks::Instrument::Sampler` for example);
|
89
124
|
# @param [Block]
|
90
125
|
# A block of code that should be executed after the successfully acquired lock.
|
91
126
|
# @return [RedisQueuedLocks::Data,Hash<Symbol,Any>,yield]
|
@@ -94,7 +129,7 @@ module RedisQueuedLocks::Acquier::AcquireLock
|
|
94
129
|
#
|
95
130
|
# @api private
|
96
131
|
# @since 1.0.0
|
97
|
-
# @version 1.
|
132
|
+
# @version 1.6.0
|
98
133
|
def acquire_lock(
|
99
134
|
redis,
|
100
135
|
lock_name,
|
@@ -118,6 +153,12 @@ module RedisQueuedLocks::Acquier::AcquireLock
|
|
118
153
|
logger:,
|
119
154
|
log_lock_try:,
|
120
155
|
conflict_strategy:,
|
156
|
+
log_sampling_enabled:,
|
157
|
+
log_sampling_percent:,
|
158
|
+
log_sampler:,
|
159
|
+
instr_sampling_enabled:,
|
160
|
+
instr_sampling_percent:,
|
161
|
+
instr_sampler:,
|
121
162
|
&block
|
122
163
|
)
|
123
164
|
# Step 0: Prevent argument type incompatabilities
|
@@ -165,6 +206,17 @@ module RedisQueuedLocks::Acquier::AcquireLock
|
|
165
206
|
lock_key_queue = RedisQueuedLocks::Resource.prepare_lock_queue(lock_name)
|
166
207
|
acquier_position = RedisQueuedLocks::Resource.calc_initial_acquier_position
|
167
208
|
|
209
|
+
log_sampled = RedisQueuedLocks::Logging.should_log?(
|
210
|
+
log_sampling_enabled,
|
211
|
+
log_sampling_percent,
|
212
|
+
log_sampler
|
213
|
+
)
|
214
|
+
instr_sampled = RedisQueuedLocks::Instrument.should_instrument?(
|
215
|
+
instr_sampling_enabled,
|
216
|
+
instr_sampling_percent,
|
217
|
+
instr_sampler
|
218
|
+
)
|
219
|
+
|
168
220
|
# Step X: intermediate result observer
|
169
221
|
acq_process = {
|
170
222
|
lock_info: {},
|
@@ -183,7 +235,9 @@ module RedisQueuedLocks::Acquier::AcquireLock
|
|
183
235
|
lock_key,
|
184
236
|
lock_key_queue,
|
185
237
|
queue_ttl,
|
186
|
-
acquier_id
|
238
|
+
acquier_id,
|
239
|
+
log_sampled,
|
240
|
+
instr_sampled
|
187
241
|
)
|
188
242
|
end
|
189
243
|
|
@@ -194,7 +248,7 @@ module RedisQueuedLocks::Acquier::AcquireLock
|
|
194
248
|
"queue_ttl => #{queue_ttl} " \
|
195
249
|
"acq_id => '#{acquier_id}'"
|
196
250
|
end
|
197
|
-
end
|
251
|
+
end if log_sampled
|
198
252
|
|
199
253
|
# Step 2: try to lock with timeout
|
200
254
|
with_acq_timeout(timeout, lock_key, raise_errors, on_timeout: acq_dequeue) do
|
@@ -209,7 +263,7 @@ module RedisQueuedLocks::Acquier::AcquireLock
|
|
209
263
|
"queue_ttl => #{queue_ttl} " \
|
210
264
|
"acq_id => '{#{acquier_id}'"
|
211
265
|
end
|
212
|
-
end
|
266
|
+
end if log_sampled
|
213
267
|
|
214
268
|
# Step 2.X: check the actual score: is it in queue ttl limit or not?
|
215
269
|
if RedisQueuedLocks::Resource.dead_score_reached?(acquier_position, queue_ttl)
|
@@ -223,7 +277,7 @@ module RedisQueuedLocks::Acquier::AcquireLock
|
|
223
277
|
"queue_ttl => #{queue_ttl} " \
|
224
278
|
"acq_id => '#{acquier_id}'"
|
225
279
|
end
|
226
|
-
end
|
280
|
+
end if log_sampled
|
227
281
|
end
|
228
282
|
|
229
283
|
try_to_lock(
|
@@ -238,7 +292,9 @@ module RedisQueuedLocks::Acquier::AcquireLock
|
|
238
292
|
queue_ttl,
|
239
293
|
fail_fast,
|
240
294
|
conflict_strategy,
|
241
|
-
meta
|
295
|
+
meta,
|
296
|
+
log_sampled,
|
297
|
+
instr_sampled
|
242
298
|
) => { ok:, result: }
|
243
299
|
|
244
300
|
acq_end_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC, :microsecond)
|
@@ -261,7 +317,7 @@ module RedisQueuedLocks::Acquier::AcquireLock
|
|
261
317
|
"acq_id => '#{acquier_id}' " \
|
262
318
|
"acq_time => #{acq_time} (ms)"
|
263
319
|
end
|
264
|
-
end
|
320
|
+
end if log_sampled
|
265
321
|
|
266
322
|
run_non_critical do
|
267
323
|
instrumenter.notify('redis_queued_locks.extendable_reentrant_lock_obtained', {
|
@@ -272,7 +328,7 @@ module RedisQueuedLocks::Acquier::AcquireLock
|
|
272
328
|
acq_time: acq_time,
|
273
329
|
instrument:
|
274
330
|
})
|
275
|
-
end
|
331
|
+
end if instr_sampled
|
276
332
|
elsif acq_process[:result][:process] == :conflict_work_through
|
277
333
|
# instrumetnation: (reentrant lock without ttl extension)
|
278
334
|
run_non_critical do
|
@@ -283,7 +339,7 @@ module RedisQueuedLocks::Acquier::AcquireLock
|
|
283
339
|
"acq_id => '#{acquier_id}' " \
|
284
340
|
"acq_time => #{acq_time} (ms)"
|
285
341
|
end
|
286
|
-
end
|
342
|
+
end if log_sampled
|
287
343
|
|
288
344
|
run_non_critical do
|
289
345
|
instrumenter.notify('redis_queued_locks.reentrant_lock_obtained', {
|
@@ -294,7 +350,7 @@ module RedisQueuedLocks::Acquier::AcquireLock
|
|
294
350
|
acq_time: acq_time,
|
295
351
|
instrument:
|
296
352
|
})
|
297
|
-
end
|
353
|
+
end if instr_sampled
|
298
354
|
else
|
299
355
|
# instrumentation: (classic lock obtain)
|
300
356
|
# NOTE: classic is: acq_process[:result][:process] == :lock_obtaining
|
@@ -306,7 +362,7 @@ module RedisQueuedLocks::Acquier::AcquireLock
|
|
306
362
|
"acq_id => '#{acquier_id}' " \
|
307
363
|
"acq_time => #{acq_time} (ms)"
|
308
364
|
end
|
309
|
-
end
|
365
|
+
end if log_sampled
|
310
366
|
|
311
367
|
# Step X (instrumentation): lock obtained
|
312
368
|
run_non_critical do
|
@@ -318,7 +374,7 @@ module RedisQueuedLocks::Acquier::AcquireLock
|
|
318
374
|
acq_time: acq_time,
|
319
375
|
instrument:
|
320
376
|
})
|
321
|
-
end
|
377
|
+
end if instr_sampled
|
322
378
|
end
|
323
379
|
|
324
380
|
# Step 2.1.a: successfully acquired => build the result
|
@@ -426,6 +482,8 @@ module RedisQueuedLocks::Acquier::AcquireLock
|
|
426
482
|
ttl_shift,
|
427
483
|
ttl,
|
428
484
|
queue_ttl,
|
485
|
+
log_sampled,
|
486
|
+
instr_sampled,
|
429
487
|
should_expire, # NOTE: should expire the lock after the block execution
|
430
488
|
should_decrease, # NOTE: should decrease the lock ttl in reentrant locks?
|
431
489
|
&block
|
@@ -451,7 +509,7 @@ module RedisQueuedLocks::Acquier::AcquireLock
|
|
451
509
|
acq_time: acq_process[:acq_time],
|
452
510
|
instrument:
|
453
511
|
})
|
454
|
-
end
|
512
|
+
end if instr_sampled
|
455
513
|
else
|
456
514
|
# Step X (instrumentation): lock_hold_and_release
|
457
515
|
run_non_critical do
|
@@ -464,7 +522,7 @@ module RedisQueuedLocks::Acquier::AcquireLock
|
|
464
522
|
acq_time: acq_process[:acq_time],
|
465
523
|
instrument:
|
466
524
|
})
|
467
|
-
end
|
525
|
+
end if instr_sampled
|
468
526
|
end
|
469
527
|
end
|
470
528
|
else
|
@@ -10,11 +10,31 @@ module RedisQueuedLocks::Acquier::ClearDeadRequests
|
|
10
10
|
# @param logger [::Logger,#debug]
|
11
11
|
# @param instrumenter [#notify]
|
12
12
|
# @param instrument [NilClass,Any]
|
13
|
+
# @param log_sampling_enabled [Boolean]
|
14
|
+
# @param log_sampling_percent [Integer]
|
15
|
+
# @param log_sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
|
16
|
+
# @param instr_sampling_enabled [Boolean]
|
17
|
+
# @param instr_sampling_percent [Integer]
|
18
|
+
# @param instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
|
13
19
|
# @return [Hash<Symbol,Boolean|Hash<Symbol,Set<String>>>]
|
14
20
|
#
|
15
21
|
# @api private
|
16
22
|
# @since 1.0.0
|
17
|
-
|
23
|
+
# @version 1.6.0
|
24
|
+
def clear_dead_requests(
|
25
|
+
redis_client,
|
26
|
+
scan_size,
|
27
|
+
dead_ttl,
|
28
|
+
logger,
|
29
|
+
instrumenter,
|
30
|
+
instrument,
|
31
|
+
log_sampling_enabled,
|
32
|
+
log_sampling_percent,
|
33
|
+
log_sampler,
|
34
|
+
instr_sampling_enabled,
|
35
|
+
instr_sampling_percent,
|
36
|
+
instr_sampler
|
37
|
+
)
|
18
38
|
dead_score = RedisQueuedLocks::Resource.acquier_dead_score(dead_ttl / 1_000.0)
|
19
39
|
|
20
40
|
result = Set.new.tap do |processed_queues|
|
@@ -17,11 +17,33 @@ module RedisQueuedLocks::Acquier::ExtendLockTTL
|
|
17
17
|
# @param lock_name [String]
|
18
18
|
# @param milliseconds [Integer]
|
19
19
|
# @param logger [::Logger,#debug]
|
20
|
+
# @param instrumenter [#notify]
|
21
|
+
# @param instrument [NilClass,Any]
|
22
|
+
# @param log_sampling_enabled [Boolean]
|
23
|
+
# @param log_sampling_percent [Integer]
|
24
|
+
# @param log_sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
|
25
|
+
# @param instr_sampling_enabled [Boolean]
|
26
|
+
# @param instr_sampling_percent [Integer]
|
27
|
+
# @param instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
|
20
28
|
# @return [Hash<Symbol,Boolean|Symbol>]
|
21
29
|
#
|
22
30
|
# @api private
|
23
31
|
# @since 1.0.0
|
24
|
-
|
32
|
+
# @version 1.6.0
|
33
|
+
def extend_lock_ttl(
|
34
|
+
redis_client,
|
35
|
+
lock_name,
|
36
|
+
milliseconds,
|
37
|
+
logger,
|
38
|
+
instrumenter,
|
39
|
+
instrument,
|
40
|
+
log_sampling_enabled,
|
41
|
+
log_sampling_percent,
|
42
|
+
log_sampler,
|
43
|
+
instr_sampling_enabled,
|
44
|
+
instr_sampling_percent,
|
45
|
+
instr_sampler
|
46
|
+
)
|
25
47
|
lock_key = RedisQueuedLocks::Resource.prepare_lock_key(lock_name)
|
26
48
|
|
27
49
|
# NOTE: EVAL signature -> <lua script>, (number of keys), *(keys), *(arguments)
|
@@ -20,29 +20,82 @@ module RedisQueuedLocks::Acquier::ReleaseAllLocks
|
|
20
20
|
# - See RedisQueuedLocks::Logging::VoidLogger for example;
|
21
21
|
# @param isntrumenter [#notify]
|
22
22
|
# See RedisQueuedLocks::Instrument::ActiveSupport for example.
|
23
|
-
# @
|
23
|
+
# @param instrument [NilClass,Any]
|
24
24
|
# - Custom instrumentation data wich will be passed to the instrumenter's payload
|
25
25
|
# with :instrument key;
|
26
|
+
# @param log_sampling_enabled [Boolean]
|
27
|
+
# - enables <log sampling>: only the configured percent of RQL cases will be logged;
|
28
|
+
# - disabled by default;
|
29
|
+
# - works in tandem with <config.log_sampling_percent and <log.sampler>;
|
30
|
+
# @param log_sampling_percent [Integer]
|
31
|
+
# - the percent of cases that should be logged;
|
32
|
+
# - take an effect when <config.log_sampling_enalbed> is true;
|
33
|
+
# - works in tandem with <config.log_sampling_enabled> and <config.log_sampler> configs;
|
34
|
+
# @param log_sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
|
35
|
+
# - percent-based log sampler that decides should be RQL case logged or not;
|
36
|
+
# - works in tandem with <config.log_sampling_enabled> and
|
37
|
+
# <config.log_sampling_percent> configs;
|
38
|
+
# - based on the ultra simple percent-based (weight-based) algorithm that uses
|
39
|
+
# SecureRandom.rand method so the algorithm error is ~(0%..13%);
|
40
|
+
# - you can provide your own log sampler with bettter algorithm that should realize
|
41
|
+
# `sampling_happened?(percent) => boolean` interface
|
42
|
+
# (see `RedisQueuedLocks::Logging::Sampler` for example);
|
43
|
+
# @param instr_sampling_enabled [Boolean]
|
44
|
+
# - enables <instrumentaion sampling>: only the configured percent
|
45
|
+
# of RQL cases will be instrumented;
|
46
|
+
# - disabled by default;
|
47
|
+
# - works in tandem with <config.instr_sampling_percent and <log.instr_sampler>;
|
48
|
+
# @param instr_sampling_percent [Integer]
|
49
|
+
# - the percent of cases that should be instrumented;
|
50
|
+
# - take an effect when <config.instr_sampling_enalbed> is true;
|
51
|
+
# - works in tandem with <config.instr_sampling_enabled> and <config.instr_sampler> configs;
|
52
|
+
# @param instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
|
53
|
+
# - percent-based log sampler that decides should be RQL case instrumented or not;
|
54
|
+
# - works in tandem with <config.instr_sampling_enabled> and
|
55
|
+
# <config.instr_sampling_percent> configs;
|
56
|
+
# - based on the ultra simple percent-based (weight-based) algorithm that uses
|
57
|
+
# SecureRandom.rand method so the algorithm error is ~(0%..13%);
|
58
|
+
# - you can provide your own log sampler with bettter algorithm that should realize
|
59
|
+
# `sampling_happened?(percent) => boolean` interface
|
60
|
+
# (see `RedisQueuedLocks::Instrument::Sampler` for example);
|
26
61
|
# @return [RedisQueuedLocks::Data,Hash<Symbol,Any>]
|
27
62
|
# Format: { ok: true, result: Hash<Symbol,Numeric> }
|
28
63
|
#
|
29
64
|
# @api private
|
30
65
|
# @since 1.0.0
|
31
|
-
# @version 1.
|
32
|
-
def release_all_locks(
|
66
|
+
# @version 1.6.0
|
67
|
+
def release_all_locks(
|
68
|
+
redis,
|
69
|
+
batch_size,
|
70
|
+
logger,
|
71
|
+
instrumenter,
|
72
|
+
instrument,
|
73
|
+
log_sampling_enabled,
|
74
|
+
log_sampling_percent,
|
75
|
+
log_sampler,
|
76
|
+
instr_sampling_enabled,
|
77
|
+
instr_sampling_percent,
|
78
|
+
instr_sampler
|
79
|
+
)
|
33
80
|
rel_start_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC, :microsecond)
|
34
81
|
fully_release_all_locks(redis, batch_size) => { ok:, result: }
|
35
82
|
time_at = Time.now.to_f
|
36
83
|
rel_end_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC, :microsecond)
|
37
84
|
rel_time = ((rel_end_time - rel_start_time) / 1_000).ceil(2)
|
38
85
|
|
86
|
+
instr_sampled = RedisQueuedLocks::Instrument.should_instrument?(
|
87
|
+
instr_sampling_enabled,
|
88
|
+
instr_sampling_percent,
|
89
|
+
instr_sampler
|
90
|
+
)
|
91
|
+
|
39
92
|
run_non_critical do
|
40
93
|
instrumenter.notify('redis_queued_locks.explicit_all_locks_release', {
|
41
94
|
at: time_at,
|
42
95
|
rel_time: rel_time,
|
43
96
|
rel_key_cnt: result[:rel_key_cnt]
|
44
97
|
})
|
45
|
-
end
|
98
|
+
end if instr_sampled
|
46
99
|
|
47
100
|
RedisQueuedLocks::Data[
|
48
101
|
ok: true,
|
@@ -23,13 +23,60 @@ module RedisQueuedLocks::Acquier::ReleaseLock
|
|
23
23
|
# @param logger [::Logger,#debug]
|
24
24
|
# - Logger object used from `configuration` layer (see config[:logger]);
|
25
25
|
# - See RedisQueuedLocks::Logging::VoidLogger for example;
|
26
|
+
# @param log_sampling_enabled [Boolean]
|
27
|
+
# - enables <log sampling>: only the configured percent of RQL cases will be logged;
|
28
|
+
# - disabled by default;
|
29
|
+
# - works in tandem with <config.log_sampling_percent and <log.sampler>;
|
30
|
+
# @param log_sampling_percent [Integer]
|
31
|
+
# - the percent of cases that should be logged;
|
32
|
+
# - take an effect when <config.log_sampling_enalbed> is true;
|
33
|
+
# - works in tandem with <config.log_sampling_enabled> and <config.log_sampler> configs;
|
34
|
+
# @param log_sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
|
35
|
+
# - percent-based log sampler that decides should be RQL case logged or not;
|
36
|
+
# - works in tandem with <config.log_sampling_enabled> and
|
37
|
+
# <config.log_sampling_percent> configs;
|
38
|
+
# - based on the ultra simple percent-based (weight-based) algorithm that uses
|
39
|
+
# SecureRandom.rand method so the algorithm error is ~(0%..13%);
|
40
|
+
# - you can provide your own log sampler with bettter algorithm that should realize
|
41
|
+
# `sampling_happened?(percent) => boolean` interface
|
42
|
+
# (see `RedisQueuedLocks::Logging::Sampler` for example);
|
43
|
+
# @param instr_sampling_enabled [Boolean]
|
44
|
+
# - enables <instrumentaion sampling>: only the configured percent
|
45
|
+
# of RQL cases will be instrumented;
|
46
|
+
# - disabled by default;
|
47
|
+
# - works in tandem with <config.instr_sampling_percent and <log.instr_sampler>;
|
48
|
+
# @param instr_sampling_percent [Integer]
|
49
|
+
# - the percent of cases that should be instrumented;
|
50
|
+
# - take an effect when <config.instr_sampling_enalbed> is true;
|
51
|
+
# - works in tandem with <config.instr_sampling_enabled> and <config.instr_sampler> configs;
|
52
|
+
# @param instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
|
53
|
+
# - percent-based log sampler that decides should be RQL case instrumented or not;
|
54
|
+
# - works in tandem with <config.instr_sampling_enabled> and
|
55
|
+
# <config.instr_sampling_percent> configs;
|
56
|
+
# - based on the ultra simple percent-based (weight-based) algorithm that uses
|
57
|
+
# SecureRandom.rand method so the algorithm error is ~(0%..13%);
|
58
|
+
# - you can provide your own log sampler with bettter algorithm that should realize
|
59
|
+
# `sampling_happened?(percent) => boolean` interface
|
60
|
+
# (see `RedisQueuedLocks::Instrument::Sampler` for example);
|
26
61
|
# @return [RedisQueuedLocks::Data,Hash<Symbol,Boolean<Hash<Symbol,Numeric|String|Symbol>>]
|
27
62
|
# Format: { ok: true/false, result: Hash<Symbol,Numeric|String|Symbol> }
|
28
63
|
#
|
29
64
|
# @api private
|
30
65
|
# @since 1.0.0
|
31
|
-
# @version 1.
|
32
|
-
|
66
|
+
# @version 1.6.0
|
67
|
+
# rubocop:disable Metrics/MethodLength
|
68
|
+
def release_lock(
|
69
|
+
redis,
|
70
|
+
lock_name,
|
71
|
+
instrumenter,
|
72
|
+
logger,
|
73
|
+
log_sampling_enabled,
|
74
|
+
log_sampling_percent,
|
75
|
+
log_sampler,
|
76
|
+
instr_sampling_enabled,
|
77
|
+
instr_sampling_percent,
|
78
|
+
instr_sampler
|
79
|
+
)
|
33
80
|
lock_key = RedisQueuedLocks::Resource.prepare_lock_key(lock_name)
|
34
81
|
lock_key_queue = RedisQueuedLocks::Resource.prepare_lock_queue(lock_name)
|
35
82
|
|
@@ -39,6 +86,12 @@ module RedisQueuedLocks::Acquier::ReleaseLock
|
|
39
86
|
rel_end_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC, :microsecond)
|
40
87
|
rel_time = ((rel_end_time - rel_start_time) / 1_000).ceil(2)
|
41
88
|
|
89
|
+
instr_sampled = RedisQueuedLocks::Instrument.should_instrument?(
|
90
|
+
instr_sampling_enabled,
|
91
|
+
instr_sampling_percent,
|
92
|
+
instr_sampler
|
93
|
+
)
|
94
|
+
|
42
95
|
run_non_critical do
|
43
96
|
instrumenter.notify('redis_queued_locks.explicit_lock_release', {
|
44
97
|
lock_key: lock_key,
|
@@ -46,7 +99,7 @@ module RedisQueuedLocks::Acquier::ReleaseLock
|
|
46
99
|
rel_time: rel_time,
|
47
100
|
at: time_at
|
48
101
|
})
|
49
|
-
end
|
102
|
+
end if instr_sampled
|
50
103
|
|
51
104
|
RedisQueuedLocks::Data[
|
52
105
|
ok: true,
|
@@ -59,6 +112,7 @@ module RedisQueuedLocks::Acquier::ReleaseLock
|
|
59
112
|
}
|
60
113
|
]
|
61
114
|
end
|
115
|
+
# rubocop:enable Metrics/MethodLength
|
62
116
|
|
63
117
|
private
|
64
118
|
|