redis_queued_locks 1.4.0 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|