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
@@ -23,6 +23,12 @@ class RedisQueuedLocks::Client
|
|
23
23
|
setting :dead_request_ttl, (1 * 24 * 60 * 60 * 1000) # NOTE: 1 day in milliseconds
|
24
24
|
setting :is_timed_by_default, false
|
25
25
|
setting :default_conflict_strategy, :wait_for_lock
|
26
|
+
setting :log_sampling_enabled, false
|
27
|
+
setting :log_sampling_percent, 15
|
28
|
+
setting :log_sampler, RedisQueuedLocks::Logging::Sampler
|
29
|
+
setting :instr_sampling_enabled, false
|
30
|
+
setting :instr_sampling_percent, 15
|
31
|
+
setting :instr_sampler, RedisQueuedLocks::Instrument::Sampler
|
26
32
|
|
27
33
|
validate('retry_count') { |val| val == nil || (val.is_a?(::Integer) && val >= 0) }
|
28
34
|
validate('retry_delay') { |val| val.is_a?(::Integer) && val >= 0 }
|
@@ -37,6 +43,12 @@ class RedisQueuedLocks::Client
|
|
37
43
|
validate('log_lock_try', :boolean)
|
38
44
|
validate('dead_request_ttl') { |val| val.is_a?(::Integer) && val > 0 }
|
39
45
|
validate('is_timed_by_default', :boolean)
|
46
|
+
validate('log_sampler') { |val| RedisQueuedLocks::Logging.valid_sampler?(val) }
|
47
|
+
validate('log_sampling_enabled', :boolean)
|
48
|
+
validate('log_sampling_percent') { |val| val.is_a?(::Integer) && val >= 0 && val <= 100 }
|
49
|
+
validate('instr_sampling_enabled', :boolean)
|
50
|
+
validate('instr_sampling_percent') { |val| val.is_a?(::Integer) && val >= 0 && val <= 100 }
|
51
|
+
validate('instr_sampler') { |val| RedisQueuedLocks::Instrument.valid_sampler?(val) }
|
40
52
|
validate('default_conflict_strategy') do |val|
|
41
53
|
# rubocop:disable Layout/MultilineOperationIndentation
|
42
54
|
val == :work_through ||
|
@@ -92,8 +104,6 @@ class RedisQueuedLocks::Client
|
|
92
104
|
# A time-interval between the each retry (in milliseconds).
|
93
105
|
# @option retry_jitter [Integer]
|
94
106
|
# Time-shift range for retry-delay (in milliseconds).
|
95
|
-
# @option instrumenter [#notify]
|
96
|
-
# See RedisQueuedLocks::Instrument::ActiveSupport for example.
|
97
107
|
# @option raise_errors [Boolean]
|
98
108
|
# Raise errors on library-related limits such as timeout or failed lock obtain.
|
99
109
|
# @option identity [String]
|
@@ -127,9 +137,50 @@ class RedisQueuedLocks::Client
|
|
127
137
|
# - should be logged the each try of lock acquiring (a lot of logs can
|
128
138
|
# be generated depending on your retry configurations);
|
129
139
|
# - see `config[:log_lock_try]`;
|
140
|
+
# @option instrumenter [#notify]
|
141
|
+
# - Custom instrumenter that will be invoked via #notify method with `event` and `payload` data;
|
142
|
+
# - See RedisQueuedLocks::Instrument::ActiveSupport for examples and implementation details;
|
143
|
+
# - See [Instrumentation](#instrumentation) section of docs;
|
144
|
+
# - pre-configured in `config[:isntrumenter]` with void notifier
|
145
|
+
# (`RedisQueuedLocks::Instrumenter::VoidNotifier`);
|
130
146
|
# @option instrument [NilClass,Any]
|
131
147
|
# - Custom instrumentation data wich will be passed to the instrumenter's payload
|
132
148
|
# with :instrument key;
|
149
|
+
# @option log_sampling_enabled [Boolean]
|
150
|
+
# - enables <log sampling>: only the configured percent of RQL cases will be logged;
|
151
|
+
# - disabled by default;
|
152
|
+
# - works in tandem with <config.log_sampling_percent and <log.sampler>;
|
153
|
+
# @option log_sampling_percent [Integer]
|
154
|
+
# - the percent of cases that should be logged;
|
155
|
+
# - take an effect when <config.log_sampling_enalbed> is true;
|
156
|
+
# - works in tandem with <config.log_sampling_enabled> and <config.log_sampler> configs;
|
157
|
+
# @option log_sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
|
158
|
+
# - percent-based log sampler that decides should be RQL case logged or not;
|
159
|
+
# - works in tandem with <config.log_sampling_enabled> and
|
160
|
+
# <config.log_sampling_percent> configs;
|
161
|
+
# - based on the ultra simple percent-based (weight-based) algorithm that uses SecureRandom.rand
|
162
|
+
# method so the algorithm error is ~(0%..13%);
|
163
|
+
# - you can provide your own log sampler with bettter algorithm that should realize
|
164
|
+
# `sampling_happened?(percent) => boolean` interface
|
165
|
+
# (see `RedisQueuedLocks::Logging::Sampler` for example);
|
166
|
+
# @option instr_sampling_enabled [Boolean]
|
167
|
+
# - enables <instrumentaion sampling>: only the configured percent
|
168
|
+
# of RQL cases will be instrumented;
|
169
|
+
# - disabled by default;
|
170
|
+
# - works in tandem with <config.instr_sampling_percent and <log.instr_sampler>;
|
171
|
+
# @option instr_sampling_percent [Integer]
|
172
|
+
# - the percent of cases that should be instrumented;
|
173
|
+
# - take an effect when <config.instr_sampling_enalbed> is true;
|
174
|
+
# - works in tandem with <config.instr_sampling_enabled> and <config.instr_sampler> configs;
|
175
|
+
# @option instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
|
176
|
+
# - percent-based log sampler that decides should be RQL case instrumented or not;
|
177
|
+
# - works in tandem with <config.instr_sampling_enabled> and
|
178
|
+
# <config.instr_sampling_percent> configs;
|
179
|
+
# - based on the ultra simple percent-based (weight-based) algorithm that uses SecureRandom.rand
|
180
|
+
# method so the algorithm error is ~(0%..13%);
|
181
|
+
# - you can provide your own log sampler with bettter algorithm that should realize
|
182
|
+
# `sampling_happened?(percent) => boolean` interface
|
183
|
+
# (see `RedisQueuedLocks::Instrument::Sampler` for example);
|
133
184
|
# @param block [Block]
|
134
185
|
# A block of code that should be executed after the successfully acquired lock.
|
135
186
|
# @return [RedisQueuedLocks::Data,Hash<Symbol,Any>,yield]
|
@@ -138,7 +189,8 @@ class RedisQueuedLocks::Client
|
|
138
189
|
#
|
139
190
|
# @api public
|
140
191
|
# @since 1.0.0
|
141
|
-
# @version 1.
|
192
|
+
# @version 1.6.0
|
193
|
+
# rubocop:disable Metrics/MethodLength
|
142
194
|
def lock(
|
143
195
|
lock_name,
|
144
196
|
ttl: config[:default_lock_ttl],
|
@@ -155,7 +207,14 @@ class RedisQueuedLocks::Client
|
|
155
207
|
meta: nil,
|
156
208
|
logger: config[:logger],
|
157
209
|
log_lock_try: config[:log_lock_try],
|
210
|
+
instrumenter: config[:instrumenter],
|
158
211
|
instrument: nil,
|
212
|
+
log_sampling_enabled: config[:log_sampling_enabled],
|
213
|
+
log_sampling_percent: config[:log_sampling_percent],
|
214
|
+
log_sampler: config[:log_sampler],
|
215
|
+
instr_sampling_enabled: config[:instr_sampling_enabled],
|
216
|
+
instr_sampling_percent: config[:instr_sampling_percent],
|
217
|
+
instr_sampler: config[:instr_sampler],
|
159
218
|
&block
|
160
219
|
)
|
161
220
|
RedisQueuedLocks::Acquier::AcquireLock.acquire_lock(
|
@@ -173,23 +232,31 @@ class RedisQueuedLocks::Client
|
|
173
232
|
retry_delay:,
|
174
233
|
retry_jitter:,
|
175
234
|
raise_errors:,
|
176
|
-
instrumenter
|
235
|
+
instrumenter:,
|
177
236
|
identity:,
|
178
237
|
fail_fast:,
|
179
238
|
conflict_strategy:,
|
180
239
|
meta:,
|
181
|
-
logger
|
182
|
-
log_lock_try
|
240
|
+
logger:,
|
241
|
+
log_lock_try:,
|
183
242
|
instrument:,
|
243
|
+
log_sampling_enabled:,
|
244
|
+
log_sampling_percent:,
|
245
|
+
log_sampler:,
|
246
|
+
instr_sampling_enabled:,
|
247
|
+
instr_sampling_percent:,
|
248
|
+
instr_sampler:,
|
184
249
|
&block
|
185
250
|
)
|
186
251
|
end
|
252
|
+
# rubocop:enable Metrics/MethodLength
|
187
253
|
|
188
254
|
# @note See #lock method signature.
|
189
255
|
#
|
190
256
|
# @api public
|
191
257
|
# @since 1.0.0
|
192
|
-
# @version 1.
|
258
|
+
# @version 1.6.0
|
259
|
+
# rubocop:disable Metrics/MethodLength
|
193
260
|
def lock!(
|
194
261
|
lock_name,
|
195
262
|
ttl: config[:default_lock_ttl],
|
@@ -202,10 +269,17 @@ class RedisQueuedLocks::Client
|
|
202
269
|
fail_fast: false,
|
203
270
|
conflict_strategy: config[:default_conflict_strategy],
|
204
271
|
identity: uniq_identity,
|
272
|
+
instrumenter: config[:instrumenter],
|
205
273
|
meta: nil,
|
206
274
|
logger: config[:logger],
|
207
275
|
log_lock_try: config[:log_lock_try],
|
208
276
|
instrument: nil,
|
277
|
+
log_sampling_enabled: config[:log_sampling_enabled],
|
278
|
+
log_sampling_percent: config[:log_sampling_percent],
|
279
|
+
log_sampler: config[:log_sampler],
|
280
|
+
instr_sampling_enabled: config[:instr_sampling_enabled],
|
281
|
+
instr_sampling_percent: config[:instr_sampling_percent],
|
282
|
+
instr_sampler: config[:instr_sampler],
|
209
283
|
&block
|
210
284
|
)
|
211
285
|
lock(
|
@@ -224,15 +298,29 @@ class RedisQueuedLocks::Client
|
|
224
298
|
log_lock_try:,
|
225
299
|
meta:,
|
226
300
|
instrument:,
|
301
|
+
instrumenter:,
|
227
302
|
conflict_strategy:,
|
303
|
+
log_sampling_enabled:,
|
304
|
+
log_sampling_percent:,
|
305
|
+
log_sampler:,
|
306
|
+
instr_sampling_enabled:,
|
307
|
+
instr_sampling_percent:,
|
308
|
+
instr_sampler:,
|
228
309
|
&block
|
229
310
|
)
|
230
311
|
end
|
312
|
+
# rubocop:enable Metrics/MethodLength
|
231
313
|
|
232
314
|
# @param lock_name [String] The lock name that should be released.
|
233
315
|
# @option logger [::Logger,#debug]
|
234
316
|
# @option instrumenter [#notify]
|
235
317
|
# @option instrument [NilClass,Any]
|
318
|
+
# @option log_sampling_enabled [Boolean]
|
319
|
+
# @option log_sampling_percent [Integer]
|
320
|
+
# @option log_sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
|
321
|
+
# @option instr_sampling_enabled [Boolean]
|
322
|
+
# @option instr_sampling_percent [Integer]
|
323
|
+
# @option instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
|
236
324
|
# @return [RedisQueuedLocks::Data, Hash<Symbol,Any>]
|
237
325
|
# Format: {
|
238
326
|
# ok: true/false,
|
@@ -247,17 +335,30 @@ class RedisQueuedLocks::Client
|
|
247
335
|
#
|
248
336
|
# @api public
|
249
337
|
# @since 1.0.0
|
338
|
+
# @version 1.6.0
|
250
339
|
def unlock(
|
251
340
|
lock_name,
|
252
341
|
logger: config[:logger],
|
253
342
|
instrumenter: config[:instrumenter],
|
254
|
-
instrument: nil
|
343
|
+
instrument: nil,
|
344
|
+
log_sampling_enabled: config[:log_sampling_enabled],
|
345
|
+
log_sampling_percent: config[:log_sampling_percent],
|
346
|
+
log_sampler: config[:log_sampler],
|
347
|
+
instr_sampling_enabled: config[:instr_sampling_enabled],
|
348
|
+
instr_sampling_percent: config[:instr_sampling_percent],
|
349
|
+
instr_sampler: config[:instr_sampler]
|
255
350
|
)
|
256
351
|
RedisQueuedLocks::Acquier::ReleaseLock.release_lock(
|
257
352
|
redis_client,
|
258
353
|
lock_name,
|
259
|
-
|
260
|
-
|
354
|
+
instrumenter,
|
355
|
+
logger,
|
356
|
+
log_sampling_enabled,
|
357
|
+
log_sampling_percent,
|
358
|
+
log_sampler,
|
359
|
+
instr_sampling_enabled,
|
360
|
+
instr_sampling_percent,
|
361
|
+
instr_sampler
|
261
362
|
)
|
262
363
|
end
|
263
364
|
|
@@ -310,18 +411,48 @@ class RedisQueuedLocks::Client
|
|
310
411
|
#
|
311
412
|
# @param lock_name [String]
|
312
413
|
# @param milliseconds [Integer] How many milliseconds should be added.
|
414
|
+
# @option logger [::Logger,#debug]
|
415
|
+
# @option instrumenter [#notify] See `config[:instrumenter]` docs for details.
|
416
|
+
# @option instrument [NilClass,Any]
|
417
|
+
# @option log_sampling_enabled [Boolean]
|
418
|
+
# @option log_sampling_percent [Integer]
|
419
|
+
# @option log_sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
|
420
|
+
# @option instr_sampling_enabled [Boolean]
|
421
|
+
# @option instr_sampling_percent [Integer]
|
422
|
+
# @option instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
|
313
423
|
# @return [Hash<Symbol,Boolean|Symbol>]
|
314
424
|
# - { ok: true, result: :ttl_extended }
|
315
425
|
# - { ok: false, result: :async_expire_or_no_lock }
|
316
426
|
#
|
317
427
|
# @api public
|
318
428
|
# @since 1.0.0
|
319
|
-
|
429
|
+
# @version 1.6.0
|
430
|
+
def extend_lock_ttl(
|
431
|
+
lock_name,
|
432
|
+
milliseconds,
|
433
|
+
logger: config[:logger],
|
434
|
+
instrumenter: config[:instrumenter],
|
435
|
+
instrument: nil,
|
436
|
+
log_sampling_enabled: config[:log_sampling_enabled],
|
437
|
+
log_sampling_percent: config[:log_sampling_percent],
|
438
|
+
log_sampler: config[:log_sampler],
|
439
|
+
instr_sampling_enabled: config[:instr_sampling_enabled],
|
440
|
+
instr_sampling_percent: config[:instr_sampling_percent],
|
441
|
+
instr_sampler: config[:instr_sampler]
|
442
|
+
)
|
320
443
|
RedisQueuedLocks::Acquier::ExtendLockTTL.extend_lock_ttl(
|
321
444
|
redis_client,
|
322
445
|
lock_name,
|
323
446
|
milliseconds,
|
324
|
-
logger
|
447
|
+
logger,
|
448
|
+
instrumenter,
|
449
|
+
instrument,
|
450
|
+
log_sampling_enabled,
|
451
|
+
log_sampling_percent,
|
452
|
+
log_sampler,
|
453
|
+
instr_sampling_enabled,
|
454
|
+
instr_sampling_percent,
|
455
|
+
instr_sampler
|
325
456
|
)
|
326
457
|
end
|
327
458
|
|
@@ -332,25 +463,44 @@ class RedisQueuedLocks::Client
|
|
332
463
|
#
|
333
464
|
# @option batch_size [Integer]
|
334
465
|
# @option logger [::Logger,#debug]
|
335
|
-
# @option instrumenter [#notify]
|
466
|
+
# @option instrumenter [#notify] See `config[:instrumenter]` docs for details.
|
336
467
|
# @option instrument [NilClass,Any]
|
468
|
+
# @option log_sampling_enabled [Boolean]
|
469
|
+
# @option log_sampling_percent [Integer]
|
470
|
+
# @option log_sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
|
471
|
+
# @option instr_sampling_enabled [Boolean]
|
472
|
+
# @option instr_sampling_percent [Integer]
|
473
|
+
# @option instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
|
337
474
|
# @return [RedisQueuedLocks::Data,Hash<Symbol,Boolean|Hash<Symbol,Numeric>>]
|
338
475
|
# Example: { ok: true, result { rel_key_cnt: 100, rel_time: 0.01 } }
|
339
476
|
#
|
340
477
|
# @api public
|
341
478
|
# @since 1.0.0
|
479
|
+
# @version 1.6.0
|
342
480
|
def clear_locks(
|
343
481
|
batch_size: config[:lock_release_batch_size],
|
344
482
|
logger: config[:logger],
|
345
483
|
instrumenter: config[:instrumenter],
|
346
|
-
instrument: nil
|
484
|
+
instrument: nil,
|
485
|
+
log_sampling_enabled: config[:log_sampling_enabled],
|
486
|
+
log_sampling_percent: config[:log_sampling_percent],
|
487
|
+
log_sampler: config[:log_sampler],
|
488
|
+
instr_sampling_enabled: config[:instr_sampling_enabled],
|
489
|
+
instr_sampling_percent: config[:instr_sampling_percent],
|
490
|
+
instr_sampler: config[:instr_sampler]
|
347
491
|
)
|
348
492
|
RedisQueuedLocks::Acquier::ReleaseAllLocks.release_all_locks(
|
349
493
|
redis_client,
|
350
494
|
batch_size,
|
351
495
|
logger,
|
352
496
|
instrumenter,
|
353
|
-
instrument
|
497
|
+
instrument,
|
498
|
+
log_sampling_enabled,
|
499
|
+
log_sampling_percent,
|
500
|
+
log_sampler,
|
501
|
+
instr_sampling_enabled,
|
502
|
+
instr_sampling_percent,
|
503
|
+
instr_sampler
|
354
504
|
)
|
355
505
|
end
|
356
506
|
|
@@ -438,18 +588,30 @@ class RedisQueuedLocks::Client
|
|
438
588
|
# @option logger [::Logger,#debug]
|
439
589
|
# @option instrumenter [#notify]
|
440
590
|
# @option instrument [NilClass,Any]
|
591
|
+
# @option log_sampling_enabled [Boolean]
|
592
|
+
# @option log_sampling_percent [Integer]
|
593
|
+
# @option log_sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
|
594
|
+
# @option instr_sampling_enabled [Boolean]
|
595
|
+
# @option instr_sampling_percent [Integer]
|
596
|
+
# @option instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
|
441
597
|
# @return [Hash<Symbol,Boolean|Hash<Symbol,Set<String>>>]
|
442
598
|
# Format: { ok: true, result: { processed_queus: Set<String> } }
|
443
599
|
#
|
444
600
|
# @api public
|
445
601
|
# @since 1.0.0
|
446
|
-
# @version 1.
|
602
|
+
# @version 1.6.0
|
447
603
|
def clear_dead_requests(
|
448
604
|
dead_ttl: config[:dead_request_ttl],
|
449
605
|
scan_size: config[:lock_release_batch_size],
|
450
606
|
logger: config[:logger],
|
451
607
|
instrumenter: config[:instrumenter],
|
452
|
-
instrument: nil
|
608
|
+
instrument: nil,
|
609
|
+
log_sampling_enabled: config[:log_sampling_enabled],
|
610
|
+
log_sampling_percent: config[:log_sampling_percent],
|
611
|
+
log_sampler: config[:log_sampler],
|
612
|
+
instr_sampling_enabled: config[:instr_sampling_enabled],
|
613
|
+
instr_sampling_percent: config[:instr_sampling_percent],
|
614
|
+
instr_sampler: config[:instr_sampler]
|
453
615
|
)
|
454
616
|
RedisQueuedLocks::Acquier::ClearDeadRequests.clear_dead_requests(
|
455
617
|
redis_client,
|
@@ -457,7 +619,13 @@ class RedisQueuedLocks::Client
|
|
457
619
|
dead_ttl,
|
458
620
|
logger,
|
459
621
|
instrumenter,
|
460
|
-
instrument
|
622
|
+
instrument,
|
623
|
+
log_sampling_enabled,
|
624
|
+
log_sampling_percent,
|
625
|
+
log_sampler,
|
626
|
+
instr_sampling_enabled,
|
627
|
+
instr_sampling_percent,
|
628
|
+
instr_sampler
|
461
629
|
)
|
462
630
|
end
|
463
631
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api public
|
4
|
+
# @since 1.6.0
|
5
|
+
module RedisQueuedLocks::Instrument::Sampler
|
6
|
+
# @return [Range]
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
# @since 1.6.0
|
10
|
+
SAMPLING_PERCENT_RANGE = (0..100)
|
11
|
+
|
12
|
+
class << self
|
13
|
+
# Super simple probalistic function based on the `weight` of <true>/<false> values.
|
14
|
+
# Requires the <percent> parameter as the required percent of <true> values sampled.
|
15
|
+
#
|
16
|
+
# @param sampling_percent [Integer]
|
17
|
+
# - percent of <true> values in range of 0..100;
|
18
|
+
# @return [Boolean]
|
19
|
+
# - <true> for <sampling_percent>% of invocations (and <false> for the rest invocations)
|
20
|
+
#
|
21
|
+
# @api public
|
22
|
+
# @since 1.6.0
|
23
|
+
def sampling_happened?(sampling_percent)
|
24
|
+
sampling_percent >= SecureRandom.rand(SAMPLING_PERCENT_RANGE)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -2,11 +2,58 @@
|
|
2
2
|
|
3
3
|
# @api public
|
4
4
|
# @since 1.0.0
|
5
|
+
# @version 1.6.0
|
5
6
|
module RedisQueuedLocks::Instrument
|
6
7
|
require_relative 'instrument/void_notifier'
|
7
8
|
require_relative 'instrument/active_support'
|
9
|
+
require_relative 'instrument/sampler'
|
8
10
|
|
9
11
|
class << self
|
12
|
+
# @param instr_sampling_enabled [Boolean]
|
13
|
+
# @param instr_sampling_percent [Integer]
|
14
|
+
# @param instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
|
15
|
+
# @return [Boolean]
|
16
|
+
#
|
17
|
+
# @api private
|
18
|
+
# @since 1.6.0
|
19
|
+
def should_instrument?(instr_sampling_enabled, instr_sampling_percent, instr_sampler)
|
20
|
+
return true unless instr_sampling_enabled
|
21
|
+
instr_sampler.sampling_happened?(instr_sampling_percent)
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
|
25
|
+
# @return [Boolean]
|
26
|
+
#
|
27
|
+
# @api private
|
28
|
+
# @since 1.6.0
|
29
|
+
def valid_sampler?(sampler)
|
30
|
+
return false unless sampler.respond_to?(:sampling_happened?)
|
31
|
+
|
32
|
+
m_obj = sampler.method(:sampling_happened?)
|
33
|
+
m_sig = m_obj.parameters
|
34
|
+
|
35
|
+
# NOTE:
|
36
|
+
# Required method signature (sampling_percent)
|
37
|
+
# => [[:req, :sampling_percent]]
|
38
|
+
# => [[:opt, :sampling_percent]]
|
39
|
+
# => [[:req, :sampling_percent], [:block, :block]]
|
40
|
+
# => [[:opt, :sampling_percent], [:block, :block]]
|
41
|
+
if m_sig.size == 1
|
42
|
+
prm = m_sig[0][0]
|
43
|
+
prm == :req || prm == :opt
|
44
|
+
elsif m_sig.size == 2
|
45
|
+
f_prm = m_sig[0][0]
|
46
|
+
s_prm = m_sign[1][0]
|
47
|
+
|
48
|
+
# rubocop:disable Layout/MultilineOperationIndentation
|
49
|
+
f_prm == :req && s_prm == :block ||
|
50
|
+
f_prm == :opt && s_prm == :block
|
51
|
+
# rubocop:enable Layout/MultilineOperationIndentation
|
52
|
+
else
|
53
|
+
false
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
10
57
|
# @param instrumenter [Class,Module,Object]
|
11
58
|
# @return [Boolean]
|
12
59
|
#
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api public
|
4
|
+
# @since 1.5.0
|
5
|
+
module RedisQueuedLocks::Logging::Sampler
|
6
|
+
# @return [Range]
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
# @since 1.6.0
|
10
|
+
SAMPLING_PERCENT_RANGE = (0..100)
|
11
|
+
|
12
|
+
class << self
|
13
|
+
# Super simple probalistic function based on the `weight` of <true>/<false> values.
|
14
|
+
# Requires the <percent> parameter as the required percent of <true> values sampled.
|
15
|
+
#
|
16
|
+
# @param sampling_percent [Integer]
|
17
|
+
# - percent of <true> values in range of 0..100;
|
18
|
+
# @return [Boolean]
|
19
|
+
# - <true> for <sampling_percent>% of invocations (and <false> for the rest invocations)
|
20
|
+
#
|
21
|
+
# @api public
|
22
|
+
# @since 1.5.0
|
23
|
+
# @version 1.6.0
|
24
|
+
def sampling_happened?(sampling_percent)
|
25
|
+
sampling_percent >= SecureRandom.rand(SAMPLING_PERCENT_RANGE)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -2,10 +2,57 @@
|
|
2
2
|
|
3
3
|
# @api public
|
4
4
|
# @since 1.0.0
|
5
|
+
# @version 1.5.0
|
5
6
|
module RedisQueuedLocks::Logging
|
6
7
|
require_relative 'logging/void_logger'
|
8
|
+
require_relative 'logging/sampler'
|
7
9
|
|
8
10
|
class << self
|
11
|
+
# @param log_sampling_enabled [Boolean]
|
12
|
+
# @param log_sampling_percent [Integer]
|
13
|
+
# @param log_sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
|
14
|
+
# @return [Boolean]
|
15
|
+
#
|
16
|
+
# @api private
|
17
|
+
# @since 1.5.0
|
18
|
+
def should_log?(log_sampling_enabled, log_sampling_percent, log_sampler)
|
19
|
+
return true unless log_sampling_enabled
|
20
|
+
log_sampler.sampling_happened?(log_sampling_percent)
|
21
|
+
end
|
22
|
+
|
23
|
+
# @param sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
|
24
|
+
# @return [Boolean]
|
25
|
+
#
|
26
|
+
# @api private
|
27
|
+
# @since 1.5.0
|
28
|
+
def valid_sampler?(sampler)
|
29
|
+
return false unless sampler.respond_to?(:sampling_happened?)
|
30
|
+
|
31
|
+
m_obj = sampler.method(:sampling_happened?)
|
32
|
+
m_sig = m_obj.parameters
|
33
|
+
|
34
|
+
# NOTE:
|
35
|
+
# Required method signature (sampling_percent)
|
36
|
+
# => [[:req, :sampling_percent]]
|
37
|
+
# => [[:opt, :sampling_percent]]
|
38
|
+
# => [[:req, :sampling_percent], [:block, :block]]
|
39
|
+
# => [[:opt, :sampling_percent], [:block, :block]]
|
40
|
+
if m_sig.size == 1
|
41
|
+
prm = m_sig[0][0]
|
42
|
+
prm == :req || prm == :opt
|
43
|
+
elsif m_sig.size == 2
|
44
|
+
f_prm = m_sig[0][0]
|
45
|
+
s_prm = m_sign[1][0]
|
46
|
+
|
47
|
+
# rubocop:disable Layout/MultilineOperationIndentation
|
48
|
+
f_prm == :req && s_prm == :block ||
|
49
|
+
f_prm == :opt && s_prm == :block
|
50
|
+
# rubocop:enable Layout/MultilineOperationIndentation
|
51
|
+
else
|
52
|
+
false
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
9
56
|
# @param logger [::Logger,#debug,::SemanticLogger::Logger]
|
10
57
|
# @return [Boolean]
|
11
58
|
#
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis_queued_locks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rustam Ibragimov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-05-
|
11
|
+
date: 2024-05-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis-client
|
@@ -79,8 +79,10 @@ files:
|
|
79
79
|
- lib/redis_queued_locks/errors.rb
|
80
80
|
- lib/redis_queued_locks/instrument.rb
|
81
81
|
- lib/redis_queued_locks/instrument/active_support.rb
|
82
|
+
- lib/redis_queued_locks/instrument/sampler.rb
|
82
83
|
- lib/redis_queued_locks/instrument/void_notifier.rb
|
83
84
|
- lib/redis_queued_locks/logging.rb
|
85
|
+
- lib/redis_queued_locks/logging/sampler.rb
|
84
86
|
- lib/redis_queued_locks/logging/void_logger.rb
|
85
87
|
- lib/redis_queued_locks/resource.rb
|
86
88
|
- lib/redis_queued_locks/utilities.rb
|
@@ -108,7 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
108
110
|
- !ruby/object:Gem::Version
|
109
111
|
version: '0'
|
110
112
|
requirements: []
|
111
|
-
rubygems_version: 3.
|
113
|
+
rubygems_version: 3.3.7
|
112
114
|
signing_key:
|
113
115
|
specification_version: 4
|
114
116
|
summary: Queued distributed locks based on Redis.
|