redis_queued_locks 1.7.0 → 1.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cd303479ce60c268e630d4ad770657cbe0223cffcb9990d31a9bb3de92d80843
4
- data.tar.gz: 2a19bfed90da70fa8c49bf069a2acd110d3840eeb78f1f21767416c28e5bc6b7
3
+ metadata.gz: 7f8dd117ee12f1f598da555d02516bb950a2d9640b075a048612726b7a88a6ad
4
+ data.tar.gz: c0a5ac4a4dcb6f3b448dc23ffa8d0e0e13a726d50bdd98fc40193704aa6f967d
5
5
  SHA512:
6
- metadata.gz: 0c2d6c956bfc7227cd45c33c8b983ae759e13bf7149121c272821922d66a4be73b57b344e2042f86d0391acbe92de794013e0a67ce6157b402c6a0ca0a3a1740
7
- data.tar.gz: e00ec46afd8e5d8ebef469c0a5d86a026562f8060e8abc95c4f3e89aa9351dc8961fe2d9d181aa4e8203056c74fb4aa8c4043f925b93a5b477c44541eec5ad9f
6
+ metadata.gz: b35d0ef98da0e1ec2c2368b36064eb0501b45d26aaa1b7204230692a41025583366ce181b85eec09cff2d6fe4e93ec146280db78e08f8cbb232a559b91f6d489
7
+ data.tar.gz: 4776dd89a7bf1e27476877465faf3240988929efe398090fa4b8b4f604a976a861558e6f606278b91c2c95530be6c5205f8245c887befe92a75d4efde31820dc
data/CHANGELOG.md CHANGED
@@ -1,8 +1,16 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [1.8.0] - 2024-06-13
4
+ ### Added
5
+ - A configurable option that enables the adding additional lock/queue data to "Acquirement Timeout"-related error messages for better debugging;
6
+ - Configurable option is used beacuse of the extra error data requires some additional Redis requests that can be costly for memory/cpu/etc resources;
7
+ - An ability to get the current acquirer id (`RedisQueuedLocks::Client#current_acquirer_id`);
8
+ ### Changed
9
+ - Added additional lock information to some exceptions that does not require extra Redis requests;
10
+
3
11
  ## [1.7.0] - 2024-06-12
4
12
  ### Added
5
- - New feature: **Lock Access Strategy**: you can obtain a lock in different ways: `queued` (classic queued FIFO), `random` (get the lock immideatly if lock is free), and soon: `lifo` and `barrier`;
13
+ - New feature: **Lock Access Strategy**: you can obtain a lock in different ways: `queued` (classic queued FIFO), `random` (get the lock immideatly if lock is free):
6
14
  - `:queued` is used by default (classic `redis_queued_locks` behavior);
7
15
  - `:random`: obtain a lock without checking the positions in the queue => if lock is free to obtain - it will be obtained;
8
16
  ### Changed
data/README.md CHANGED
@@ -34,6 +34,7 @@ Provides flexible invocation flow, parametrized limits (lock request ttl, lock t
34
34
  - [locks_info](#locks_info---get-list-of-locks-with-their-info)
35
35
  - [queues_info](#queues_info---get-list-of-queues-with-their-info)
36
36
  - [clear_dead_requests](#clear_dead_requests)
37
+ - [current_acquirer_id](#current_acquirer_id)
37
38
  - [Lock Access Strategies](#lock-access-strategies)
38
39
  - [queued](#lock-access-strategies)
39
40
  - [random](#lock-access-strategies)
@@ -157,6 +158,29 @@ clinet = RedisQueuedLocks::Client.new(redis_client) do |config|
157
158
  # - should be all blocks of code are timed by default;
158
159
  config.is_timed_by_default = false
159
160
 
161
+ # (boolean) (default: false)
162
+ # - When the lock acquirement try reached the acquirement time limit (:timeout option) the
163
+ # `RedisQueuedLocks::LockAcquirementTimeoutError` is raised (when `raise_errors` option
164
+ # of the #lock method is set to `true`). The error message contains the lock key name and
165
+ # the timeout value).
166
+ # - <true> option adds the additional details to the error message:
167
+ # - current lock queue state (you can see which acquirer blocks your request and
168
+ # how much acquirers are in queue);
169
+ # - current lock data stored inside (for example: you can check the current acquirer and
170
+ # the lock meta state if you store some additional data there);
171
+ # - Realized as an option because of the additional lock data requires two additional Redis
172
+ # queries: (1) get the current lock from redis and (2) fetch the lock queue state;
173
+ # - These two additional Redis queries has async nature so you can receive
174
+ # inconsistent data of the lock and of the lock queue in your error emssage because:
175
+ # - required lock can be released after the error moment and before the error message build;
176
+ # - required lock can be obtained by other process after the error moment and
177
+ # before the error message build;
178
+ # - required lock queue can reach a state when the blocking acquirer start to obtain the lock
179
+ # and moved from the lock queue after the error moment and before the error message build;
180
+ # - You should consider the async nature of this error message and should use received data
181
+ # from error message correspondingly;
182
+ config.detailed_acq_timeout_error = false
183
+
160
184
  # (symbol) (default: :queued)
161
185
  # - Defines the way in which the lock should be obitained;
162
186
  # - By default it is configured to obtain a lock in classic `queued` way:
@@ -316,6 +340,7 @@ end
316
340
  - [locks_info](#locks_info---get-list-of-locks-with-their-info)
317
341
  - [queues_info](#queues_info---get-list-of-queues-with-their-info)
318
342
  - [clear_dead_requests](#clear_dead_requests)
343
+ - [current_acquirer_id](#current_acquirer_id)
319
344
 
320
345
  ---
321
346
 
@@ -348,6 +373,7 @@ def lock(
348
373
  access_strategy: config[:default_access_strategy],
349
374
  identity: uniq_identity, # (attr_accessor) calculated during client instantiation via config[:uniq_identifier] proc;
350
375
  meta: nil,
376
+ detailed_acq_timeout_error: config[:detailed_acq_timeout_error],
351
377
  instrument: nil,
352
378
  instrumenter: config[:instrumenter],
353
379
  logger: config[:logger],
@@ -433,6 +459,25 @@ def lock(
433
459
  - A custom metadata wich will be passed to the lock data in addition to the existing data;
434
460
  - Custom metadata can not contain reserved lock data keys (such as `lock_key`, `acq_id`, `ts`, `ini_ttl`, `rem_ttl`);
435
461
  - `nil` by default (means "no metadata");
462
+ - `detailed_acq_timeout_error` - (optional) `[Boolean]`
463
+ - When the lock acquirement try reached the acquirement time limit (:timeout option) the
464
+ `RedisQueuedLocks::LockAcquirementTimeoutError` is raised (when `raise_errors` option
465
+ set to `true`). The error message contains the lock key name and the timeout value).
466
+ - <true> option adds the additional details to the error message:
467
+ - current lock queue state (you can see which acquirer blocks your request and how much acquirers are in queue);
468
+ - current lock data stored inside (for example: you can check the current acquirer and the lock meta state if you store some additional data there);
469
+ - Realized as an option because of the additional lock data requires two additional Redis
470
+ queries: (1) get the current lock from redis and (2) fetch the lock queue state;
471
+ - These two additional Redis queries has async nature so you can receive
472
+ inconsistent data of the lock and of the lock queue in your error emssage because:
473
+ - required lock can be released after the error moment and before the error message build;
474
+ - required lock can be obtained by other process after the error moment and
475
+ before the error message build;
476
+ - required lock queue can reach a state when the blocking acquirer start to obtain the lock
477
+ and moved from the lock queue after the error moment and before the error message build;
478
+ - You should consider the async nature of this error message and should use received data
479
+ from error message correspondingly;
480
+ - pre-configred in `config[:detailed_acq_timeout_error]`;
436
481
  - `logger` - (optional) `[::Logger,#debug]`
437
482
  - Logger object used for loggin internal mutation oeprations and opertioan results / process progress;
438
483
  - pre-configured in `config[:logger]` with void logger `RedisQueuedLocks::Logging::VoidLogger`;
@@ -725,6 +770,7 @@ def lock!(
725
770
  fail_fast: false,
726
771
  identity: uniq_identity,
727
772
  meta: nil,
773
+ detailed_acq_timeout_error: config[:detailed_acq_timeout_error]
728
774
  logger: config[:logger],
729
775
  log_lock_try: config[:log_lock_try],
730
776
  instrument: nil,
@@ -1319,8 +1365,45 @@ rql.clear_dead_requests(dead_ttl: 60 * 60 * 1000) # 1 hour in milliseconds
1319
1365
 
1320
1366
  ---
1321
1367
 
1368
+ #### #current_acquirer_id
1369
+
1370
+ - get the current acquirer identifier in RQL notation that you can use for debugging purposes during the lock analyzation;
1371
+ - acquirer identifier format:
1372
+ ```ruby
1373
+ "rql:acq:#{process_id}/#{thread_id}/#{fiber_id}/#{ractor_id}/#{identity}"
1374
+ ```
1375
+ - because of the moment that `#lock`/`#lock!` gives you a possibility to customize `process_id`,
1376
+ `fiber_id`, `thread_id`, `ractor_id` and `unique identity` identifiers the `#current_acquirer_id` method provides this possibility too;
1377
+
1378
+ Accepts:
1379
+
1380
+ - `process_id:` - (optional) `[Integer,Any]`
1381
+ - `::Process.pid` by default;
1382
+ - `thread_id:` - (optional) `[Integer,Any]`;
1383
+ - `::Thread.current.object_id` by default;
1384
+ - `fiber_id:` - (optional) `[Integer,Any]`;
1385
+ - `::Fiber.current.object_id` by default;
1386
+ - `ractor_id:` - (optional) `[Integer,Any]`;
1387
+ - `::Ractor.current.object_id` by default;
1388
+ - `identity:` - (optional) `[String,Any]`;
1389
+ - this value is calculated once during `RedisQueuedLock::Client` instantiation and stored in `@uniq_identity`;
1390
+ - this value can be accessed from `RedisQueuedLock::Client#uniq_identity`;
1391
+ - [Configuration](#configuration) documentation: see `config[:uniq_identifier]`;
1392
+ - [#lock](#lock---obtain-a-lock) method documentation: see `uniq_identifier`;
1393
+
1394
+ ```ruby
1395
+ rql.current_acquirer_id
1396
+
1397
+ # =>
1398
+ "rql:acq:38529/4500/4520/4360/66093702f24a3129"
1399
+ ```
1400
+
1401
+ ---
1402
+
1322
1403
  ## Lock Access Strategies
1323
1404
 
1405
+ <sup>\[[back to top](#table-of-contents)\]</sup>
1406
+
1324
1407
  - **this documentation section is in progress**;
1325
1408
  - (little details for a context of the current implementation and feautres):
1326
1409
  - defines the way in which the lock should be obitained;
@@ -3,29 +3,63 @@
3
3
  # @api private
4
4
  # @since 1.0.0
5
5
  module RedisQueuedLocks::Acquier::AcquireLock::WithAcqTimeout
6
+ # @param redis [RedisClient]
7
+ # Redis connection manager required for additional data extraction for error message.
6
8
  # @param timeout [NilClass,Integer]
7
9
  # Time period after which the logic will fail with timeout error.
8
10
  # @param lock_key [String]
9
- # Lock name.
11
+ # Lock name in RQL notation (rql:lock:some-lock-name).
12
+ # @param lock_name [String]
13
+ # Original lock name passed by the businessl logic (without RQL notaiton parts).
10
14
  # @param raise_errors [Boolean]
11
15
  # Raise erros on exceptional cases.
16
+ # @param detailed_acq_timeout_error [Boolean]
17
+ # Add additional error data about lock queue and required lock to the timeout error or not.
12
18
  # @option on_timeout [Proc,NilClass]
13
19
  # Callback invoked on Timeout::Error.
14
20
  # @return [Any]
15
21
  #
16
22
  # @api private
17
23
  # @since 1.0.0
18
- def with_acq_timeout(timeout, lock_key, raise_errors, on_timeout: nil, &block)
24
+ # @version 1.8.0
25
+ def with_acq_timeout(
26
+ redis,
27
+ timeout,
28
+ lock_key,
29
+ lock_name,
30
+ raise_errors,
31
+ detailed_acq_timeout_error,
32
+ on_timeout: nil,
33
+ &block
34
+ )
19
35
  ::Timeout.timeout(timeout, &block)
20
36
  rescue ::Timeout::Error
21
37
  on_timeout.call unless on_timeout == nil
22
38
 
23
39
  if raise_errors
24
- raise(
25
- RedisQueuedLocks::LockAcquiermentTimeoutError,
26
- "Failed to acquire the lock \"#{lock_key}\" " \
27
- "for the given timeout (#{timeout} seconds)."
28
- )
40
+ if detailed_acq_timeout_error
41
+ # TODO: rewrite these invocations to separated inner-AcquireLock-related modules
42
+ # in order to remove any dependencies from the other public RQL commands cuz
43
+ # all AcquireLock logic elements should be fully independent from others as a core;
44
+ lock_info = RedisQueuedLocks::Acquier::LockInfo.lock_info(redis, lock_name)
45
+ queue_info = RedisQueuedLocks::Acquier::QueueInfo.queue_info(redis, lock_name)
46
+
47
+ # rubocop:disable Metrics/BlockNesting
48
+ raise(
49
+ RedisQueuedLocks::LockAcquiermentTimeoutError,
50
+ "Failed to acquire the lock \"#{lock_key}\" " \
51
+ "for the given <#{timeout} seconds> timeout. Details: " \
52
+ "<Lock Data> => #{lock_info ? lock_info.inspect : '<no_data>'}; " \
53
+ "<Queue Data> => #{queue_info ? queue_info.inspect : '<no_data>'};"
54
+ )
55
+ # rubocop:enable Metrics/BlockNesting
56
+ else
57
+ raise(
58
+ RedisQueuedLocks::LockAcquiermentTimeoutError,
59
+ "Failed to acquire the lock \"#{lock_key}\" " \
60
+ "for the given <#{timeout} seconds> timeout."
61
+ )
62
+ end
29
63
  end
30
64
  end
31
65
  end
@@ -25,6 +25,7 @@ module RedisQueuedLocks::Acquier::AcquireLock::YieldExpire
25
25
  # @param ttl [Integer,NilClass] Lock's time to live (in ms). Nil means "without timeout".
26
26
  # @param queue_ttl [Integer] Lock request lifetime.
27
27
  # @param block [Block] Custom logic that should be invoked unter the obtained lock.
28
+ # @param meta [NilClass,Hash<String|Symbol,Any>] Custom metadata wich is passed to the lock data;
28
29
  # @param log_sampled [Boolean] Should the logic be logged or not.
29
30
  # @param instr_sampled [Boolean] Should the logic be instrumented or not.
30
31
  # @param should_expire [Boolean] Should the lock be expired after the block invocation.
@@ -35,7 +36,7 @@ module RedisQueuedLocks::Acquier::AcquireLock::YieldExpire
35
36
  #
36
37
  # @api private
37
38
  # @since 1.3.0
38
- # @version 1.7.0
39
+ # @version 1.8.0
39
40
  # rubocop:disable Metrics/MethodLength
40
41
  def yield_expire(
41
42
  redis,
@@ -47,6 +48,7 @@ module RedisQueuedLocks::Acquier::AcquireLock::YieldExpire
47
48
  ttl_shift,
48
49
  ttl,
49
50
  queue_ttl,
51
+ meta,
50
52
  log_sampled,
51
53
  instr_sampled,
52
54
  should_expire,
@@ -62,7 +64,7 @@ module RedisQueuedLocks::Acquier::AcquireLock::YieldExpire
62
64
  end
63
65
 
64
66
  if timed && ttl != nil
65
- yield_with_timeout(timeout, lock_key, ttl, &block)
67
+ yield_with_timeout(timeout, lock_key, ttl, acquier_id, meta, &block)
66
68
  else
67
69
  yield
68
70
  end
@@ -97,18 +99,24 @@ module RedisQueuedLocks::Acquier::AcquireLock::YieldExpire
97
99
  # @param timeout [Float]
98
100
  # @parma lock_key [String]
99
101
  # @param lock_ttl [Integer,NilClass]
102
+ # @param acquier_id [String]
103
+ # @param meta [NilClass,Hash<Symbol|String,Any>]
100
104
  # @param block [Blcok]
101
105
  # @return [Any]
102
106
  #
103
107
  # @api private
104
108
  # @since 1.3.0
105
- def yield_with_timeout(timeout, lock_key, lock_ttl, &block)
109
+ # @version 1.8.0
110
+ def yield_with_timeout(timeout, lock_key, lock_ttl, acquier_id, meta, &block)
106
111
  ::Timeout.timeout(timeout, &block)
107
112
  rescue ::Timeout::Error
108
113
  raise(
109
114
  RedisQueuedLocks::TimedLockTimeoutError,
110
- "Passed <timed> block of code exceeded " \
111
- "the lock TTL (lock: \"#{lock_key}\", ttl: #{lock_ttl})"
115
+ "Passed <timed> block of code exceeded the lock TTL " \
116
+ "(lock: \"#{lock_key}\", " \
117
+ "ttl: #{lock_ttl}, " \
118
+ "meta: #{meta ? meta.inspect : '<no-meta>'}, " \
119
+ "acq_id: \"#{acquier_id}\")"
112
120
  )
113
121
  end
114
122
  end
@@ -69,6 +69,10 @@ module RedisQueuedLocks::Acquier::AcquireLock
69
69
  # @option meta [NilClass,Hash<String|Symbol,Any>]
70
70
  # - A custom metadata wich will be passed to the lock data in addition to the existing data;
71
71
  # - Metadata can not contain reserved lock data keys;
72
+ # @option detailed_acq_timeout_error [Boolean]
73
+ # - Add additional data to the acquirement timeout error such as the current lock queue state
74
+ # and the required lock state;
75
+ # - See `config[:detailed_acq_timeout_error]` for details;
72
76
  # @option logger [::Logger,#debug]
73
77
  # - Logger object used from the configuration layer (see config[:logger]);
74
78
  # - See `RedisQueuedLocks::Logging::VoidLogger` for example;
@@ -143,7 +147,7 @@ module RedisQueuedLocks::Acquier::AcquireLock
143
147
  #
144
148
  # @api private
145
149
  # @since 1.0.0
146
- # @version 1.7.0
150
+ # @version 1.8.0
147
151
  def acquire_lock(
148
152
  redis,
149
153
  lock_name,
@@ -163,6 +167,7 @@ module RedisQueuedLocks::Acquier::AcquireLock
163
167
  identity:,
164
168
  fail_fast:,
165
169
  meta:,
170
+ detailed_acq_timeout_error:,
166
171
  instrument:,
167
172
  logger:,
168
173
  log_lock_try:,
@@ -246,7 +251,8 @@ module RedisQueuedLocks::Acquier::AcquireLock
246
251
 
247
252
  acq_dequeue = proc do
248
253
  dequeue_from_lock_queue(
249
- redis, logger,
254
+ redis,
255
+ logger,
250
256
  lock_key,
251
257
  lock_key_queue,
252
258
  queue_ttl,
@@ -263,7 +269,15 @@ module RedisQueuedLocks::Acquier::AcquireLock
263
269
  )
264
270
 
265
271
  # Step 2: try to lock with timeout
266
- with_acq_timeout(timeout, lock_key, raise_errors, on_timeout: acq_dequeue) do
272
+ with_acq_timeout(
273
+ redis,
274
+ timeout,
275
+ lock_key,
276
+ lock_name,
277
+ raise_errors,
278
+ detailed_acq_timeout_error,
279
+ on_timeout: acq_dequeue
280
+ ) do
267
281
  acq_start_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC, :microsecond)
268
282
 
269
283
  # Step 2.1: cyclically try to obtain the lock
@@ -455,6 +469,7 @@ module RedisQueuedLocks::Acquier::AcquireLock
455
469
  ttl_shift,
456
470
  ttl,
457
471
  queue_ttl,
472
+ meta,
458
473
  log_sampled,
459
474
  instr_sampled,
460
475
  should_expire, # NOTE: should expire the lock after the block execution
@@ -14,6 +14,7 @@ class RedisQueuedLocks::Client
14
14
  setting :try_to_lock_timeout, 10 # NOTE: in seconds
15
15
  setting :default_lock_ttl, 5_000 # NOTE: in milliseconds
16
16
  setting :default_queue_ttl, 15 # NOTE: in seconds
17
+ setting :detailed_acq_timeout_error, false
17
18
  setting :lock_release_batch_size, 100
18
19
  setting :key_extraction_batch_size, 500
19
20
  setting :instrumenter, RedisQueuedLocks::Instrument::VoidNotifier
@@ -37,6 +38,7 @@ class RedisQueuedLocks::Client
37
38
  validate('try_to_lock_timeout') { |val| val == nil || (val.is_a?(::Integer) && val >= 0) }
38
39
  validate('default_lock_tt', :integer)
39
40
  validate('default_queue_ttl', :integer)
41
+ validate('detailed_acq_timeout_error', :boolean)
40
42
  validate('lock_release_batch_size', :integer)
41
43
  validate('instrumenter') { |val| RedisQueuedLocks::Instrument.valid_interface?(val) }
42
44
  validate('uniq_identifier', :proc)
@@ -95,6 +97,39 @@ class RedisQueuedLocks::Client
95
97
  @redis_client = redis_client
96
98
  end
97
99
 
100
+ # Retrun the current acquirer identifier.
101
+ #
102
+ # @option process_id [Integer,Any] Process identifier.
103
+ # @option thread_id [Integer,Any] Thread identifier.
104
+ # @option fiber_id [Integer,Any] Fiber identifier.
105
+ # @option ractor_id [Integer,Any] Ractor identifier.
106
+ # @option identity [String] Unique per-process string. See `config[:uniq_identifier]`.
107
+ # @return [String]
108
+ #
109
+ # @see RedisQueuedLocks::Resource.get_process_id
110
+ # @see RedisQueuedLocks::Resource.get_thread_id
111
+ # @see RedisQueuedLocks::Resource.get_fiber_id
112
+ # @see RedisQueuedLocks::Resource.get_ractor_id
113
+ # @see RedisQueuedLocks::Client#uniq_identity
114
+ #
115
+ # @api public
116
+ # @since 1.8.0
117
+ def current_acquier_id(
118
+ process_id: RedisQueuedLocks::Resource.get_process_id,
119
+ thread_id: RedisQueuedLocks::Resource.get_thread_id,
120
+ fiber_id: RedisQueuedLocks::Resource.get_fiber_id,
121
+ ractor_id: RedisQueuedLocks::Resource.get_ractor_id,
122
+ identity: uniq_identity
123
+ )
124
+ RedisQueuedLocks::Resource.acquier_identifier(
125
+ process_id,
126
+ thread_id,
127
+ fiber_id,
128
+ ractor_id,
129
+ identity
130
+ )
131
+ end
132
+
98
133
  # @param lock_name [String]
99
134
  # Lock name to be obtained.
100
135
  # @option ttl [Integer]
@@ -146,6 +181,27 @@ class RedisQueuedLocks::Client
146
181
  # @option meta [NilClass,Hash<String|Symbol,Any>]
147
182
  # - A custom metadata wich will be passed to the lock data in addition to the existing data;
148
183
  # - Metadata can not contain reserved lock data keys;
184
+ # @option detailed_acq_timeout_error [Boolean]
185
+ # - When the lock acquirement try reached the acquirement time limit (:timeout option) the
186
+ # `RedisQueuedLocks::LockAcquirementTimeoutError` is raised (when `raise_errors` option
187
+ # set to `true`). The error message contains the lock key name and the timeout value).
188
+ # - <true> option adds the additional details to the error message:
189
+ # - current lock queue state (you can see which acquirer blocks your request and
190
+ # how much acquirers are in queue);
191
+ # - current lock data stored inside (for example: you can check the current acquirer and
192
+ # the lock meta state if you store some additional data there);
193
+ # - Realized as an option because of the additional lock data requires two additional Redis
194
+ # queries: (1) get the current lock from redis and (2) fetch the lock queue state;
195
+ # - These two additional Redis queries has async nature so you can receive
196
+ # inconsistent data of the lock and of the lock queue in your error emssage because:
197
+ # - required lock can be released after the error moment and before the error message build;
198
+ # - required lock can be obtained by other process after the error moment and
199
+ # before the error message build;
200
+ # - required lock queue can reach a state when the blocking acquirer start to obtain the lock
201
+ # and moved from the lock queue after the error moment and before the error message build;
202
+ # - You should consider the async nature of this error message and should use received data
203
+ # from error message correspondingly;
204
+ # - pre-configred in `config[:detailed_acq_timeout_error]`;
149
205
  # @option logger [::Logger,#debug]
150
206
  # - Logger object used from the configuration layer (see config[:logger]);
151
207
  # - See `RedisQueuedLocks::Logging::VoidLogger` for example;
@@ -206,7 +262,7 @@ class RedisQueuedLocks::Client
206
262
  #
207
263
  # @api public
208
264
  # @since 1.0.0
209
- # @version 1.7.0
265
+ # @version 1.8.0
210
266
  # rubocop:disable Metrics/MethodLength
211
267
  def lock(
212
268
  lock_name,
@@ -223,6 +279,7 @@ class RedisQueuedLocks::Client
223
279
  access_strategy: config[:default_access_strategy],
224
280
  identity: uniq_identity,
225
281
  meta: nil,
282
+ detailed_acq_timeout_error: config[:detailed_acq_timeout_error],
226
283
  logger: config[:logger],
227
284
  log_lock_try: config[:log_lock_try],
228
285
  instrumenter: config[:instrumenter],
@@ -256,6 +313,7 @@ class RedisQueuedLocks::Client
256
313
  conflict_strategy:,
257
314
  access_strategy:,
258
315
  meta:,
316
+ detailed_acq_timeout_error:,
259
317
  logger:,
260
318
  log_lock_try:,
261
319
  instrument:,
@@ -274,7 +332,7 @@ class RedisQueuedLocks::Client
274
332
  #
275
333
  # @api public
276
334
  # @since 1.0.0
277
- # @version 1.7.0
335
+ # @version 1.8.0
278
336
  # rubocop:disable Metrics/MethodLength
279
337
  def lock!(
280
338
  lock_name,
@@ -291,6 +349,7 @@ class RedisQueuedLocks::Client
291
349
  identity: uniq_identity,
292
350
  instrumenter: config[:instrumenter],
293
351
  meta: nil,
352
+ detailed_acq_timeout_error: config[:detailed_acq_timeout_error],
294
353
  logger: config[:logger],
295
354
  log_lock_try: config[:log_lock_try],
296
355
  instrument: nil,
@@ -317,6 +376,7 @@ class RedisQueuedLocks::Client
317
376
  logger:,
318
377
  log_lock_try:,
319
378
  meta:,
379
+ detailed_acq_timeout_error:,
320
380
  instrument:,
321
381
  instrumenter:,
322
382
  conflict_strategy:,
@@ -5,6 +5,6 @@ module RedisQueuedLocks
5
5
  #
6
6
  # @api public
7
7
  # @since 0.0.1
8
- # @version 1.7.0
9
- VERSION = '1.7.0'
8
+ # @version 1.8.0
9
+ VERSION = '1.8.0'
10
10
  end
@@ -15,21 +15,17 @@ Gem::Specification.new do |spec|
15
15
  'capabilities based on the Redis Database.'
16
16
 
17
17
  spec.description =
18
- 'Distributed locks with "prioritized lock acquisition queue" capabilities ' \
18
+ '|> Distributed locks with "prioritized lock acquisition queue" capabilities ' \
19
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 " \
20
+ '|> Each lock request is put into the request queue ' \
21
+ '(each lock is hosted by it\'s own queue separately from other queues) and processed ' \
23
22
  'in order of their priority (FIFO). ' \
24
- # ---
25
- 'Each lock request lives some period of time (RTTL) ' \
23
+ '|> Each lock request lives some period of time (RTTL) ' \
26
24
  '(with requeue capabilities) which guarantees the request queue will never be stacked. ' \
27
- # ---
28
- 'In addition to the classic `queued` (FIFO) strategy RQL supports ' \
25
+ '|> In addition to the classic `queued` (FIFO) strategy RQL supports ' \
29
26
  '`random` (RANDOM) lock obtaining strategy when any acquirer from the lock queue ' \
30
27
  'can obtain the lock regardless the position in the queue. ' \
31
- # ---
32
- 'Provides flexible invocation flow, parametrized limits ' \
28
+ '|> Provides flexible invocation flow, parametrized limits ' \
33
29
  '(lock request ttl, lock ttl, queue ttl, lock attempts limit, fast failing, etc), ' \
34
30
  'logging and instrumentation.'
35
31
 
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.7.0
4
+ version: 1.8.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-06-12 00:00:00.000000000 Z
11
+ date: 2024-06-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis-client
@@ -38,8 +38,16 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0.28'
41
- description: 'Distributed locks with "prioritized lock acquisition queue" capabilities
42
- based on the Redis Database. '
41
+ description: '|> Distributed locks with "prioritized lock acquisition queue" capabilities
42
+ based on the Redis Database. |> Each lock request is put into the request queue
43
+ (each lock is hosted by it''s own queue separately from other queues) and processed
44
+ in order of their priority (FIFO). |> Each lock request lives some period of time
45
+ (RTTL) (with requeue capabilities) which guarantees the request queue will never
46
+ be stacked. |> In addition to the classic `queued` (FIFO) strategy RQL supports
47
+ `random` (RANDOM) lock obtaining strategy when any acquirer from the lock queue
48
+ can obtain the lock regardless the position in the queue. |> Provides flexible invocation
49
+ flow, parametrized limits (lock request ttl, lock ttl, queue ttl, lock attempts
50
+ limit, fast failing, etc), logging and instrumentation.'
43
51
  email:
44
52
  - iamdaiver@gmail.com
45
53
  executables: []
@@ -117,7 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
117
125
  - !ruby/object:Gem::Version
118
126
  version: '0'
119
127
  requirements: []
120
- rubygems_version: 3.3.7
128
+ rubygems_version: 3.5.1
121
129
  signing_key:
122
130
  specification_version: 4
123
131
  summary: Distributed locks with "prioritized lock acquisition queue" capabilities