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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 524740cce42224df4610bce35ced68e38f0fceb13ba233fe9c2f4ceac76fa49a
4
- data.tar.gz: f3cb8b791292ba1c98b9b97c2a23b413edf74a3a5a25cebba5c7e3900f5705fd
3
+ metadata.gz: eb745a97296f4661f7a68d7719d7bdb894521348d6aa25b92b23b4fcffce56cd
4
+ data.tar.gz: e12566b1c653ad97bf973887d4511482c628d8ec27fd265901d1d4bfba9c112b
5
5
  SHA512:
6
- metadata.gz: 732ffd5fe549d093f8bc4ef6edd1db9751aa951b0cd0f75d3ba63b8facc7a5bea1d31c88527ae2ae1c3bd4bfc5e686a447ab3907d18f37c1756167d306c929aa
7
- data.tar.gz: f6b95308ec0653068de4816ce47a45f2470000079d468a54950f4a4bfc10c2689778108a265d3be097811d0da31b16678d14aa284903066e9c889201cc412abb
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 capabilites (redis, rubyvm);
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); end
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
@@ -3,6 +3,12 @@
3
3
  # @api private
4
4
  # @since 0.1.0
5
5
  module RedisQueuedLocks::Resource
6
+ # @return [String]
7
+ #
8
+ # @api private
9
+ # @since 0.1.0
10
+ KEY_PATTERN = 'rql:lock*'
11
+
6
12
  # @return [String]
7
13
  #
8
14
  # @api private
@@ -5,6 +5,6 @@ module RedisQueuedLocks
5
5
  #
6
6
  # @api public
7
7
  # @since 0.0.1
8
- # @version 0.0.16
9
- VERSION = '0.0.16'
8
+ # @version 0.0.17
9
+ VERSION = '0.0.17'
10
10
  end
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: 0.0.16
4
+ version: 0.0.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rustam Ibragimov