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
@@ -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.
|