redis_queued_locks 0.0.16 → 0.0.17
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 +6 -0
- data/README.md +103 -2
- data/lib/redis_queued_locks/acquier/release.rb +2 -0
- data/lib/redis_queued_locks/acquier.rb +60 -1
- data/lib/redis_queued_locks/client.rb +28 -0
- data/lib/redis_queued_locks/resource.rb +6 -0
- data/lib/redis_queued_locks/version.rb +2 -2
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eb745a97296f4661f7a68d7719d7bdb894521348d6aa25b92b23b4fcffce56cd
|
4
|
+
data.tar.gz: e12566b1c653ad97bf973887d4511482c628d8ec27fd265901d1d4bfba9c112b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c3e6f4c421c8e6fb9b3933c01ebcd23d5762f0bdb0581333e2d85ab478a8002d8bce360bfabaab29d819c92a4f148e6562d0fa426e5999b0fc2d1c9b59f3eaa7
|
7
|
+
data.tar.gz: 42a5800757191ea80797c7462b765c5dd4187771ce73c6c9af70f6653dea5599710d8569b5a2fc1a0c30cb0b3483abfac557bd888a7f4bcbde4ac4a7de308021
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.0.17] - 2024-02-29
|
4
|
+
### Added
|
5
|
+
- `RedisQueuedLocks::Client#locks` - list of obtained locks;
|
6
|
+
- `RedisQueuedLocks::Client#queues` - list of existing lock request queus;
|
7
|
+
- `RedisQueuedLocks::Client#keys` - get list of taken locks and queues;
|
8
|
+
|
3
9
|
## [0.0.16] - 2024-02-29
|
4
10
|
### Fixed
|
5
11
|
- Execution delay formula returns the value "in seconds" (should be "in milliseconds");
|
data/README.md
CHANGED
@@ -21,6 +21,10 @@ Each lock request is put into the request queue and processed in order of their
|
|
21
21
|
- [queued?](#queued)
|
22
22
|
- [unlock](#unlock---release-a-lock)
|
23
23
|
- [clear_locks](#clear_locks---release-all-locks-and-lock-queues)
|
24
|
+
- [extend_lock_ttl](#extend_lock_ttl)
|
25
|
+
- [locks](#locks---get-list-of-obtained-locks)
|
26
|
+
- [queues](#queues---get-list-of-lock-request-queues)
|
27
|
+
- [keys](#keys---get-list-of-taken-locks-and-queues)
|
24
28
|
- [Instrumentation](#instrumentation)
|
25
29
|
- [Instrumentation Events](#instrumentation-events)
|
26
30
|
- [Roadmap](#roadmap)
|
@@ -104,10 +108,15 @@ clinet = RedisQueuedLocks::Client.new(redis_client) do |config|
|
|
104
108
|
config.default_queue_ttl = 15
|
105
109
|
|
106
110
|
# (default: 100)
|
107
|
-
# - how many items will be released at a time in RedisQueuedLocks::Client#clear_locks logic;
|
108
|
-
# - affects the performancs
|
111
|
+
# - how many items will be released at a time in RedisQueuedLocks::Client#clear_locks logic (uses SCAN);
|
112
|
+
# - affects the performancs of your Redis and Ruby Application (configure thoughtfully);
|
109
113
|
config.lock_release_batch_size = 100
|
110
114
|
|
115
|
+
# (default: 500)
|
116
|
+
# - how many items should be extracted from redis during the #locks, #queues and #keys operations (uses SCAN);
|
117
|
+
# - affects the performance of your Redis and Ruby Application (configure thoughtfully;)
|
118
|
+
config.key_extraction_batch_size = 500
|
119
|
+
|
111
120
|
# (default: RedisQueuedLocks::Instrument::VoidNotifier)
|
112
121
|
# - instrumentation layer;
|
113
122
|
# - you can provde your own instrumenter with `#notify(event, payload = {})`
|
@@ -138,6 +147,10 @@ end
|
|
138
147
|
- [queued?](#queued)
|
139
148
|
- [unlock](#unlock---release-a-lock)
|
140
149
|
- [clear_locks](#clear_locks---release-all-locks-and-lock-queues)
|
150
|
+
- [extend_lock_ttl](#extend_lock_ttl)
|
151
|
+
- [locks](#locks---get-list-of-obtained-locks)
|
152
|
+
- [queues](#queues---get-list-of-lock-request-queues)
|
153
|
+
- [keys](#keys---get-list-of-taken-locks-and-queues)
|
141
154
|
|
142
155
|
---
|
143
156
|
|
@@ -393,6 +406,94 @@ Return:
|
|
393
406
|
|
394
407
|
---
|
395
408
|
|
409
|
+
#### #extend_lock_ttl
|
410
|
+
|
411
|
+
- soon
|
412
|
+
|
413
|
+
---
|
414
|
+
|
415
|
+
#### #locks - get list of obtained locks
|
416
|
+
|
417
|
+
- uses redis `SCAN` under the hood;
|
418
|
+
- accepts `scan_size:`/`Integer` option (`config[:key_extraction_batch_size]` by default);
|
419
|
+
- returns `Set<String>`
|
420
|
+
|
421
|
+
```ruby
|
422
|
+
rql.locks # or rql.locks(scan_size: 123)
|
423
|
+
|
424
|
+
=>
|
425
|
+
#<Set:
|
426
|
+
{"rql:lock:locklock75",
|
427
|
+
"rql:lock:locklock9",
|
428
|
+
"rql:lock:locklock108",
|
429
|
+
"rql:lock:locklock7",
|
430
|
+
"rql:lock:locklock48",
|
431
|
+
"rql:lock:locklock104",
|
432
|
+
"rql:lock:locklock13",
|
433
|
+
"rql:lock:locklock62",
|
434
|
+
"rql:lock:locklock80",
|
435
|
+
"rql:lock:locklock28",
|
436
|
+
...}>
|
437
|
+
```
|
438
|
+
|
439
|
+
---
|
440
|
+
|
441
|
+
#### #queues - get list of lock request queues
|
442
|
+
|
443
|
+
- uses redis `SCAN` under the hood;
|
444
|
+
- accepts `scan_size:`/`Integer` option (`config[:key_extraction_batch_size]` by default);
|
445
|
+
- returns `Set<String>`
|
446
|
+
|
447
|
+
```ruby
|
448
|
+
rql.queues # or rql.queues(scan_size: 123)
|
449
|
+
|
450
|
+
=>
|
451
|
+
#<Set:
|
452
|
+
{"rql:lock_queue:locklock75",
|
453
|
+
"rql:lock_queue:locklock9",
|
454
|
+
"rql:lock_queue:locklock108",
|
455
|
+
"rql:lock_queue:locklock7",
|
456
|
+
"rql:lock_queue:locklock48",
|
457
|
+
"rql:lock_queue:locklock104",
|
458
|
+
"rql:lock_queue:locklock13",
|
459
|
+
"rql:lock_queue:locklock62",
|
460
|
+
"rql:lock_queue:locklock80",
|
461
|
+
"rql:lock_queue:locklock28",
|
462
|
+
...}>
|
463
|
+
```
|
464
|
+
|
465
|
+
---
|
466
|
+
|
467
|
+
#### #keys - get list of taken locks and queues
|
468
|
+
|
469
|
+
- uses redis `SCAN` under the hood;
|
470
|
+
- accepts `scan_size:`/`Integer` option (`config[:key_extraction_batch_size]` by default);
|
471
|
+
- returns `Set<String>`
|
472
|
+
|
473
|
+
```ruby
|
474
|
+
rql.keys # or rql.keys(scan_size: 123)
|
475
|
+
|
476
|
+
=>
|
477
|
+
#<Set:
|
478
|
+
{"rql:lock_queue:locklock75",
|
479
|
+
"rql:lock_queue:locklock9",
|
480
|
+
"rql:lock:locklock9",
|
481
|
+
"rql:lock_queue:locklock108",
|
482
|
+
"rql:lock_queue:locklock7",
|
483
|
+
"rql:lock:locklock7",
|
484
|
+
"rql:lock_queue:locklock48",
|
485
|
+
"rql:lock_queue:locklock104",
|
486
|
+
"rql:lock:locklock104",
|
487
|
+
"rql:lock_queue:locklock13",
|
488
|
+
"rql:lock_queue:locklock62",
|
489
|
+
"rql:lock_queue:locklock80",
|
490
|
+
"rql:lock:locklock80",
|
491
|
+
"rql:lock_queue:locklock28",
|
492
|
+
...}>
|
493
|
+
```
|
494
|
+
|
495
|
+
---
|
496
|
+
|
396
497
|
## Instrumentation
|
397
498
|
|
398
499
|
An instrumentation layer is incapsulated in `instrumenter` object stored in [config](#configuration) (`RedisQueuedLocks::Client#config[:instrumenter]`).
|
@@ -37,6 +37,7 @@ module RedisQueuedLocks::Acquier::Release
|
|
37
37
|
RedisQueuedLocks::Resource::LOCK_QUEUE_PATTERN,
|
38
38
|
count: batch_size
|
39
39
|
) do |lock_queue|
|
40
|
+
# TODO: reduce unnecessary iterations
|
40
41
|
pipeline.call('ZREMRANGEBYSCORE', lock_queue, '-inf', '+inf')
|
41
42
|
pipeline.call('EXPIRE', RedisQueuedLocks::Resource.lock_key_from_queue(lock_queue), '0')
|
42
43
|
end
|
@@ -47,6 +48,7 @@ module RedisQueuedLocks::Acquier::Release
|
|
47
48
|
RedisQueuedLocks::Resource::LOCK_PATTERN,
|
48
49
|
count: batch_size
|
49
50
|
) do |lock_key|
|
51
|
+
# TODO: reduce unnecessary iterations
|
50
52
|
pipeline.call('EXPIRE', lock_key, '0')
|
51
53
|
end
|
52
54
|
end
|
@@ -437,7 +437,66 @@ module RedisQueuedLocks::Acquier
|
|
437
437
|
#
|
438
438
|
# @api private
|
439
439
|
# @since 0.1.0
|
440
|
-
def extend_lock_ttl(redis_client, lock_name, milliseconds)
|
440
|
+
def extend_lock_ttl(redis_client, lock_name, milliseconds)
|
441
|
+
# TODO: realize
|
442
|
+
end
|
443
|
+
|
444
|
+
# @param redis_client [RedisClient]
|
445
|
+
# @option scan_size [Integer]
|
446
|
+
# @return [Set<String>]
|
447
|
+
#
|
448
|
+
# @api private
|
449
|
+
# @since 0.1.0
|
450
|
+
def locks(redis_client, scan_size:)
|
451
|
+
Set.new.tap do |lock_keys|
|
452
|
+
redis_client.scan(
|
453
|
+
'MATCH',
|
454
|
+
RedisQueuedLocks::Resource::LOCK_PATTERN,
|
455
|
+
count: scan_size
|
456
|
+
) do |lock_key|
|
457
|
+
# TODO: reduce unnecessary iterations
|
458
|
+
lock_keys.add(lock_key)
|
459
|
+
end
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
# @param redis_client [RedisClient]
|
464
|
+
# @param scan_size [Integer]
|
465
|
+
# @return [Set<String>]
|
466
|
+
#
|
467
|
+
# @api private
|
468
|
+
# @since 0.1.0
|
469
|
+
def queues(redis_client, scan_size:)
|
470
|
+
Set.new.tap do |lock_queues|
|
471
|
+
redis_client.scan(
|
472
|
+
'MATCH',
|
473
|
+
RedisQueuedLocks::Resource::LOCK_QUEUE_PATTERN,
|
474
|
+
count: scan_size
|
475
|
+
) do |lock_queue|
|
476
|
+
# TODO: reduce unnecessary iterations
|
477
|
+
lock_queues.add(lock_queue)
|
478
|
+
end
|
479
|
+
end
|
480
|
+
end
|
481
|
+
|
482
|
+
# @param redis_client [RedisClient]
|
483
|
+
# @option scan_size [Integer]
|
484
|
+
# @return [Array<String>]
|
485
|
+
#
|
486
|
+
# @api private
|
487
|
+
# @since 0.1.0
|
488
|
+
def keys(redis_client, scan_size:)
|
489
|
+
Set.new.tap do |keys|
|
490
|
+
redis_client.scan(
|
491
|
+
'MATCH',
|
492
|
+
RedisQueuedLocks::Resource::KEY_PATTERN,
|
493
|
+
count: scan_size
|
494
|
+
) do |key|
|
495
|
+
# TODO: reduce unnecessary iterations
|
496
|
+
keys.add(key)
|
497
|
+
end
|
498
|
+
end
|
499
|
+
end
|
441
500
|
|
442
501
|
private
|
443
502
|
|
@@ -15,6 +15,7 @@ class RedisQueuedLocks::Client
|
|
15
15
|
setting :default_lock_ttl, 5_000 # NOTE: milliseconds
|
16
16
|
setting :default_queue_ttl, 15 # NOTE: seconds
|
17
17
|
setting :lock_release_batch_size, 100
|
18
|
+
setting :key_extraction_batch_size, 500
|
18
19
|
setting :instrumenter, RedisQueuedLocks::Instrument::VoidNotifier
|
19
20
|
setting :uniq_identifier, -> { RedisQueuedLocks::Resource.calc_uniq_identity }
|
20
21
|
|
@@ -225,5 +226,32 @@ class RedisQueuedLocks::Client
|
|
225
226
|
def clear_locks(batch_size: config[:lock_release_batch_size])
|
226
227
|
RedisQueuedLocks::Acquier.release_all_locks!(redis_client, batch_size, config[:instrumenter])
|
227
228
|
end
|
229
|
+
|
230
|
+
# @option scan_size [Integer]
|
231
|
+
# @return [Set<String>]
|
232
|
+
#
|
233
|
+
# @api public
|
234
|
+
# @since 0.1.0
|
235
|
+
def locks(scan_size: config[:key_extraction_batch_size])
|
236
|
+
RedisQueuedLocks::Acquier.locks(redis_client, scan_size:)
|
237
|
+
end
|
238
|
+
|
239
|
+
# @option scan_size [Integer]
|
240
|
+
# @return [Set<String>]
|
241
|
+
#
|
242
|
+
# @api public
|
243
|
+
# @since 0.1.0
|
244
|
+
def queues(scan_size: config[:key_extraction_batch_size])
|
245
|
+
RedisQueuedLocks::Acquier.queues(redis_client, scan_size:)
|
246
|
+
end
|
247
|
+
|
248
|
+
# @option scan_size [Integer]
|
249
|
+
# @return [Set<String>]
|
250
|
+
#
|
251
|
+
# @api public
|
252
|
+
# @since 0.1.0
|
253
|
+
def keys(scan_size: config[:key_extraction_batch_size])
|
254
|
+
RedisQueuedLocks::Acquier.keys(redis_client, scan_size:)
|
255
|
+
end
|
228
256
|
end
|
229
257
|
# rubocop:enable Metrics/ClassLength
|