redis_queued_locks 1.5.0 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -23,9 +23,13 @@ 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 :default_access_strategy, :queued
26
27
  setting :log_sampling_enabled, false
27
28
  setting :log_sampling_percent, 15
28
29
  setting :log_sampler, RedisQueuedLocks::Logging::Sampler
30
+ setting :instr_sampling_enabled, false
31
+ setting :instr_sampling_percent, 15
32
+ setting :instr_sampler, RedisQueuedLocks::Instrument::Sampler
29
33
 
30
34
  validate('retry_count') { |val| val == nil || (val.is_a?(::Integer) && val >= 0) }
31
35
  validate('retry_delay') { |val| val.is_a?(::Integer) && val >= 0 }
@@ -43,6 +47,9 @@ class RedisQueuedLocks::Client
43
47
  validate('log_sampler') { |val| RedisQueuedLocks::Logging.valid_sampler?(val) }
44
48
  validate('log_sampling_enabled', :boolean)
45
49
  validate('log_sampling_percent') { |val| val.is_a?(::Integer) && val >= 0 && val <= 100 }
50
+ validate('instr_sampling_enabled', :boolean)
51
+ validate('instr_sampling_percent') { |val| val.is_a?(::Integer) && val >= 0 && val <= 100 }
52
+ validate('instr_sampler') { |val| RedisQueuedLocks::Instrument.valid_sampler?(val) }
46
53
  validate('default_conflict_strategy') do |val|
47
54
  # rubocop:disable Layout/MultilineOperationIndentation
48
55
  val == :work_through ||
@@ -51,6 +58,12 @@ class RedisQueuedLocks::Client
51
58
  val == :dead_locking
52
59
  # rubocop:enable Layout/MultilineOperationIndentation
53
60
  end
61
+ validate('default_access_strategy') do |val|
62
+ # rubocop:disable Layout/MultilineOperationIndentation
63
+ val == :queued ||
64
+ val == :random
65
+ # rubocop:enable Layout/MultilineOperationIndentation
66
+ end
54
67
  end
55
68
 
56
69
  # @return [RedisClient]
@@ -98,8 +111,6 @@ class RedisQueuedLocks::Client
98
111
  # A time-interval between the each retry (in milliseconds).
99
112
  # @option retry_jitter [Integer]
100
113
  # Time-shift range for retry-delay (in milliseconds).
101
- # @option instrumenter [#notify]
102
- # See RedisQueuedLocks::Instrument::ActiveSupport for example.
103
114
  # @option raise_errors [Boolean]
104
115
  # Raise errors on library-related limits such as timeout or failed lock obtain.
105
116
  # @option identity [String]
@@ -122,6 +133,16 @@ class RedisQueuedLocks::Client
122
133
  # - `:wait_for_lock` - (default) - work in classic way
123
134
  # (with timeouts, retry delays, retry limits, etc - in classic way :));
124
135
  # - `:dead_locking` - fail with deadlock exception;
136
+ # @option access_strategy [Symbol]
137
+ # - The way in which the lock will be obtained;
138
+ # - By default it uses `:queued` strategy;
139
+ # - Supports following strategies:
140
+ # - `:queued` (FIFO): the classic queued behavior (default), your lock will be
141
+ # obitaned if you are first in queue and the required lock is free;
142
+ # - `:random` (RANDOM): obtain a lock without checking the positions in the queue
143
+ # (but with checking the limist, retries, timeouts and so on). if lock is
144
+ # free to obtain - it will be obtained;
145
+ # - pre-configured in `config[:default_access_strategy]`;
125
146
  # @option meta [NilClass,Hash<String|Symbol,Any>]
126
147
  # - A custom metadata wich will be passed to the lock data in addition to the existing data;
127
148
  # - Metadata can not contain reserved lock data keys;
@@ -133,6 +154,12 @@ class RedisQueuedLocks::Client
133
154
  # - should be logged the each try of lock acquiring (a lot of logs can
134
155
  # be generated depending on your retry configurations);
135
156
  # - see `config[:log_lock_try]`;
157
+ # @option instrumenter [#notify]
158
+ # - Custom instrumenter that will be invoked via #notify method with `event` and `payload` data;
159
+ # - See RedisQueuedLocks::Instrument::ActiveSupport for examples and implementation details;
160
+ # - See [Instrumentation](#instrumentation) section of docs;
161
+ # - pre-configured in `config[:isntrumenter]` with void notifier
162
+ # (`RedisQueuedLocks::Instrumenter::VoidNotifier`);
136
163
  # @option instrument [NilClass,Any]
137
164
  # - Custom instrumentation data wich will be passed to the instrumenter's payload
138
165
  # with :instrument key;
@@ -153,6 +180,24 @@ class RedisQueuedLocks::Client
153
180
  # - you can provide your own log sampler with bettter algorithm that should realize
154
181
  # `sampling_happened?(percent) => boolean` interface
155
182
  # (see `RedisQueuedLocks::Logging::Sampler` for example);
183
+ # @option instr_sampling_enabled [Boolean]
184
+ # - enables <instrumentaion sampling>: only the configured percent
185
+ # of RQL cases will be instrumented;
186
+ # - disabled by default;
187
+ # - works in tandem with <config.instr_sampling_percent and <log.instr_sampler>;
188
+ # @option instr_sampling_percent [Integer]
189
+ # - the percent of cases that should be instrumented;
190
+ # - take an effect when <config.instr_sampling_enalbed> is true;
191
+ # - works in tandem with <config.instr_sampling_enabled> and <config.instr_sampler> configs;
192
+ # @option instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
193
+ # - percent-based log sampler that decides should be RQL case instrumented or not;
194
+ # - works in tandem with <config.instr_sampling_enabled> and
195
+ # <config.instr_sampling_percent> configs;
196
+ # - based on the ultra simple percent-based (weight-based) algorithm that uses SecureRandom.rand
197
+ # method so the algorithm error is ~(0%..13%);
198
+ # - you can provide your own log sampler with bettter algorithm that should realize
199
+ # `sampling_happened?(percent) => boolean` interface
200
+ # (see `RedisQueuedLocks::Instrument::Sampler` for example);
156
201
  # @param block [Block]
157
202
  # A block of code that should be executed after the successfully acquired lock.
158
203
  # @return [RedisQueuedLocks::Data,Hash<Symbol,Any>,yield]
@@ -161,7 +206,7 @@ class RedisQueuedLocks::Client
161
206
  #
162
207
  # @api public
163
208
  # @since 1.0.0
164
- # @version 1.5.0
209
+ # @version 1.7.0
165
210
  # rubocop:disable Metrics/MethodLength
166
211
  def lock(
167
212
  lock_name,
@@ -175,14 +220,19 @@ class RedisQueuedLocks::Client
175
220
  raise_errors: false,
176
221
  fail_fast: false,
177
222
  conflict_strategy: config[:default_conflict_strategy],
223
+ access_strategy: config[:default_access_strategy],
178
224
  identity: uniq_identity,
179
225
  meta: nil,
180
226
  logger: config[:logger],
181
227
  log_lock_try: config[:log_lock_try],
228
+ instrumenter: config[:instrumenter],
182
229
  instrument: nil,
183
230
  log_sampling_enabled: config[:log_sampling_enabled],
184
231
  log_sampling_percent: config[:log_sampling_percent],
185
232
  log_sampler: config[:log_sampler],
233
+ instr_sampling_enabled: config[:instr_sampling_enabled],
234
+ instr_sampling_percent: config[:instr_sampling_percent],
235
+ instr_sampler: config[:instr_sampler],
186
236
  &block
187
237
  )
188
238
  RedisQueuedLocks::Acquier::AcquireLock.acquire_lock(
@@ -200,10 +250,11 @@ class RedisQueuedLocks::Client
200
250
  retry_delay:,
201
251
  retry_jitter:,
202
252
  raise_errors:,
203
- instrumenter: config[:instrumenter],
253
+ instrumenter:,
204
254
  identity:,
205
255
  fail_fast:,
206
256
  conflict_strategy:,
257
+ access_strategy:,
207
258
  meta:,
208
259
  logger:,
209
260
  log_lock_try:,
@@ -211,6 +262,9 @@ class RedisQueuedLocks::Client
211
262
  log_sampling_enabled:,
212
263
  log_sampling_percent:,
213
264
  log_sampler:,
265
+ instr_sampling_enabled:,
266
+ instr_sampling_percent:,
267
+ instr_sampler:,
214
268
  &block
215
269
  )
216
270
  end
@@ -220,7 +274,8 @@ class RedisQueuedLocks::Client
220
274
  #
221
275
  # @api public
222
276
  # @since 1.0.0
223
- # @version 1.5.0
277
+ # @version 1.7.0
278
+ # rubocop:disable Metrics/MethodLength
224
279
  def lock!(
225
280
  lock_name,
226
281
  ttl: config[:default_lock_ttl],
@@ -232,7 +287,9 @@ class RedisQueuedLocks::Client
232
287
  retry_jitter: config[:retry_jitter],
233
288
  fail_fast: false,
234
289
  conflict_strategy: config[:default_conflict_strategy],
290
+ access_strategy: config[:default_access_strategy],
235
291
  identity: uniq_identity,
292
+ instrumenter: config[:instrumenter],
236
293
  meta: nil,
237
294
  logger: config[:logger],
238
295
  log_lock_try: config[:log_lock_try],
@@ -240,6 +297,9 @@ class RedisQueuedLocks::Client
240
297
  log_sampling_enabled: config[:log_sampling_enabled],
241
298
  log_sampling_percent: config[:log_sampling_percent],
242
299
  log_sampler: config[:log_sampler],
300
+ instr_sampling_enabled: config[:instr_sampling_enabled],
301
+ instr_sampling_percent: config[:instr_sampling_percent],
302
+ instr_sampler: config[:instr_sampler],
243
303
  &block
244
304
  )
245
305
  lock(
@@ -258,13 +318,19 @@ class RedisQueuedLocks::Client
258
318
  log_lock_try:,
259
319
  meta:,
260
320
  instrument:,
321
+ instrumenter:,
261
322
  conflict_strategy:,
323
+ access_strategy:,
262
324
  log_sampling_enabled:,
263
325
  log_sampling_percent:,
264
326
  log_sampler:,
327
+ instr_sampling_enabled:,
328
+ instr_sampling_percent:,
329
+ instr_sampler:,
265
330
  &block
266
331
  )
267
332
  end
333
+ # rubocop:enable Metrics/MethodLength
268
334
 
269
335
  # @param lock_name [String] The lock name that should be released.
270
336
  # @option logger [::Logger,#debug]
@@ -273,6 +339,9 @@ class RedisQueuedLocks::Client
273
339
  # @option log_sampling_enabled [Boolean]
274
340
  # @option log_sampling_percent [Integer]
275
341
  # @option log_sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
342
+ # @option instr_sampling_enabled [Boolean]
343
+ # @option instr_sampling_percent [Integer]
344
+ # @option instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
276
345
  # @return [RedisQueuedLocks::Data, Hash<Symbol,Any>]
277
346
  # Format: {
278
347
  # ok: true/false,
@@ -287,7 +356,7 @@ class RedisQueuedLocks::Client
287
356
  #
288
357
  # @api public
289
358
  # @since 1.0.0
290
- # @version 1.5.0
359
+ # @version 1.6.0
291
360
  def unlock(
292
361
  lock_name,
293
362
  logger: config[:logger],
@@ -295,16 +364,22 @@ class RedisQueuedLocks::Client
295
364
  instrument: nil,
296
365
  log_sampling_enabled: config[:log_sampling_enabled],
297
366
  log_sampling_percent: config[:log_sampling_percent],
298
- log_sampler: config[:log_sampler]
367
+ log_sampler: config[:log_sampler],
368
+ instr_sampling_enabled: config[:instr_sampling_enabled],
369
+ instr_sampling_percent: config[:instr_sampling_percent],
370
+ instr_sampler: config[:instr_sampler]
299
371
  )
300
372
  RedisQueuedLocks::Acquier::ReleaseLock.release_lock(
301
373
  redis_client,
302
374
  lock_name,
303
- config[:instrumenter],
304
- config[:logger],
375
+ instrumenter,
376
+ logger,
305
377
  log_sampling_enabled,
306
378
  log_sampling_percent,
307
- log_sampler
379
+ log_sampler,
380
+ instr_sampling_enabled,
381
+ instr_sampling_percent,
382
+ instr_sampler
308
383
  )
309
384
  end
310
385
 
@@ -358,43 +433,47 @@ class RedisQueuedLocks::Client
358
433
  # @param lock_name [String]
359
434
  # @param milliseconds [Integer] How many milliseconds should be added.
360
435
  # @option logger [::Logger,#debug]
436
+ # @option instrumenter [#notify] See `config[:instrumenter]` docs for details.
437
+ # @option instrument [NilClass,Any]
361
438
  # @option log_sampling_enabled [Boolean]
362
- # - The percent of cases that should be logged;
363
- # - Sampling algorithm is super simple and works via SecureRandom.rand method
364
- # on the base of "weight" algorithm;
365
- # - You can provide your own sampler via config[:log_sampler] config and :sampler option
366
- # (see `RedisQueuedLocks::Logging::Sampler` for examples);
367
- # - The spread of guaranteed percent is approximately +13% (rand method spread);
368
- # - Take an effect when <log_sampling_enabled> parameter has <true> value
369
- # (when log sampling is enabled);
370
439
  # @option log_sampling_percent [Integer]
371
- # - The percent of cases that should be logged;
372
- # - Take an effect when <log_sampling_enabled> parameter has <true> value
373
- # (when log sampling is enabled);
374
440
  # @option log_sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
441
+ # @option instr_sampling_enabled [Boolean]
442
+ # @option instr_sampling_percent [Integer]
443
+ # @option instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
375
444
  # @return [Hash<Symbol,Boolean|Symbol>]
376
445
  # - { ok: true, result: :ttl_extended }
377
446
  # - { ok: false, result: :async_expire_or_no_lock }
378
447
  #
379
448
  # @api public
380
449
  # @since 1.0.0
381
- # @version 1.5.0
450
+ # @version 1.6.0
382
451
  def extend_lock_ttl(
383
452
  lock_name,
384
453
  milliseconds,
385
454
  logger: config[:logger],
455
+ instrumenter: config[:instrumenter],
456
+ instrument: nil,
386
457
  log_sampling_enabled: config[:log_sampling_enabled],
387
458
  log_sampling_percent: config[:log_sampling_percent],
388
- log_sampler: config[:log_sampler]
459
+ log_sampler: config[:log_sampler],
460
+ instr_sampling_enabled: config[:instr_sampling_enabled],
461
+ instr_sampling_percent: config[:instr_sampling_percent],
462
+ instr_sampler: config[:instr_sampler]
389
463
  )
390
464
  RedisQueuedLocks::Acquier::ExtendLockTTL.extend_lock_ttl(
391
465
  redis_client,
392
466
  lock_name,
393
467
  milliseconds,
394
468
  logger,
469
+ instrumenter,
470
+ instrument,
395
471
  log_sampling_enabled,
396
472
  log_sampling_percent,
397
- log_sampler
473
+ log_sampler,
474
+ instr_sampling_enabled,
475
+ instr_sampling_percent,
476
+ instr_sampler
398
477
  )
399
478
  end
400
479
 
@@ -405,17 +484,20 @@ class RedisQueuedLocks::Client
405
484
  #
406
485
  # @option batch_size [Integer]
407
486
  # @option logger [::Logger,#debug]
408
- # @option instrumenter [#notify]
487
+ # @option instrumenter [#notify] See `config[:instrumenter]` docs for details.
409
488
  # @option instrument [NilClass,Any]
410
489
  # @option log_sampling_enabled [Boolean]
411
490
  # @option log_sampling_percent [Integer]
412
491
  # @option log_sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
492
+ # @option instr_sampling_enabled [Boolean]
493
+ # @option instr_sampling_percent [Integer]
494
+ # @option instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
413
495
  # @return [RedisQueuedLocks::Data,Hash<Symbol,Boolean|Hash<Symbol,Numeric>>]
414
496
  # Example: { ok: true, result { rel_key_cnt: 100, rel_time: 0.01 } }
415
497
  #
416
498
  # @api public
417
499
  # @since 1.0.0
418
- # @version 1.5.0
500
+ # @version 1.6.0
419
501
  def clear_locks(
420
502
  batch_size: config[:lock_release_batch_size],
421
503
  logger: config[:logger],
@@ -423,7 +505,10 @@ class RedisQueuedLocks::Client
423
505
  instrument: nil,
424
506
  log_sampling_enabled: config[:log_sampling_enabled],
425
507
  log_sampling_percent: config[:log_sampling_percent],
426
- log_sampler: config[:log_sampler]
508
+ log_sampler: config[:log_sampler],
509
+ instr_sampling_enabled: config[:instr_sampling_enabled],
510
+ instr_sampling_percent: config[:instr_sampling_percent],
511
+ instr_sampler: config[:instr_sampler]
427
512
  )
428
513
  RedisQueuedLocks::Acquier::ReleaseAllLocks.release_all_locks(
429
514
  redis_client,
@@ -433,7 +518,10 @@ class RedisQueuedLocks::Client
433
518
  instrument,
434
519
  log_sampling_enabled,
435
520
  log_sampling_percent,
436
- log_sampler
521
+ log_sampler,
522
+ instr_sampling_enabled,
523
+ instr_sampling_percent,
524
+ instr_sampler
437
525
  )
438
526
  end
439
527
 
@@ -524,12 +612,15 @@ class RedisQueuedLocks::Client
524
612
  # @option log_sampling_enabled [Boolean]
525
613
  # @option log_sampling_percent [Integer]
526
614
  # @option log_sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
615
+ # @option instr_sampling_enabled [Boolean]
616
+ # @option instr_sampling_percent [Integer]
617
+ # @option instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
527
618
  # @return [Hash<Symbol,Boolean|Hash<Symbol,Set<String>>>]
528
619
  # Format: { ok: true, result: { processed_queus: Set<String> } }
529
620
  #
530
621
  # @api public
531
622
  # @since 1.0.0
532
- # @version 1.5.0
623
+ # @version 1.6.0
533
624
  def clear_dead_requests(
534
625
  dead_ttl: config[:dead_request_ttl],
535
626
  scan_size: config[:lock_release_batch_size],
@@ -538,7 +629,10 @@ class RedisQueuedLocks::Client
538
629
  instrument: nil,
539
630
  log_sampling_enabled: config[:log_sampling_enabled],
540
631
  log_sampling_percent: config[:log_sampling_percent],
541
- log_sampler: config[:log_sampler]
632
+ log_sampler: config[:log_sampler],
633
+ instr_sampling_enabled: config[:instr_sampling_enabled],
634
+ instr_sampling_percent: config[:instr_sampling_percent],
635
+ instr_sampler: config[:instr_sampler]
542
636
  )
543
637
  RedisQueuedLocks::Acquier::ClearDeadRequests.clear_dead_requests(
544
638
  redis_client,
@@ -549,7 +643,10 @@ class RedisQueuedLocks::Client
549
643
  instrument,
550
644
  log_sampling_enabled,
551
645
  log_sampling_percent,
552
- log_sampler
646
+ log_sampler,
647
+ instr_sampling_enabled,
648
+ instr_sampling_percent,
649
+ instr_sampler
553
650
  )
554
651
  end
555
652
  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
  #
@@ -1,8 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # @api private
3
+ # @api public
4
4
  # @since 1.5.0
5
5
  module RedisQueuedLocks::Logging::Sampler
6
+ # @return [Range]
7
+ #
8
+ # @api private
9
+ # @since 1.6.0
10
+ SAMPLING_PERCENT_RANGE = (0..100)
11
+
6
12
  class << self
7
13
  # Super simple probalistic function based on the `weight` of <true>/<false> values.
8
14
  # Requires the <percent> parameter as the required percent of <true> values sampled.
@@ -12,10 +18,11 @@ module RedisQueuedLocks::Logging::Sampler
12
18
  # @return [Boolean]
13
19
  # - <true> for <sampling_percent>% of invocations (and <false> for the rest invocations)
14
20
  #
15
- # @api private
21
+ # @api public
16
22
  # @since 1.5.0
23
+ # @version 1.6.0
17
24
  def sampling_happened?(sampling_percent)
18
- sampling_percent >= SecureRandom.rand(0..100)
25
+ sampling_percent >= SecureRandom.rand(SAMPLING_PERCENT_RANGE)
19
26
  end
20
27
  end
21
28
  end
@@ -2,6 +2,7 @@
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'
7
8
  require_relative 'logging/sampler'
@@ -2,7 +2,6 @@
2
2
 
3
3
  # @api private
4
4
  # @since 1.0.0
5
- # @version 1.5.0
6
5
  module RedisQueuedLocks::Utilities
7
6
  module_function
8
7
 
@@ -5,6 +5,6 @@ module RedisQueuedLocks
5
5
  #
6
6
  # @api public
7
7
  # @since 0.0.1
8
- # @version 1.5.0
9
- VERSION = '1.5.0'
8
+ # @version 1.7.0
9
+ VERSION = '1.7.0'
10
10
  end
@@ -0,0 +1 @@
1
+ # frozen_string_literal: true
@@ -10,9 +10,29 @@ Gem::Specification.new do |spec|
10
10
  spec.authors = ['Rustam Ibragimov']
11
11
  spec.email = ['iamdaiver@gmail.com']
12
12
 
13
- spec.summary = 'Queued distributed locks based on Redis.'
14
- spec.description = 'Distributed locks with "lock acquisition queue" ' \
15
- 'capabilities based on the Redis Database.'
13
+ spec.summary =
14
+ 'Distributed locks with "prioritized lock acquisition queue" ' \
15
+ 'capabilities based on the Redis Database.'
16
+
17
+ spec.description =
18
+ 'Distributed locks with "prioritized lock acquisition queue" capabilities ' \
19
+ 'based on the Redis Database. ' \
20
+ # ---
21
+ 'Each lock request is put into the request queue ' \
22
+ "(each lock is hosted by it's own queue separately from other queues) and processed " \
23
+ 'in order of their priority (FIFO). ' \
24
+ # ---
25
+ 'Each lock request lives some period of time (RTTL) ' \
26
+ '(with requeue capabilities) which guarantees the request queue will never be stacked. ' \
27
+ # ---
28
+ 'In addition to the classic `queued` (FIFO) strategy RQL supports ' \
29
+ '`random` (RANDOM) lock obtaining strategy when any acquirer from the lock queue ' \
30
+ 'can obtain the lock regardless the position in the queue. ' \
31
+ # ---
32
+ 'Provides flexible invocation flow, parametrized limits ' \
33
+ '(lock request ttl, lock ttl, queue ttl, lock attempts limit, fast failing, etc), ' \
34
+ 'logging and instrumentation.'
35
+
16
36
  spec.homepage = 'https://github.com/0exp/redis_queued_locks'
17
37
  spec.license = 'MIT'
18
38
 
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.5.0
4
+ version: 1.7.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-23 00:00:00.000000000 Z
11
+ date: 2024-06-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis-client
@@ -38,8 +38,8 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0.28'
41
- description: Distributed locks with "lock acquisition queue" capabilities based on
42
- the Redis Database.
41
+ description: 'Distributed locks with "prioritized lock acquisition queue" capabilities
42
+ based on the Redis Database. '
43
43
  email:
44
44
  - iamdaiver@gmail.com
45
45
  executables: []
@@ -58,9 +58,15 @@ files:
58
58
  - lib/redis_queued_locks/acquier.rb
59
59
  - lib/redis_queued_locks/acquier/acquire_lock.rb
60
60
  - lib/redis_queued_locks/acquier/acquire_lock/delay_execution.rb
61
+ - lib/redis_queued_locks/acquier/acquire_lock/dequeue_from_lock_queue.rb
62
+ - lib/redis_queued_locks/acquier/acquire_lock/dequeue_from_lock_queue/log_visitor.rb
63
+ - lib/redis_queued_locks/acquier/acquire_lock/instr_visitor.rb
64
+ - lib/redis_queued_locks/acquier/acquire_lock/log_visitor.rb
61
65
  - lib/redis_queued_locks/acquier/acquire_lock/try_to_lock.rb
66
+ - lib/redis_queued_locks/acquier/acquire_lock/try_to_lock/log_visitor.rb
62
67
  - lib/redis_queued_locks/acquier/acquire_lock/with_acq_timeout.rb
63
68
  - lib/redis_queued_locks/acquier/acquire_lock/yield_expire.rb
69
+ - lib/redis_queued_locks/acquier/acquire_lock/yield_expire/log_visitor.rb
64
70
  - lib/redis_queued_locks/acquier/clear_dead_requests.rb
65
71
  - lib/redis_queued_locks/acquier/extend_lock_ttl.rb
66
72
  - lib/redis_queued_locks/acquier/is_locked.rb
@@ -79,6 +85,7 @@ files:
79
85
  - lib/redis_queued_locks/errors.rb
80
86
  - lib/redis_queued_locks/instrument.rb
81
87
  - lib/redis_queued_locks/instrument/active_support.rb
88
+ - lib/redis_queued_locks/instrument/sampler.rb
82
89
  - lib/redis_queued_locks/instrument/void_notifier.rb
83
90
  - lib/redis_queued_locks/logging.rb
84
91
  - lib/redis_queued_locks/logging/sampler.rb
@@ -86,6 +93,7 @@ files:
86
93
  - lib/redis_queued_locks/resource.rb
87
94
  - lib/redis_queued_locks/utilities.rb
88
95
  - lib/redis_queued_locks/version.rb
96
+ - lib/redis_queued_locks/watcher.rb
89
97
  - redis_queued_locks.gemspec
90
98
  homepage: https://github.com/0exp/redis_queued_locks
91
99
  licenses:
@@ -109,8 +117,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
109
117
  - !ruby/object:Gem::Version
110
118
  version: '0'
111
119
  requirements: []
112
- rubygems_version: 3.5.1
120
+ rubygems_version: 3.3.7
113
121
  signing_key:
114
122
  specification_version: 4
115
- summary: Queued distributed locks based on Redis.
123
+ summary: Distributed locks with "prioritized lock acquisition queue" capabilities
124
+ based on the Redis Database.
116
125
  test_files: []