redis_queued_locks 1.22.0 → 1.23.1
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/.claude/project-overview.md +90 -38
- data/.claude/rules/acquirer.md +12 -7
- data/.claude/rules/arguments.md +2 -2
- data/.claude/rules/logic.md +5 -4
- data/.claude/rules/tests.md +4 -4
- data/.claude/rules/type-checking.md +2 -3
- data/.claude/rules/visitors.md +8 -6
- data/.claude/skills/rql-code-review/SKILL.md +25 -20
- data/.ruby-version +1 -1
- data/CHANGELOG.md +30 -1
- data/CLAUDE.md +5 -4
- data/README.md +259 -103
- data/lib/redis_queued_locks/acquirer/acquire_lock/dequeue_from_lock_queue.rb +4 -4
- data/lib/redis_queued_locks/acquirer/acquire_lock/try_to_lock.rb +582 -276
- data/lib/redis_queued_locks/acquirer/acquire_lock/yield_expire.rb +29 -12
- data/lib/redis_queued_locks/acquirer/acquire_lock.rb +36 -27
- data/lib/redis_queued_locks/acquirer/extend_lock_ttl.rb +13 -13
- data/lib/redis_queued_locks/acquirer/lock_series/instr_visitor.rb +243 -0
- data/lib/redis_queued_locks/acquirer/lock_series/log_visitor.rb +472 -0
- data/lib/redis_queued_locks/acquirer/lock_series/release_lock_series.rb +181 -0
- data/lib/redis_queued_locks/acquirer/lock_series/try_to_lock_series.rb +1051 -0
- data/lib/redis_queued_locks/acquirer/lock_series.rb +957 -0
- data/lib/redis_queued_locks/acquirer.rb +1 -1
- data/lib/redis_queued_locks/client.rb +55 -25
- data/lib/redis_queued_locks/errors.rb +8 -0
- data/lib/redis_queued_locks/version.rb +2 -2
- data/redis_queued_locks.gemspec +21 -14
- data/sig/redis_queued_locks/acquirer/acquire_lock/dequeue_from_lock_queue.rbs +1 -1
- data/sig/redis_queued_locks/acquirer/acquire_lock/try_to_lock.rbs +106 -5
- data/sig/redis_queued_locks/acquirer/acquire_lock.rbs +1 -1
- data/sig/redis_queued_locks/acquirer/extend_lock_ttl.rbs +2 -2
- data/sig/redis_queued_locks/acquirer/lock_series/instr_visitor.rbs +102 -0
- data/sig/redis_queued_locks/acquirer/lock_series/log_visitor.rbs +154 -0
- data/sig/redis_queued_locks/acquirer/lock_series/release_lock_series.rbs +37 -0
- data/sig/redis_queued_locks/acquirer/lock_series/try_to_lock_series.rbs +198 -0
- data/sig/redis_queued_locks/acquirer/lock_series.rbs +106 -0
- data/sig/redis_queued_locks/client.rbs +70 -3
- data/sig/redis_queued_locks/errors.rbs +6 -0
- metadata +32 -11
- data/lib/redis_queued_locks/acquirer/lock_series_poc/instr_visitor.rb +0 -61
- data/lib/redis_queued_locks/acquirer/lock_series_poc/log_visitor.rb +0 -104
- data/lib/redis_queued_locks/acquirer/lock_series_poc.rb +0 -513
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
# @api private
|
|
4
4
|
# @since 1.3.0
|
|
5
5
|
# @version 1.18.0
|
|
6
|
+
# rubocop:disable Metrics/ModuleLength
|
|
6
7
|
module RedisQueuedLocks::Acquirer::AcquireLock::YieldExpire
|
|
7
8
|
require_relative 'yield_expire/log_visitor'
|
|
8
9
|
|
|
@@ -158,21 +159,37 @@ module RedisQueuedLocks::Acquirer::AcquireLock::YieldExpire
|
|
|
158
159
|
# @return [Any]
|
|
159
160
|
#
|
|
160
161
|
# @raise [RedisQueuedLocks::TimedLockTimeoutError]
|
|
162
|
+
# @raise [RedisQueuedLocks::LockTtlTimeBudgetIsSpentError]
|
|
163
|
+
# @raise [RedisQueuedLocks::TimedBlockExceedsLockTtlError]
|
|
161
164
|
#
|
|
162
165
|
# @api private
|
|
163
166
|
# @since 1.3.0
|
|
164
|
-
# @version 1.
|
|
167
|
+
# @version 1.23.1
|
|
165
168
|
def yield_with_timeout(timeout, lock_key, lock_ttl, acquirer_id, host_id, meta, &block)
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
169
|
+
# NOTE: no budget left => the block is not invoked (`Timeout.timeout(0)` means "no timeout")
|
|
170
|
+
if timeout == 0.0
|
|
171
|
+
raise(
|
|
172
|
+
RedisQueuedLocks::LockTtlTimeBudgetIsSpentError,
|
|
173
|
+
"Passed <timed> block of code was not invoked: the time budget of the lock TTL is spent " \
|
|
174
|
+
"(lock: \"#{lock_key}\", ttl: #{lock_ttl}, " \
|
|
175
|
+
"meta: #{meta ? meta.inspect : '<no-meta>'}, " \
|
|
176
|
+
"acq_id: \"#{acquirer_id}\", " \
|
|
177
|
+
"hst_id: \"#{host_id}\")"
|
|
178
|
+
)
|
|
179
|
+
else
|
|
180
|
+
begin
|
|
181
|
+
::Timeout.timeout(timeout, RedisQueuedLocks::TimedLockIntermediateTimeoutError, &block)
|
|
182
|
+
rescue RedisQueuedLocks::TimedLockIntermediateTimeoutError
|
|
183
|
+
raise(
|
|
184
|
+
RedisQueuedLocks::TimedBlockExceedsLockTtlError,
|
|
185
|
+
"Passed <timed> block of code exceeded the lock TTL " \
|
|
186
|
+
"(lock: \"#{lock_key}\", ttl: #{lock_ttl}, " \
|
|
187
|
+
"meta: #{meta ? meta.inspect : '<no-meta>'}, " \
|
|
188
|
+
"acq_id: \"#{acquirer_id}\", " \
|
|
189
|
+
"hst_id: \"#{host_id}\")"
|
|
190
|
+
)
|
|
191
|
+
end
|
|
192
|
+
end
|
|
177
193
|
end
|
|
178
194
|
end
|
|
195
|
+
# rubocop:enable Metrics/ModuleLength
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# @api private
|
|
4
4
|
# @since 1.0.0
|
|
5
|
-
# @version 1.
|
|
5
|
+
# @version 1.23.0
|
|
6
6
|
# rubocop:disable Metrics/ModuleLength
|
|
7
7
|
# rubocop:disable Metrics/MethodLength
|
|
8
8
|
# rubocop:disable Metrics/ClassLength
|
|
@@ -106,7 +106,7 @@ module RedisQueuedLocks::Acquirer::AcquireLock
|
|
|
106
106
|
# - `:extendable_work_through`;
|
|
107
107
|
# - `:wait_for_lock`;
|
|
108
108
|
# - `:dead_locking`;
|
|
109
|
-
# @option
|
|
109
|
+
# @option rw_mode [Symbol]
|
|
110
110
|
# - `:write` (default) - exclusive lock: waits for the write lock and for all read locks;
|
|
111
111
|
# - `:read` - shared lock: waits for the write lock only (read locks do not block each other);
|
|
112
112
|
# - `:queued` access strategy orders read and write requests in FIFO between modes
|
|
@@ -193,7 +193,7 @@ module RedisQueuedLocks::Acquirer::AcquireLock
|
|
|
193
193
|
#
|
|
194
194
|
# @api private
|
|
195
195
|
# @since 1.0.0
|
|
196
|
-
# @version 1.
|
|
196
|
+
# @version 1.23.1
|
|
197
197
|
def acquire_lock(
|
|
198
198
|
redis,
|
|
199
199
|
lock_name,
|
|
@@ -220,7 +220,7 @@ module RedisQueuedLocks::Acquirer::AcquireLock
|
|
|
220
220
|
logger:,
|
|
221
221
|
log_lock_try:,
|
|
222
222
|
conflict_strategy:,
|
|
223
|
-
|
|
223
|
+
rw_mode:,
|
|
224
224
|
access_strategy:,
|
|
225
225
|
priority:,
|
|
226
226
|
lock_priorities:,
|
|
@@ -245,14 +245,14 @@ module RedisQueuedLocks::Acquirer::AcquireLock
|
|
|
245
245
|
)
|
|
246
246
|
end
|
|
247
247
|
|
|
248
|
-
# Step 0.1 (RW): prevent :
|
|
249
|
-
case
|
|
248
|
+
# Step 0.1 (RW): prevent :rw_mode incompatabilities
|
|
249
|
+
case rw_mode # NOTE: (steep) case/when narrows `Symbol` to `RQL::readWriteMode` below
|
|
250
250
|
when :read, :write then nil
|
|
251
251
|
else
|
|
252
252
|
raise(
|
|
253
253
|
RedisQueuedLocks::ArgumentError,
|
|
254
|
-
"`:
|
|
255
|
-
"got #{
|
|
254
|
+
"`:rw_mode` argument should be `:read` or `:write`, " \
|
|
255
|
+
"got #{rw_mode.inspect}."
|
|
256
256
|
)
|
|
257
257
|
end
|
|
258
258
|
|
|
@@ -383,7 +383,7 @@ module RedisQueuedLocks::Acquirer::AcquireLock
|
|
|
383
383
|
# NOTE: (RW) read lock data key is required by read lock requests only (write lock requests
|
|
384
384
|
# never obtain read locks: read-to-write lock upgrade is not supported);
|
|
385
385
|
read_lock_key =
|
|
386
|
-
if
|
|
386
|
+
if rw_mode == :read
|
|
387
387
|
RedisQueuedLocks::Resource.prepare_read_lock_key(lock_name, acquirer_id)
|
|
388
388
|
end
|
|
389
389
|
|
|
@@ -412,6 +412,7 @@ module RedisQueuedLocks::Acquirer::AcquireLock
|
|
|
412
412
|
tries: 0,
|
|
413
413
|
acquired: false,
|
|
414
414
|
result: nil,
|
|
415
|
+
try_start_time: nil,
|
|
415
416
|
acq_time: nil, # NOTE: in milliseconds
|
|
416
417
|
hold_time: nil, # NOTE: in milliseconds
|
|
417
418
|
rel_time: nil # NOTE: in milliseconds
|
|
@@ -422,7 +423,7 @@ module RedisQueuedLocks::Acquirer::AcquireLock
|
|
|
422
423
|
redis,
|
|
423
424
|
logger,
|
|
424
425
|
lock_key,
|
|
425
|
-
|
|
426
|
+
rw_mode,
|
|
426
427
|
lock_key_queue,
|
|
427
428
|
read_lock_key_queue,
|
|
428
429
|
queue_ttl,
|
|
@@ -436,7 +437,7 @@ module RedisQueuedLocks::Acquirer::AcquireLock
|
|
|
436
437
|
|
|
437
438
|
LogVisitor.start_lock_obtaining(
|
|
438
439
|
logger, log_sampled, lock_key,
|
|
439
|
-
queue_ttl, acquirer_id, host_id, access_strategy,
|
|
440
|
+
queue_ttl, acquirer_id, host_id, access_strategy, rw_mode, priority
|
|
440
441
|
)
|
|
441
442
|
|
|
442
443
|
# Step 2: try to lock with timeout
|
|
@@ -457,7 +458,7 @@ module RedisQueuedLocks::Acquirer::AcquireLock
|
|
|
457
458
|
|
|
458
459
|
LogVisitor.start_try_to_lock_cycle(
|
|
459
460
|
logger, log_sampled, lock_key,
|
|
460
|
-
queue_ttl, acquirer_id, host_id, access_strategy,
|
|
461
|
+
queue_ttl, acquirer_id, host_id, access_strategy, rw_mode, priority
|
|
461
462
|
)
|
|
462
463
|
|
|
463
464
|
# Step 2.X: check the actual score: is it in queue ttl limit or not?
|
|
@@ -468,10 +469,12 @@ module RedisQueuedLocks::Acquirer::AcquireLock
|
|
|
468
469
|
|
|
469
470
|
LogVisitor.dead_score_reached__reset_acquirer_position(
|
|
470
471
|
logger, log_sampled, lock_key,
|
|
471
|
-
queue_ttl, acquirer_id, host_id, access_strategy,
|
|
472
|
+
queue_ttl, acquirer_id, host_id, access_strategy, rw_mode, priority
|
|
472
473
|
)
|
|
473
474
|
end
|
|
474
475
|
|
|
476
|
+
acq_process[:try_start_time] = clock_gettime
|
|
477
|
+
|
|
475
478
|
# NOTE: (steep ignorance) pattern matching is not supported in steep
|
|
476
479
|
# steep:ignore:start
|
|
477
480
|
try_to_lock(
|
|
@@ -479,7 +482,7 @@ module RedisQueuedLocks::Acquirer::AcquireLock
|
|
|
479
482
|
logger,
|
|
480
483
|
log_lock_try,
|
|
481
484
|
lock_key,
|
|
482
|
-
|
|
485
|
+
rw_mode,
|
|
483
486
|
lock_key_queue,
|
|
484
487
|
read_lock_key_queue,
|
|
485
488
|
lock_readers_key,
|
|
@@ -522,11 +525,11 @@ module RedisQueuedLocks::Acquirer::AcquireLock
|
|
|
522
525
|
# instrumetnation: (reentrant lock with ttl extension)
|
|
523
526
|
LogVisitor.extendable_reentrant_lock_obtained(
|
|
524
527
|
logger, log_sampled, result[:lock_key],
|
|
525
|
-
queue_ttl, acquirer_id, host_id, acq_time, access_strategy,
|
|
528
|
+
queue_ttl, acquirer_id, host_id, acq_time, access_strategy, rw_mode,
|
|
526
529
|
priority
|
|
527
530
|
)
|
|
528
531
|
InstrVisitor.extendable_reentrant_lock_obtained(
|
|
529
|
-
instrumenter, instr_sampled, result[:lock_key],
|
|
532
|
+
instrumenter, instr_sampled, result[:lock_key], rw_mode, priority,
|
|
530
533
|
result[:ttl], result[:acq_id], result[:hst_id], result[:ts], acq_time,
|
|
531
534
|
instrument
|
|
532
535
|
)
|
|
@@ -534,11 +537,11 @@ module RedisQueuedLocks::Acquirer::AcquireLock
|
|
|
534
537
|
# instrumetnation: (reentrant lock without ttl extension)
|
|
535
538
|
LogVisitor.reentrant_lock_obtained(
|
|
536
539
|
logger, log_sampled, result[:lock_key],
|
|
537
|
-
queue_ttl, acquirer_id, host_id, acq_time, access_strategy,
|
|
540
|
+
queue_ttl, acquirer_id, host_id, acq_time, access_strategy, rw_mode,
|
|
538
541
|
priority
|
|
539
542
|
)
|
|
540
543
|
InstrVisitor.reentrant_lock_obtained(
|
|
541
|
-
instrumenter, instr_sampled, result[:lock_key],
|
|
544
|
+
instrumenter, instr_sampled, result[:lock_key], rw_mode, priority,
|
|
542
545
|
result[:ttl], result[:acq_id], result[:hst_id], result[:ts], acq_time,
|
|
543
546
|
instrument
|
|
544
547
|
)
|
|
@@ -547,11 +550,11 @@ module RedisQueuedLocks::Acquirer::AcquireLock
|
|
|
547
550
|
# NOTE: classic is: acq_process[:result][:process] == :lock_obtaining
|
|
548
551
|
LogVisitor.lock_obtained(
|
|
549
552
|
logger, log_sampled, result[:lock_key],
|
|
550
|
-
queue_ttl, acquirer_id, host_id, acq_time, access_strategy,
|
|
553
|
+
queue_ttl, acquirer_id, host_id, acq_time, access_strategy, rw_mode,
|
|
551
554
|
priority
|
|
552
555
|
)
|
|
553
556
|
InstrVisitor.lock_obtained(
|
|
554
|
-
instrumenter, instr_sampled, result[:lock_key],
|
|
557
|
+
instrumenter, instr_sampled, result[:lock_key], rw_mode, priority,
|
|
555
558
|
result[:ttl], result[:acq_id], result[:hst_id], result[:ts], acq_time,
|
|
556
559
|
instrument
|
|
557
560
|
)
|
|
@@ -662,8 +665,14 @@ module RedisQueuedLocks::Acquirer::AcquireLock
|
|
|
662
665
|
begin
|
|
663
666
|
yield_time = clock_gettime
|
|
664
667
|
|
|
668
|
+
# NOTE: the budget of a `timed` block (see `Resource::REDIS_TIMESHIFT_ERROR`):
|
|
669
|
+
# - the lock ttl starts inside the attempt (write: `EXEC` of the transaction,
|
|
670
|
+
# read: `TIME` of the lock state read), this moment is unknown on the client:
|
|
671
|
+
# the time is counted from the start of the successful attempt (it is
|
|
672
|
+
# earlier, the budget can only be shorter than the real lifetime of the lock);
|
|
673
|
+
# - the Redis time error is a margin: it decreases the budget;
|
|
665
674
|
ttl_shift = (
|
|
666
|
-
(yield_time - acq_process[:
|
|
675
|
+
(yield_time - acq_process[:try_start_time]) / 1_000.0 +
|
|
667
676
|
RedisQueuedLocks::Resource::REDIS_TIMESHIFT_ERROR
|
|
668
677
|
).ceil(2)
|
|
669
678
|
|
|
@@ -708,7 +717,7 @@ module RedisQueuedLocks::Acquirer::AcquireLock
|
|
|
708
717
|
instrumenter,
|
|
709
718
|
instr_sampled,
|
|
710
719
|
acq_process[:lock_info][:lock_key],
|
|
711
|
-
|
|
720
|
+
rw_mode,
|
|
712
721
|
priority,
|
|
713
722
|
acq_process[:lock_info][:ttl],
|
|
714
723
|
acq_process[:lock_info][:acq_id],
|
|
@@ -724,7 +733,7 @@ module RedisQueuedLocks::Acquirer::AcquireLock
|
|
|
724
733
|
instrumenter,
|
|
725
734
|
instr_sampled,
|
|
726
735
|
acq_process[:lock_info][:lock_key],
|
|
727
|
-
|
|
736
|
+
rw_mode,
|
|
728
737
|
priority,
|
|
729
738
|
acq_process[:lock_info][:ttl],
|
|
730
739
|
acq_process[:lock_info][:acq_id],
|
|
@@ -755,10 +764,10 @@ module RedisQueuedLocks::Acquirer::AcquireLock
|
|
|
755
764
|
acq_time = ((clock_gettime - acq_start_time) / 1_000.0).ceil(2)
|
|
756
765
|
LogVisitor.lock_obtaining_failed(
|
|
757
766
|
logger, log_sampled, lock_key, queue_ttl, acquirer_id, host_id,
|
|
758
|
-
acq_time, access_strategy,
|
|
767
|
+
acq_time, access_strategy, rw_mode, priority, acq_process[:result]
|
|
759
768
|
)
|
|
760
769
|
InstrVisitor.lock_obtaining_failed(
|
|
761
|
-
instrumenter, instr_sampled, lock_key,
|
|
770
|
+
instrumenter, instr_sampled, lock_key, rw_mode, priority, lock_ttl, acquirer_id,
|
|
762
771
|
host_id, Time.now.to_f, acq_time, acq_process[:result], instrument
|
|
763
772
|
)
|
|
764
773
|
{ ok: false, result: acq_process[:result] } #: { ok: bool, result: Symbol }
|
|
@@ -780,10 +789,10 @@ module RedisQueuedLocks::Acquirer::AcquireLock
|
|
|
780
789
|
acq_time = ((clock_gettime - acq_start_time) / 1_000.0).ceil(2)
|
|
781
790
|
LogVisitor.lock_obtaining_failed(
|
|
782
791
|
logger, log_sampled, lock_key, queue_ttl, acquirer_id, host_id,
|
|
783
|
-
acq_time, access_strategy,
|
|
792
|
+
acq_time, access_strategy, rw_mode, priority, acq_process[:result]
|
|
784
793
|
)
|
|
785
794
|
InstrVisitor.lock_obtaining_failed(
|
|
786
|
-
instrumenter, instr_sampled, lock_key,
|
|
795
|
+
instrumenter, instr_sampled, lock_key, rw_mode, priority, lock_ttl, acquirer_id,
|
|
787
796
|
host_id, Time.now.to_f, acq_time, acq_process[:result], instrument
|
|
788
797
|
)
|
|
789
798
|
end
|
|
@@ -26,7 +26,7 @@ module RedisQueuedLocks::Acquirer::ExtendLockTTL
|
|
|
26
26
|
# @param lock_name [String]
|
|
27
27
|
# @param milliseconds [Integer]
|
|
28
28
|
# How many milliseconds should be added: a positive Integer.
|
|
29
|
-
# @param
|
|
29
|
+
# @param rw_mode [Symbol]
|
|
30
30
|
# - `:write` - extends the write lock (of any acquirer);
|
|
31
31
|
# - `:read` - extends the read lock of the given acquirer (other read locks are not affected)
|
|
32
32
|
# or all live read locks of the lock (see `all_read_locks`);
|
|
@@ -52,13 +52,13 @@ module RedisQueuedLocks::Acquirer::ExtendLockTTL
|
|
|
52
52
|
#
|
|
53
53
|
# @api private
|
|
54
54
|
# @since 1.0.0
|
|
55
|
-
# @version 1.
|
|
55
|
+
# @version 1.23.0
|
|
56
56
|
# rubocop:disable Metrics/MethodLength
|
|
57
57
|
def extend_lock_ttl(
|
|
58
58
|
redis_client,
|
|
59
59
|
lock_name,
|
|
60
60
|
milliseconds,
|
|
61
|
-
|
|
61
|
+
rw_mode,
|
|
62
62
|
all_read_locks,
|
|
63
63
|
acquirer_id,
|
|
64
64
|
lock_index_enabled,
|
|
@@ -74,13 +74,13 @@ module RedisQueuedLocks::Acquirer::ExtendLockTTL
|
|
|
74
74
|
instr_sampler,
|
|
75
75
|
instr_sample_this
|
|
76
76
|
)
|
|
77
|
-
case
|
|
77
|
+
case rw_mode # NOTE: (steep) case/when narrows `Symbol` to `RQL::readWriteMode` below
|
|
78
78
|
when :read, :write then nil
|
|
79
79
|
else
|
|
80
80
|
raise(
|
|
81
81
|
RedisQueuedLocks::ArgumentError,
|
|
82
|
-
"`:
|
|
83
|
-
"got #{
|
|
82
|
+
"`:rw_mode` argument should be `:read` or `:write`, " \
|
|
83
|
+
"got #{rw_mode.inspect}."
|
|
84
84
|
)
|
|
85
85
|
end
|
|
86
86
|
|
|
@@ -92,7 +92,7 @@ module RedisQueuedLocks::Acquirer::ExtendLockTTL
|
|
|
92
92
|
)
|
|
93
93
|
end
|
|
94
94
|
|
|
95
|
-
if
|
|
95
|
+
if rw_mode == :read && all_read_locks != true && all_read_locks != false
|
|
96
96
|
raise(
|
|
97
97
|
RedisQueuedLocks::ArgumentError,
|
|
98
98
|
"`:all_read_locks` argument should be a boolean, got #{all_read_locks.inspect}."
|
|
@@ -103,7 +103,7 @@ module RedisQueuedLocks::Acquirer::ExtendLockTTL
|
|
|
103
103
|
|
|
104
104
|
ext_start_time = clock_gettime
|
|
105
105
|
result = fully_extend_lock_ttl(
|
|
106
|
-
redis_client, lock_name, lock_key, milliseconds,
|
|
106
|
+
redis_client, lock_name, lock_key, milliseconds, rw_mode, all_read_locks,
|
|
107
107
|
acquirer_id, lock_index_enabled
|
|
108
108
|
)
|
|
109
109
|
time_at = Time.now.to_f
|
|
@@ -129,7 +129,7 @@ module RedisQueuedLocks::Acquirer::ExtendLockTTL
|
|
|
129
129
|
logger.debug do
|
|
130
130
|
"[redis_queued_locks.extend_lock_ttl] " \
|
|
131
131
|
"lock_key => '#{lock_key}' " \
|
|
132
|
-
"rw_mode => '#{
|
|
132
|
+
"rw_mode => '#{rw_mode}' " \
|
|
133
133
|
"all_read_locks => #{all_read_locks} " \
|
|
134
134
|
"ext_ttl => #{milliseconds} " \
|
|
135
135
|
"extended_locks_count => #{extended_locks_count} " \
|
|
@@ -141,7 +141,7 @@ module RedisQueuedLocks::Acquirer::ExtendLockTTL
|
|
|
141
141
|
run_non_critical do
|
|
142
142
|
instrumenter.notify('redis_queued_locks.extend_lock_ttl', {
|
|
143
143
|
lock_key: lock_key,
|
|
144
|
-
rw_mode
|
|
144
|
+
rw_mode:,
|
|
145
145
|
all_read_locks: all_read_locks,
|
|
146
146
|
ext_ttl: milliseconds,
|
|
147
147
|
extended_locks_count: extended_locks_count,
|
|
@@ -163,7 +163,7 @@ module RedisQueuedLocks::Acquirer::ExtendLockTTL
|
|
|
163
163
|
# @param lock_name [String]
|
|
164
164
|
# @param lock_key [String]
|
|
165
165
|
# @param milliseconds [Integer]
|
|
166
|
-
# @param
|
|
166
|
+
# @param rw_mode [Symbol]
|
|
167
167
|
# @param all_read_locks [Boolean]
|
|
168
168
|
# @param acquirer_id [String]
|
|
169
169
|
# @param lock_index_enabled [Boolean]
|
|
@@ -177,12 +177,12 @@ module RedisQueuedLocks::Acquirer::ExtendLockTTL
|
|
|
177
177
|
lock_name,
|
|
178
178
|
lock_key,
|
|
179
179
|
milliseconds,
|
|
180
|
-
|
|
180
|
+
rw_mode,
|
|
181
181
|
all_read_locks,
|
|
182
182
|
acquirer_id,
|
|
183
183
|
lock_index_enabled
|
|
184
184
|
)
|
|
185
|
-
if
|
|
185
|
+
if rw_mode == :read
|
|
186
186
|
# NOTE: (RW) all live read locks of the lock
|
|
187
187
|
if all_read_locks
|
|
188
188
|
return extend_all_read_locks_ttl(
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# @api private
|
|
4
|
+
# @since 1.23.0
|
|
5
|
+
# rubocop:disable Metrics/ModuleLength
|
|
6
|
+
module RedisQueuedLocks::Acquirer::LockSeries::InstrVisitor
|
|
7
|
+
# rubocop:disable Metrics/ClassLength
|
|
8
|
+
class << self
|
|
9
|
+
# @param instrumenter [#notify]
|
|
10
|
+
# @param instr_sampled [Boolean]
|
|
11
|
+
# @param lock_key [String] The lock of the series.
|
|
12
|
+
# @param lock_keys [Array<String>] All locks of the series.
|
|
13
|
+
# @param rw_mode [Symbol] The mode of the lock series (`:read` or `:write`).
|
|
14
|
+
# @param priority [Integer] The lock request priority of the series.
|
|
15
|
+
# @param ttl [Integer]
|
|
16
|
+
# @param acq_id [String]
|
|
17
|
+
# @param hst_id [String]
|
|
18
|
+
# @param ts [Numeric]
|
|
19
|
+
# @param acq_time [Numeric]
|
|
20
|
+
# @param instrument [NilClass,Any]
|
|
21
|
+
# @return [void]
|
|
22
|
+
#
|
|
23
|
+
# @api private
|
|
24
|
+
# @since 1.23.0
|
|
25
|
+
def lock_series_intermediate_lock_obtained(
|
|
26
|
+
instrumenter,
|
|
27
|
+
instr_sampled,
|
|
28
|
+
lock_key,
|
|
29
|
+
lock_keys,
|
|
30
|
+
rw_mode,
|
|
31
|
+
priority,
|
|
32
|
+
ttl,
|
|
33
|
+
acq_id,
|
|
34
|
+
hst_id,
|
|
35
|
+
ts,
|
|
36
|
+
acq_time,
|
|
37
|
+
instrument
|
|
38
|
+
)
|
|
39
|
+
return unless instr_sampled
|
|
40
|
+
instrumenter.notify('redis_queued_locks.lock_series_intermediate_lock_obtained', {
|
|
41
|
+
lock_key:, lock_keys:, rw_mode:, priority:, ttl:, acq_id:, hst_id:, ts:, acq_time:,
|
|
42
|
+
instrument:
|
|
43
|
+
}) rescue nil
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# @param instrumenter [#notify]
|
|
47
|
+
# @param instr_sampled [Boolean]
|
|
48
|
+
# @param lock_key [String] The lock of the series.
|
|
49
|
+
# @param lock_keys [Array<String>] All locks of the series.
|
|
50
|
+
# @param rw_mode [Symbol] The mode of the lock series (`:read` or `:write`).
|
|
51
|
+
# @param priority [Integer] The lock request priority of the series.
|
|
52
|
+
# @param ttl [Integer]
|
|
53
|
+
# @param acq_id [String]
|
|
54
|
+
# @param hst_id [String]
|
|
55
|
+
# @param ts [Numeric]
|
|
56
|
+
# @param acq_time [Numeric]
|
|
57
|
+
# @param instrument [NilClass,Any]
|
|
58
|
+
# @return [void]
|
|
59
|
+
#
|
|
60
|
+
# @api private
|
|
61
|
+
# @since 1.23.0
|
|
62
|
+
def lock_series_lock_obtained(
|
|
63
|
+
instrumenter,
|
|
64
|
+
instr_sampled,
|
|
65
|
+
lock_key,
|
|
66
|
+
lock_keys,
|
|
67
|
+
rw_mode,
|
|
68
|
+
priority,
|
|
69
|
+
ttl,
|
|
70
|
+
acq_id,
|
|
71
|
+
hst_id,
|
|
72
|
+
ts,
|
|
73
|
+
acq_time,
|
|
74
|
+
instrument
|
|
75
|
+
)
|
|
76
|
+
return unless instr_sampled
|
|
77
|
+
instrumenter.notify('redis_queued_locks.lock_series_lock_obtained', {
|
|
78
|
+
lock_key:, lock_keys:, rw_mode:, priority:, ttl:, acq_id:, hst_id:, ts:, acq_time:,
|
|
79
|
+
instrument:
|
|
80
|
+
}) rescue nil
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# @param instrumenter [#notify]
|
|
84
|
+
# @param instr_sampled [Boolean]
|
|
85
|
+
# @param lock_key [String] The lock that blocks the series.
|
|
86
|
+
# @param lock_keys [Array<String>] All locks of the series.
|
|
87
|
+
# @param rw_mode [Symbol] The mode of the lock series (`:read` or `:write`).
|
|
88
|
+
# @param priority [Integer] The lock request priority of the series.
|
|
89
|
+
# @param ttl [Integer]
|
|
90
|
+
# @param acq_id [String]
|
|
91
|
+
# @param hst_id [String]
|
|
92
|
+
# @param ts [Numeric]
|
|
93
|
+
# @param acq_time [Numeric]
|
|
94
|
+
# @param result [Symbol] The failure result (`:timeout_reached`, `:retry_limit_reached`, ...).
|
|
95
|
+
# @param instrument [NilClass,Any]
|
|
96
|
+
# @return [void]
|
|
97
|
+
#
|
|
98
|
+
# @api private
|
|
99
|
+
# @since 1.23.0
|
|
100
|
+
def lock_series_lock_obtaining_failed(
|
|
101
|
+
instrumenter,
|
|
102
|
+
instr_sampled,
|
|
103
|
+
lock_key,
|
|
104
|
+
lock_keys,
|
|
105
|
+
rw_mode,
|
|
106
|
+
priority,
|
|
107
|
+
ttl,
|
|
108
|
+
acq_id,
|
|
109
|
+
hst_id,
|
|
110
|
+
ts,
|
|
111
|
+
acq_time,
|
|
112
|
+
result,
|
|
113
|
+
instrument
|
|
114
|
+
)
|
|
115
|
+
return unless instr_sampled
|
|
116
|
+
instrumenter.notify('redis_queued_locks.lock_series_lock_obtaining_failed', {
|
|
117
|
+
lock_key:, lock_keys:, rw_mode:, priority:, ttl:, acq_id:, hst_id:, ts:, acq_time:, result:,
|
|
118
|
+
instrument:
|
|
119
|
+
}) rescue nil
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# @param instrumenter [#notify]
|
|
123
|
+
# @param instr_sampled [Boolean]
|
|
124
|
+
# @param lock_keys [Array<String>]
|
|
125
|
+
# @param rw_mode [Symbol] The mode of the lock series (`:read` or `:write`).
|
|
126
|
+
# @param priority [Integer] The lock request priority of the series.
|
|
127
|
+
# @param ttl [Integer]
|
|
128
|
+
# @param acq_id [String]
|
|
129
|
+
# @param hst_id [String]
|
|
130
|
+
# @param ts [Numeric]
|
|
131
|
+
# @param acq_time [Numeric]
|
|
132
|
+
# @param reentrant_lock_keys [Array<String>]
|
|
133
|
+
# The locks of the series that are obtained by the outer logic of the current acquirer.
|
|
134
|
+
# @param instrument [NilClass,Any]
|
|
135
|
+
# @return [void]
|
|
136
|
+
#
|
|
137
|
+
# @api private
|
|
138
|
+
# @since 1.23.0
|
|
139
|
+
def lock_series_obtained(
|
|
140
|
+
instrumenter,
|
|
141
|
+
instr_sampled,
|
|
142
|
+
lock_keys,
|
|
143
|
+
rw_mode,
|
|
144
|
+
priority,
|
|
145
|
+
ttl,
|
|
146
|
+
acq_id,
|
|
147
|
+
hst_id,
|
|
148
|
+
ts,
|
|
149
|
+
acq_time,
|
|
150
|
+
reentrant_lock_keys,
|
|
151
|
+
instrument
|
|
152
|
+
)
|
|
153
|
+
return unless instr_sampled
|
|
154
|
+
instrumenter.notify('redis_queued_locks.lock_series_obtained', {
|
|
155
|
+
lock_keys:, rw_mode:, priority:, ttl:, acq_id:, hst_id:, ts:, acq_time:,
|
|
156
|
+
reentrant_lock_keys:, instrument:
|
|
157
|
+
}) rescue nil
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# @param instrumenter [#notify]
|
|
161
|
+
# @param instr_sampled [Boolean]
|
|
162
|
+
# @param lock_keys [Array<String>]
|
|
163
|
+
# @param rw_mode [Symbol] The mode of the lock series (`:read` or `:write`).
|
|
164
|
+
# @param priority [Integer] The lock request priority of the series.
|
|
165
|
+
# @param ttl [Integer]
|
|
166
|
+
# @param acq_id [String]
|
|
167
|
+
# @param hst_id [String]
|
|
168
|
+
# @param ts [Numeric]
|
|
169
|
+
# @param acq_time [Numeric]
|
|
170
|
+
# @param hold_time [Numeric]
|
|
171
|
+
# @param reentrant_lock_keys [Array<String>]
|
|
172
|
+
# The locks of the series that are obtained by the outer logic of the current acquirer.
|
|
173
|
+
# @param instrument [NilClass,Any]
|
|
174
|
+
# @return [void]
|
|
175
|
+
#
|
|
176
|
+
# @api private
|
|
177
|
+
# @since 1.23.0
|
|
178
|
+
def lock_series_hold_and_release(
|
|
179
|
+
instrumenter,
|
|
180
|
+
instr_sampled,
|
|
181
|
+
lock_keys,
|
|
182
|
+
rw_mode,
|
|
183
|
+
priority,
|
|
184
|
+
ttl,
|
|
185
|
+
acq_id,
|
|
186
|
+
hst_id,
|
|
187
|
+
ts,
|
|
188
|
+
acq_time,
|
|
189
|
+
hold_time,
|
|
190
|
+
reentrant_lock_keys,
|
|
191
|
+
instrument
|
|
192
|
+
)
|
|
193
|
+
return unless instr_sampled
|
|
194
|
+
instrumenter.notify('redis_queued_locks.lock_series_hold_and_release', {
|
|
195
|
+
lock_keys:, rw_mode:, priority:, hold_time:, ttl:, acq_id:, hst_id:, ts:, acq_time:,
|
|
196
|
+
reentrant_lock_keys:, instrument:
|
|
197
|
+
}) rescue nil
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# @param instrumenter [#notify]
|
|
201
|
+
# @param instr_sampled [Boolean]
|
|
202
|
+
# @param lock_keys [Array<String>]
|
|
203
|
+
# @param rw_mode [Symbol] The mode of the lock series (`:read` or `:write`).
|
|
204
|
+
# @param priority [Integer] The lock request priority of the series.
|
|
205
|
+
# @param ttl [Integer]
|
|
206
|
+
# @param acq_id [String]
|
|
207
|
+
# @param hst_id [String]
|
|
208
|
+
# @param ts [Numeric]
|
|
209
|
+
# @param acq_time [Numeric]
|
|
210
|
+
# @param result [Symbol] The failure result (`:timeout_reached`, `:retry_limit_reached`, ...).
|
|
211
|
+
# @param failed_lock_key [String,NilClass]
|
|
212
|
+
# The lock of the series that blocks the series (`nil`: unknown, an attempt was not finished
|
|
213
|
+
# or some lock state was changed during the attempt).
|
|
214
|
+
# @param instrument [NilClass,Any]
|
|
215
|
+
# @return [void]
|
|
216
|
+
#
|
|
217
|
+
# @api private
|
|
218
|
+
# @since 1.23.0
|
|
219
|
+
def lock_series_obtaining_failed(
|
|
220
|
+
instrumenter,
|
|
221
|
+
instr_sampled,
|
|
222
|
+
lock_keys,
|
|
223
|
+
rw_mode,
|
|
224
|
+
priority,
|
|
225
|
+
ttl,
|
|
226
|
+
acq_id,
|
|
227
|
+
hst_id,
|
|
228
|
+
ts,
|
|
229
|
+
acq_time,
|
|
230
|
+
result,
|
|
231
|
+
failed_lock_key,
|
|
232
|
+
instrument
|
|
233
|
+
)
|
|
234
|
+
return unless instr_sampled
|
|
235
|
+
instrumenter.notify('redis_queued_locks.lock_series_obtaining_failed', {
|
|
236
|
+
lock_keys:, rw_mode:, priority:, ttl:, acq_id:, hst_id:, ts:, acq_time:, result:,
|
|
237
|
+
failed_lock_key:, instrument:
|
|
238
|
+
}) rescue nil
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
# rubocop:enable Metrics/ClassLength
|
|
242
|
+
end
|
|
243
|
+
# rubocop:enable Metrics/ModuleLength
|