redis_queued_locks 1.14.0 → 1.15.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/CHANGELOG.md +14 -3
- data/README.md +10 -8
- data/github_ci/ruby3.3.gemfile.lock +25 -26
- data/lib/redis_queued_locks/acquirer/release_locks_of.rb +11 -1
- data/lib/redis_queued_locks/config.rb +3 -2
- data/lib/redis_queued_locks/swarm.rb +1 -1
- data/lib/redis_queued_locks/version.rb +2 -2
- data/redis_queued_locks.gemspec +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f196a3e198011c805f10df6ba3c2110471b85e0f7e3629a8d6c0594329c6a61c
|
|
4
|
+
data.tar.gz: 00d1067ee165b563380b0e2061af8c73e37466e8a55b2f43c8f119069fd90b39
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6b6066096f58daeafab9c6c06f815628be1d2b32a56374f1fc3d1d6cdcff4f7aba6271d20efc16c0439084e629b6867e66eeb58d0091454b5441e29310fcb83b
|
|
7
|
+
data.tar.gz: 43751ba0011d662474c47ad014620d2b43d4555f04ae41f1a23ac1f7072aa20736a430e5a7db2a494449fe3245331e48bcf8453b91ba56c4ceba08dafaf5ed42
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [1.15.1] - 2025-10-22
|
|
4
|
+
### Fixed
|
|
5
|
+
- **Config Layer**:
|
|
6
|
+
- some config keys has no correspondig validator so during config instantation
|
|
7
|
+
custom configuraiton of these keys leads to **NoMethodError**. Missing validators were added and
|
|
8
|
+
a correspondig test added too.
|
|
9
|
+
|
|
10
|
+
## [1.15.0] - 2025-10-17
|
|
11
|
+
### Changed
|
|
12
|
+
- `"redis_queud_locks.release_locks_of"` instrumentation event payload now includes `hst_id` and `acq_id`;
|
|
13
|
+
|
|
3
14
|
## [1.14.0] - 2025-10-17
|
|
4
15
|
### Added
|
|
5
16
|
- `#clear_locks_of`/`#release_locks_of`
|
|
@@ -271,17 +282,17 @@
|
|
|
271
282
|
|
|
272
283
|
## [0.0.31] - 2024-03-25
|
|
273
284
|
### Changed
|
|
274
|
-
- `:metadata` renamed to `:instrument` in order to reflect
|
|
285
|
+
- `:metadata` renamed to `:instrument` in order to reflect its domain area;
|
|
275
286
|
- `:metadata` is renamed to `:meta` and reserved for future updates;
|
|
276
287
|
|
|
277
288
|
## [0.0.30] - 2024-03-23
|
|
278
289
|
### Fixed
|
|
279
290
|
- Re-enqueue problem: fixed a problem when the expired lock requests were infinitly re-added to the lock queue
|
|
280
291
|
and immediately removed from the lock queue rather than being re-positioned. It happens when the lock request
|
|
281
|
-
ttl reached the queue ttl, and the new request now had the dead score forever (fix:
|
|
292
|
+
ttl reached the queue ttl, and the new request now had the dead score forever (fix: its score now will be correctly
|
|
282
293
|
recalculated from the current time at the dead score time moment);
|
|
283
294
|
### Added
|
|
284
|
-
- Logging: more detailed logs to the `RedisQueuedLocks::Acquier::AcquierLock` logic and
|
|
295
|
+
- Logging: more detailed logs to the `RedisQueuedLocks::Acquier::AcquierLock` logic and its sub-modules:
|
|
285
296
|
- added new logs;
|
|
286
297
|
- added `queue_ttl` to each log;
|
|
287
298
|
|
data/README.md
CHANGED
|
@@ -104,7 +104,7 @@ Provides flexible invocation flow, parametrized limits (lock request ttl, lock t
|
|
|
104
104
|
|
|
105
105
|
<sup>\[[back to top](#table-of-contents)\]</sup>
|
|
106
106
|
|
|
107
|
-
> Each lock request is put into the request queue (each lock is hosted by
|
|
107
|
+
> Each lock request is put into the request queue (each lock is hosted by its own queue separately from other queues) and processed in order of their priority (FIFO). Each lock request lives some period of time (RTTL) which guarantees that the request queue will never be stacked.
|
|
108
108
|
|
|
109
109
|
> In addition to the classic "queued" (FIFO) strategy RQL supports "random" (RANDOM) lock obtaining strategy when any acquirer from the lock queue can obtain the lock regardless the position in the queue.
|
|
110
110
|
|
|
@@ -577,8 +577,8 @@ def lock(
|
|
|
577
577
|
- `false` by default;
|
|
578
578
|
- `block` - (optional) `[Block]`
|
|
579
579
|
- A block of code that should be executed after the successfully acquired lock.
|
|
580
|
-
- If block is **passed** the obtained lock will be released after the block execution or
|
|
581
|
-
- If block is **not passed** the obtained lock will be released after
|
|
580
|
+
- If block is **passed** the obtained lock will be released after the block execution or its ttl (what will happen first);
|
|
581
|
+
- If block is **not passed** the obtained lock will be released after its ttl;
|
|
582
582
|
- If you want the block to have a TTL too and this TTL to be the same as TTL of the lock
|
|
583
583
|
use `timed: true` option (`rql.lock("my_lock", timed: true, ttl: 5_000) { ... }`)
|
|
584
584
|
|
|
@@ -722,7 +722,7 @@ rql.lock_info("my_lock")
|
|
|
722
722
|
|
|
723
723
|
- (`:queue_ttl`) setting a short limit of time to the lock request queue position (if a process fails to acquire
|
|
724
724
|
the lock within this period of time (and before timeout/retry_count limits occurs of course) -
|
|
725
|
-
|
|
725
|
+
its lock request will be moved to the end of queue):
|
|
726
726
|
|
|
727
727
|
```ruby
|
|
728
728
|
rql.lock("my_lock", queue_ttl: 5, timeout: 10_000, retry_count: nil)
|
|
@@ -1596,7 +1596,7 @@ Accepts:
|
|
|
1596
1596
|
- `:dead_ttl` - (optional) `[Integer]`
|
|
1597
1597
|
- lock request ttl after which a lock request is considered dead;
|
|
1598
1598
|
- has a preconfigured value in `config['dead_request_ttl']` (1 day by default);
|
|
1599
|
-
- `:
|
|
1599
|
+
- `:scan_size` - (optional) `[Integer]`
|
|
1600
1600
|
- the batch of scanned keys for Redis'es SCAN command;
|
|
1601
1601
|
- has a preconfigured valie in `config['lock_release_batch_size']`;
|
|
1602
1602
|
- `:logger` - (optional) `[::Logger,#debug]`
|
|
@@ -2286,13 +2286,15 @@ Detalized event semantics and payload structure:
|
|
|
2286
2286
|
|
|
2287
2287
|
##### `"redis_queued_locks.release_locks_of"`
|
|
2288
2288
|
- <sup>\[[back to the list](#instrumentation-events)\]</sup>
|
|
2289
|
-
- an event signalizes about the released locks of the
|
|
2289
|
+
- an event signalizes about the released locks (and removement from lock queues) of the concrete host and acquirer;
|
|
2290
2290
|
- raised from `#clear_locks_of` and `#clear_current_locks` (`#release_locks_of` and `#release_current_locks` respectively);
|
|
2291
2291
|
- payload:
|
|
2292
2292
|
- `:rel_time` - `float`/`milliseconds` - time spent on "release locks of" operation;
|
|
2293
2293
|
- `:at` - `float`/`epoch` - the time when the opertaion has ended;
|
|
2294
|
+
- `:acq_id` - `string` - refused acquirer identifier;
|
|
2295
|
+
- `:hst_id` - `string` - refused host identifier;
|
|
2294
2296
|
- `:rel_key_cnt` - `integer` - released locks count;
|
|
2295
|
-
- `:tch_queue_cnt` - `:integer` - the number of queues from which the
|
|
2297
|
+
- `:tch_queue_cnt` - `:integer` - the number of queues from which the concrete host/acquirer was removed;
|
|
2296
2298
|
|
|
2297
2299
|
---
|
|
2298
2300
|
|
|
@@ -2355,7 +2357,7 @@ Detalized event semantics and payload structure:
|
|
|
2355
2357
|
- `unlock_on:`-option in lock/lock! logic in order to support auto-unlocking on any exception rasaied under the invoked block (invoked under the lock);
|
|
2356
2358
|
- **Research**: support for `Valkey` database backend (https://github.com/valkey-io/valkey) (https://valkey.io/);
|
|
2357
2359
|
- **Research**: support for `Garnet` database backend (https://microsoft.github.io/) (https://github.com/microsoft/garnet);
|
|
2358
|
-
- add a library-level exception, when RQL-related key in Redis (required for
|
|
2360
|
+
- add a library-level exception, when RQL-related key in Redis (required for its logic) has incompatible type (means: some other program uses our key with their own type and logic and RQL can't work properly);
|
|
2359
2361
|
---
|
|
2360
2362
|
|
|
2361
2363
|
## Build and Develop
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: ..
|
|
3
3
|
specs:
|
|
4
|
-
redis_queued_locks (1.
|
|
4
|
+
redis_queued_locks (1.15.1)
|
|
5
5
|
redis-client (~> 0.20)
|
|
6
6
|
|
|
7
7
|
GEM
|
|
8
8
|
remote: https://rubygems.org/
|
|
9
9
|
specs:
|
|
10
|
-
activesupport (8.0
|
|
10
|
+
activesupport (8.1.0)
|
|
11
11
|
base64
|
|
12
|
-
benchmark (>= 0.3)
|
|
13
12
|
bigdecimal
|
|
14
13
|
concurrent-ruby (~> 1.0, >= 1.3.1)
|
|
15
14
|
connection_pool (>= 2.2.5)
|
|
16
15
|
drb
|
|
17
16
|
i18n (>= 1.6, < 2)
|
|
17
|
+
json
|
|
18
18
|
logger (>= 1.4.2)
|
|
19
19
|
minitest (>= 5.1)
|
|
20
20
|
securerandom (>= 0.3)
|
|
@@ -33,11 +33,10 @@ GEM
|
|
|
33
33
|
rubocop-thread_safety (= 0.7.2)
|
|
34
34
|
ast (2.4.3)
|
|
35
35
|
base64 (0.3.0)
|
|
36
|
-
|
|
37
|
-
bigdecimal (3.2.1)
|
|
36
|
+
bigdecimal (3.3.1)
|
|
38
37
|
coderay (1.1.3)
|
|
39
38
|
concurrent-ruby (1.3.5)
|
|
40
|
-
connection_pool (2.5.
|
|
39
|
+
connection_pool (2.5.4)
|
|
41
40
|
csv (3.3.5)
|
|
42
41
|
diff-lcs (1.6.2)
|
|
43
42
|
docile (1.4.1)
|
|
@@ -56,7 +55,7 @@ GEM
|
|
|
56
55
|
fileutils (1.7.3)
|
|
57
56
|
i18n (1.14.7)
|
|
58
57
|
concurrent-ruby (~> 1.0)
|
|
59
|
-
json (2.
|
|
58
|
+
json (2.15.1)
|
|
60
59
|
language_server-protocol (3.17.0.5)
|
|
61
60
|
lint_roller (1.1.0)
|
|
62
61
|
listen (3.9.0)
|
|
@@ -64,43 +63,43 @@ GEM
|
|
|
64
63
|
rb-inotify (~> 0.9, >= 0.9.10)
|
|
65
64
|
logger (1.7.0)
|
|
66
65
|
method_source (1.1.0)
|
|
67
|
-
minitest (5.
|
|
66
|
+
minitest (5.26.0)
|
|
68
67
|
mutex_m (0.3.0)
|
|
69
68
|
parallel (1.27.0)
|
|
70
|
-
parser (3.3.
|
|
69
|
+
parser (3.3.9.0)
|
|
71
70
|
ast (~> 2.4.1)
|
|
72
71
|
racc
|
|
73
|
-
prism (1.
|
|
72
|
+
prism (1.6.0)
|
|
74
73
|
pry (0.15.2)
|
|
75
74
|
coderay (~> 1.1)
|
|
76
75
|
method_source (~> 1.0)
|
|
77
76
|
racc (1.8.1)
|
|
78
|
-
rack (3.
|
|
77
|
+
rack (3.2.3)
|
|
79
78
|
rainbow (3.1.1)
|
|
80
79
|
rake (13.3.0)
|
|
81
80
|
rb-fsevent (0.11.2)
|
|
82
81
|
rb-inotify (0.11.1)
|
|
83
82
|
ffi (~> 1.0)
|
|
84
|
-
rbs (3.9.
|
|
83
|
+
rbs (3.9.5)
|
|
85
84
|
logger
|
|
86
|
-
redis-client (0.
|
|
85
|
+
redis-client (0.26.1)
|
|
87
86
|
connection_pool
|
|
88
|
-
regexp_parser (2.
|
|
89
|
-
rspec (3.13.
|
|
87
|
+
regexp_parser (2.11.3)
|
|
88
|
+
rspec (3.13.2)
|
|
90
89
|
rspec-core (~> 3.13.0)
|
|
91
90
|
rspec-expectations (~> 3.13.0)
|
|
92
91
|
rspec-mocks (~> 3.13.0)
|
|
93
|
-
rspec-core (3.13.
|
|
92
|
+
rspec-core (3.13.6)
|
|
94
93
|
rspec-support (~> 3.13.0)
|
|
95
94
|
rspec-expectations (3.13.5)
|
|
96
95
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
97
96
|
rspec-support (~> 3.13.0)
|
|
98
|
-
rspec-mocks (3.13.
|
|
97
|
+
rspec-mocks (3.13.6)
|
|
99
98
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
100
99
|
rspec-support (~> 3.13.0)
|
|
101
100
|
rspec-retry (0.6.2)
|
|
102
101
|
rspec-core (> 3.3)
|
|
103
|
-
rspec-support (3.13.
|
|
102
|
+
rspec-support (3.13.6)
|
|
104
103
|
rubocop (1.75.7)
|
|
105
104
|
json (~> 2.3)
|
|
106
105
|
language_server-protocol (~> 3.17.0.2)
|
|
@@ -112,7 +111,7 @@ GEM
|
|
|
112
111
|
rubocop-ast (>= 1.44.0, < 2.0)
|
|
113
112
|
ruby-progressbar (~> 1.7)
|
|
114
113
|
unicode-display_width (>= 2.4.0, < 4.0)
|
|
115
|
-
rubocop-ast (1.
|
|
114
|
+
rubocop-ast (1.47.1)
|
|
116
115
|
parser (>= 3.3.7.2)
|
|
117
116
|
prism (~> 1.4)
|
|
118
117
|
rubocop-capybara (2.22.1)
|
|
@@ -155,8 +154,8 @@ GEM
|
|
|
155
154
|
docile (~> 1.1)
|
|
156
155
|
simplecov-html (~> 0.11)
|
|
157
156
|
simplecov_json_formatter (~> 0.1)
|
|
158
|
-
simplecov-html (0.13.
|
|
159
|
-
simplecov-lcov (0.
|
|
157
|
+
simplecov-html (0.13.2)
|
|
158
|
+
simplecov-lcov (0.9.0)
|
|
160
159
|
simplecov_json_formatter (0.1.4)
|
|
161
160
|
steep (1.10.0)
|
|
162
161
|
activesupport (>= 5.1)
|
|
@@ -180,10 +179,10 @@ GEM
|
|
|
180
179
|
unicode-display_width (>= 1.1.1, < 4)
|
|
181
180
|
tzinfo (2.0.6)
|
|
182
181
|
concurrent-ruby (~> 1.0)
|
|
183
|
-
unicode-display_width (3.
|
|
184
|
-
unicode-emoji (~> 4.
|
|
185
|
-
unicode-emoji (4.0
|
|
186
|
-
uri (1.0.
|
|
182
|
+
unicode-display_width (3.2.0)
|
|
183
|
+
unicode-emoji (~> 4.1)
|
|
184
|
+
unicode-emoji (4.1.0)
|
|
185
|
+
uri (1.0.4)
|
|
187
186
|
zlib (3.2.1)
|
|
188
187
|
|
|
189
188
|
PLATFORMS
|
|
@@ -214,4 +213,4 @@ DEPENDENCIES
|
|
|
214
213
|
steep
|
|
215
214
|
|
|
216
215
|
BUNDLED WITH
|
|
217
|
-
2.
|
|
216
|
+
2.7.2
|
|
@@ -73,10 +73,18 @@ module RedisQueuedLocks::Acquirer::ReleaseLocksOf
|
|
|
73
73
|
# despite the enabled instrumentation sampling;
|
|
74
74
|
# - makes sense when instrumentation sampling is enabled;
|
|
75
75
|
# @return [Hash<Symbol,Any>]
|
|
76
|
-
# Format: {
|
|
76
|
+
# Format: {
|
|
77
|
+
# ok: true,
|
|
78
|
+
# result: {
|
|
79
|
+
# rel_key_cnt: Integer,
|
|
80
|
+
# tch_queue_cnt: Integer,
|
|
81
|
+
# rel_time: Numeric
|
|
82
|
+
# }
|
|
83
|
+
# }
|
|
77
84
|
#
|
|
78
85
|
# @api private
|
|
79
86
|
# @since 1.14.0
|
|
87
|
+
# @version 1.15.0
|
|
80
88
|
# rubocop:disable Metrics/MethodLength
|
|
81
89
|
def release_locks_of(
|
|
82
90
|
refused_host_id,
|
|
@@ -125,6 +133,8 @@ module RedisQueuedLocks::Acquirer::ReleaseLocksOf
|
|
|
125
133
|
run_non_critical do
|
|
126
134
|
instrumenter.notify('redis_queued_locks.release_locks_of', {
|
|
127
135
|
at: time_at,
|
|
136
|
+
hst_id: refused_host_id,
|
|
137
|
+
acq_id: refused_acquirer_id,
|
|
128
138
|
rel_time: rel_time,
|
|
129
139
|
rel_key_cnt: result[:rel_key_cnt],
|
|
130
140
|
tch_queue_cnt: result[:tch_queue_cnt]
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# @api private
|
|
4
4
|
# @since 1.13.0
|
|
5
|
-
# @version 1.
|
|
5
|
+
# @version 1.15.1
|
|
6
6
|
# rubocop:disable Metrics/ClassLength
|
|
7
7
|
class RedisQueuedLocks::Config
|
|
8
8
|
require_relative 'config/dsl'
|
|
@@ -78,12 +78,13 @@ class RedisQueuedLocks::Config
|
|
|
78
78
|
validate('retry_delay') { |val| val.is_a?(Integer) && val >= 0 }
|
|
79
79
|
validate('retry_jitter') { |val| val.is_a?(Integer) && val >= 0 }
|
|
80
80
|
validate('try_to_lock_timeout') { |val| val == nil || (val.is_a?(Integer) && val >= 0) }
|
|
81
|
-
validate('
|
|
81
|
+
validate('default_lock_ttl') { |val| val.is_a?(Integer) }
|
|
82
82
|
validate('default_queue_ttl') { |val| val.is_a?(Integer) }
|
|
83
83
|
validate('detailed_acq_timeout_error') { |val| val == true || val == false }
|
|
84
84
|
validate('lock_release_batch_size') { |val| val.is_a?(Integer) }
|
|
85
85
|
validate('clear_locks_of__lock_scan_size') { |val| val.is_a?(Integer) }
|
|
86
86
|
validate('clear_locks_of__queue_scan_size') { |val| val.is_a?(Integer) }
|
|
87
|
+
validate('key_extraction_batch_size') { |val| val.is_a?(Integer) }
|
|
87
88
|
validate('instrumenter') { |val| RedisQueuedLocks::Instrument.valid_interface?(val) }
|
|
88
89
|
validate('uniq_identifier') { |val| val.is_a?(Proc) }
|
|
89
90
|
validate('logger') { |val| RedisQueuedLocks::Logging.valid_interface?(val) }
|
data/redis_queued_locks.gemspec
CHANGED
|
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
|
18
18
|
"|> Distributed locks with \"prioritized lock acquisition queue\" capabilities " \
|
|
19
19
|
"based on the Redis Database.\n" \
|
|
20
20
|
"|> Each lock request is put into the request queue " \
|
|
21
|
-
"(each lock is hosted by
|
|
21
|
+
"(each lock is hosted by its own queue separately from other queues) and processed " \
|
|
22
22
|
"in order of their priority (FIFO).\n" \
|
|
23
23
|
"|> Each lock request lives some period of time (RTTL) " \
|
|
24
24
|
"(with requeue capabilities) which guarantees the request queue will never be stacked.\n" \
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
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.15.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Rustam Ibragimov
|
|
@@ -25,7 +25,7 @@ dependencies:
|
|
|
25
25
|
version: '0.20'
|
|
26
26
|
description: |-
|
|
27
27
|
|> Distributed locks with "prioritized lock acquisition queue" capabilities based on the Redis Database.
|
|
28
|
-
|> Each lock request is put into the request queue (each lock is hosted by
|
|
28
|
+
|> Each lock request is put into the request queue (each lock is hosted by its own queue separately from other queues) and processed in order of their priority (FIFO).
|
|
29
29
|
|> Each lock request lives some period of time (RTTL) (with requeue capabilities) which guarantees the request queue will never be stacked.
|
|
30
30
|
|> In addition to the classic `queued` (FIFO) strategy RQL supports `random` (RANDOM) lock obtaining strategy when any acquirer from the lock queue can obtain the lock regardless the position in the queue.
|
|
31
31
|
|> Provides flexible invocation flow, parametrized limits (lock request ttl, lock ttl, queue ttl, lock attempts limit, fast failing, etc), logging and instrumentation.
|