redis_queued_locks 1.20.0 → 1.22.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.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/project-overview.md +249 -36
  3. data/.claude/rules/acquirer.md +16 -14
  4. data/.claude/rules/arguments.md +2 -2
  5. data/.claude/rules/changelog.md +27 -0
  6. data/.claude/rules/git.md +1 -1
  7. data/.claude/rules/logic.md +34 -13
  8. data/.claude/rules/swarm.md +4 -5
  9. data/.claude/rules/tests.md +9 -6
  10. data/.claude/rules/type-checking.md +13 -14
  11. data/.claude/rules/visitors.md +13 -14
  12. data/.claude/skills/rql-code-review/SKILL.md +134 -43
  13. data/CHANGELOG.md +105 -125
  14. data/CLAUDE.md +11 -9
  15. data/README.md +501 -136
  16. data/Rakefile +11 -0
  17. data/lib/redis_queued_locks/acquirer/acquire_lock/dequeue_from_lock_queue/log_visitor.rb +1 -0
  18. data/lib/redis_queued_locks/acquirer/acquire_lock/instr_visitor.rb +68 -10
  19. data/lib/redis_queued_locks/acquirer/acquire_lock/log_visitor.rb +82 -15
  20. data/lib/redis_queued_locks/acquirer/acquire_lock/try_to_lock/log_visitor.rb +92 -14
  21. data/lib/redis_queued_locks/acquirer/acquire_lock/try_to_lock.rb +441 -63
  22. data/lib/redis_queued_locks/acquirer/acquire_lock/with_acq_timeout.rb +2 -2
  23. data/lib/redis_queued_locks/acquirer/acquire_lock/yield_expire/log_visitor.rb +1 -0
  24. data/lib/redis_queued_locks/acquirer/acquire_lock/yield_expire.rb +5 -5
  25. data/lib/redis_queued_locks/acquirer/acquire_lock.rb +176 -39
  26. data/lib/redis_queued_locks/acquirer/clear_dead_requests.rb +322 -49
  27. data/lib/redis_queued_locks/acquirer/extend_lock_ttl.rb +125 -13
  28. data/lib/redis_queued_locks/acquirer/is_locked.rb +0 -1
  29. data/lib/redis_queued_locks/acquirer/is_queued.rb +0 -1
  30. data/lib/redis_queued_locks/acquirer/keys.rb +16 -3
  31. data/lib/redis_queued_locks/acquirer/lock_info.rb +31 -39
  32. data/lib/redis_queued_locks/acquirer/lock_series_poc/instr_visitor.rb +11 -5
  33. data/lib/redis_queued_locks/acquirer/lock_series_poc/log_visitor.rb +20 -10
  34. data/lib/redis_queued_locks/acquirer/lock_series_poc.rb +105 -36
  35. data/lib/redis_queued_locks/acquirer/locks.rb +32 -11
  36. data/lib/redis_queued_locks/acquirer/queue_info.rb +30 -8
  37. data/lib/redis_queued_locks/acquirer/queues.rb +26 -6
  38. data/lib/redis_queued_locks/acquirer/reindex_locks.rb +117 -4
  39. data/lib/redis_queued_locks/acquirer/release_all_locks.rb +37 -6
  40. data/lib/redis_queued_locks/acquirer/release_lock.rb +33 -7
  41. data/lib/redis_queued_locks/acquirer/release_locks_of.rb +45 -6
  42. data/lib/redis_queued_locks/acquirer/release_read_lock.rb +22 -3
  43. data/lib/redis_queued_locks/client.rb +140 -56
  44. data/lib/redis_queued_locks/config.rb +105 -14
  45. data/lib/redis_queued_locks/errors.rb +34 -4
  46. data/lib/redis_queued_locks/instrument/sampler.rb +4 -7
  47. data/lib/redis_queued_locks/logging/sampler.rb +4 -8
  48. data/lib/redis_queued_locks/resource.rb +137 -12
  49. data/lib/redis_queued_locks/swarm/flush_zombies.rb +1 -0
  50. data/lib/redis_queued_locks/swarm/redis_client_builder.rb +8 -4
  51. data/lib/redis_queued_locks/swarm/swarm_element/threaded.rb +8 -6
  52. data/lib/redis_queued_locks/swarm/zombie_info.rb +6 -2
  53. data/lib/redis_queued_locks/swarm.rb +86 -5
  54. data/lib/redis_queued_locks/utilities.rb +1 -1
  55. data/lib/redis_queued_locks/version.rb +2 -2
  56. data/rbs_collection.lock.yaml +4 -0
  57. data/rbs_collection.yaml +2 -1
  58. data/sig/manifest.yml +1 -0
  59. data/sig/redis_queued_locks/acquirer/acquire_lock/dequeue_from_lock_queue/log_visitor.rbs +2 -2
  60. data/sig/redis_queued_locks/acquirer/acquire_lock/dequeue_from_lock_queue.rbs +2 -2
  61. data/sig/redis_queued_locks/acquirer/acquire_lock/instr_visitor.rbs +25 -5
  62. data/sig/redis_queued_locks/acquirer/acquire_lock/log_visitor.rbs +32 -12
  63. data/sig/redis_queued_locks/acquirer/acquire_lock/try_to_lock/log_visitor.rbs +61 -40
  64. data/sig/redis_queued_locks/acquirer/acquire_lock/try_to_lock.rbs +59 -11
  65. data/sig/redis_queued_locks/acquirer/acquire_lock/{yield_with_expire → yield_expire}/log_visitor.rbs +4 -4
  66. data/sig/redis_queued_locks/acquirer/acquire_lock/yield_expire.rbs +4 -4
  67. data/sig/redis_queued_locks/acquirer/acquire_lock.rbs +6 -4
  68. data/sig/redis_queued_locks/acquirer/clear_dead_requests.rbs +23 -1
  69. data/sig/redis_queued_locks/acquirer/extend_lock_ttl.rbs +16 -3
  70. data/sig/redis_queued_locks/acquirer/queues.rbs +1 -1
  71. data/sig/redis_queued_locks/acquirer/reindex_locks.rbs +22 -1
  72. data/sig/redis_queued_locks/acquirer/release_lock.rbs +3 -2
  73. data/sig/redis_queued_locks/acquirer/release_read_lock.rbs +1 -1
  74. data/sig/redis_queued_locks/client.rbs +24 -10
  75. data/sig/redis_queued_locks/config.rbs +54 -1
  76. data/sig/redis_queued_locks/errors.rbs +5 -2
  77. data/sig/redis_queued_locks/instrument/sampler.rbs +3 -3
  78. data/sig/redis_queued_locks/instrument/void_notifier.rbs +3 -1
  79. data/sig/redis_queued_locks/logging/sampler.rbs +3 -3
  80. data/sig/redis_queued_locks/resource.rbs +23 -13
  81. data/sig/redis_queued_locks/swarm/swarm_element/threaded.rbs +1 -1
  82. data/sig/redis_queued_locks/utilities.rbs +2 -1
  83. data/sig/redis_queued_locks.rbs +7 -0
  84. data/sig/vendor/redis_client.rbs +1 -0
  85. metadata +4 -3
  86. /data/sig/redis_queued_locks/{acquier.rbs → acquirer.rbs} +0 -0
@@ -10,6 +10,9 @@ module RedisQueuedLocks
10
10
  SWARM_KEY: String
11
11
  LOCK_INDEX_KEY: String
12
12
  REDIS_TIMESHIFT_ERROR: Integer
13
+ MIN_LOCK_PRIORITY: Integer
14
+ MAX_LOCK_PRIORITY: Integer
15
+ LOCK_PRIORITY_BAND: Integer
13
16
 
14
17
  def self.calc_uniq_identity: () -> String
15
18
  def self.acquirer_identifier: (
@@ -27,25 +30,32 @@ module RedisQueuedLocks
27
30
  String identity
28
31
  ) -> String
29
32
 
30
- def self.prepare_lock_key: (String lock_name) -> String
31
- def self.prepare_lock_queue: (String lock_name) -> String
32
- def self.prepare_read_lock_queue: (String lock_name) -> String
33
- def self.prepare_lock_readers: (String lock_name) -> String
34
- def self.prepare_read_lock_key: (String lock_name, String acquirer_id) -> String
33
+ # NOTE: (rbs test) `%a{rbs:test:skip}`: these functions run inside the zombie flusher Ractor
34
+ # (`FlushZombies.flush_zombies`); rbs/test hooks read `RBS.logger` and raise
35
+ # `Ractor::IsolationError` there, so they are not hooked (Steep still checks them).
36
+ %a{rbs:test:skip} def self.prepare_lock_key: (String lock_name) -> String
37
+ %a{rbs:test:skip} def self.prepare_lock_queue: (String lock_name) -> String
38
+ %a{rbs:test:skip} def self.prepare_read_lock_queue: (String lock_name) -> String
39
+ %a{rbs:test:skip} def self.prepare_lock_readers: (String lock_name) -> String
40
+ %a{rbs:test:skip} def self.prepare_read_lock_key: (String lock_name, String acquirer_id) -> String
35
41
  def self.lock_queue_rw_mode: (String lock_queue) -> String?
36
42
  type lockKeyFamily = :lock | :lock_queue | :lock_readers | :read_lock_queue | :read_lock
37
- def self.lock_key_family: (String key) -> lockKeyFamily?
43
+ %a{rbs:test:skip} def self.lock_key_family: (String key) -> lockKeyFamily?
38
44
  def self.lock_name_from_key: (String key, lockKeyFamily? key_family) -> String?
39
- def self.lock_index_time: () -> Integer
40
- def self.lock_name_from_readers: (String lock_readers_key) -> String
45
+ %a{rbs:test:skip} def self.lock_index_time: () -> Integer
46
+ def self.lock_index_score_expired?: (String lock_index_score, Integer lock_index_time) -> bool
47
+ %a{rbs:test:skip} def self.lock_name_from_readers: (String lock_readers_key) -> String
41
48
  def self.lock_key_from_readers: (String lock_readers_key) -> String
42
- def self.host_identifier_from_acquirer: (String acquirer_id) -> String
49
+ %a{rbs:test:skip} def self.host_identifier_from_acquirer: (String acquirer_id) -> String
43
50
  def self.redis_time_ms: (Array[String] redis_time) -> Integer
44
- def self.calc_initial_acquirer_position: () -> Float
51
+ def self.calc_initial_acquirer_position: (Integer priority) -> Float
45
52
  def self.acquirer_dead_score: (Integer|Float queue_ttl) -> Float
46
- def self.calc_zombie_score: (Float zombie_ttl) -> Float
47
- def self.dead_score_reached?: (Float acquirer_position, Integer queue_ttl) -> bool
48
- def self.lock_key_from_queue: (String lock_queue) -> String
53
+ def self.lock_priority_band_floor: (Integer priority) -> Integer
54
+ def self.lock_priority_band_dead_score: (Float dead_score, Integer priority) -> Float
55
+ def self.lock_request_priority: (Integer|Float acquirer_position) -> Integer
56
+ %a{rbs:test:skip} def self.calc_zombie_score: (Float zombie_ttl) -> Float
57
+ def self.dead_score_reached?: (Float acquirer_position, Integer priority, Integer queue_ttl) -> bool
58
+ def self.lock_key_from_queue: (String lock_queue) -> String?
49
59
  def self.get_thread_id: () -> Integer
50
60
  def self.get_fiber_id: () -> Integer
51
61
  def self.get_ractor_id: () -> Integer
@@ -54,7 +54,7 @@ module RedisQueuedLocks
54
54
  def swarm_loop__start: () -> void
55
55
  def swarm_loop__stop: () -> void
56
56
  def swarm_loop__send_command: (Symbol command) -> swarmLoopReply?
57
- def swarm_element__termiante: () -> void
57
+ def swarm_element__terminate: () -> void
58
58
  end
59
59
  end
60
60
  end
@@ -7,7 +7,8 @@ module RedisQueuedLocks
7
7
  def self?.run_non_critical: () { (?) -> untyped } -> untyped?
8
8
  def self?.ractor_status: (Ractor ractor) -> String
9
9
  def self?.ractor_alive?: (Ractor ractor) -> bool
10
- def self?.thread_state: (Thread thread) -> String
10
+ # NOTE: (rbs test) runs inside the element Ractor (`Isolated.swarm_loop`), see `resource.rbs`;
11
+ %a{rbs:test:skip} def self?.thread_state: (Thread thread) -> String
11
12
  def self?.clock_gettime: () -> Integer
12
13
  def self?.ruby_over_4?: () -> bool
13
14
  end
@@ -10,5 +10,12 @@ module RedisQueuedLocks
10
10
  type loggerObj = Object & _Loggable
11
11
  type instrObj = Object & _Instrumentable
12
12
 
13
+ type readWriteMode = :read | :write
14
+ type accessStrategy = :queued | :random
15
+ type conflictStrategy = :wait_for_lock | :work_through | :extendable_work_through | :dead_locking
16
+ # NOTE: (lock request priorities) an Integer priority or a priority name of
17
+ # `config['lock_priorities']` (resolved by `AcquireLock.acquire_lock`);
18
+ type lockPriority = Integer | Symbol
19
+
13
20
  extend ::RedisQueuedLocks::Debugger::Interface
14
21
  end
@@ -6,6 +6,7 @@ class RedisClient
6
6
  def zscan: (String key, *untyped) { (String member, String score) -> untyped } -> untyped
7
7
  def multi: (?watch: Array[String]) { (Multi transact) -> untyped } -> untyped
8
8
  def with: (?untyped) { (::RedisClient|::RedisClient::Pooled rconn) -> untyped } -> untyped
9
+ def close: () -> void
9
10
  end
10
11
 
11
12
  include _Client
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.20.0
4
+ version: 1.22.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rustam Ibragimov
@@ -38,6 +38,7 @@ files:
38
38
  - ".claude/project-overview.md"
39
39
  - ".claude/rules/acquirer.md"
40
40
  - ".claude/rules/arguments.md"
41
+ - ".claude/rules/changelog.md"
41
42
  - ".claude/rules/git.md"
42
43
  - ".claude/rules/logic.md"
43
44
  - ".claude/rules/swarm.md"
@@ -122,7 +123,7 @@ files:
122
123
  - redis_queued_locks.gemspec
123
124
  - sig/manifest.yml
124
125
  - sig/redis_queued_locks.rbs
125
- - sig/redis_queued_locks/acquier.rbs
126
+ - sig/redis_queued_locks/acquirer.rbs
126
127
  - sig/redis_queued_locks/acquirer/acquire_lock.rbs
127
128
  - sig/redis_queued_locks/acquirer/acquire_lock/delay_execution.rbs
128
129
  - sig/redis_queued_locks/acquirer/acquire_lock/dequeue_from_lock_queue.rbs
@@ -133,7 +134,7 @@ files:
133
134
  - sig/redis_queued_locks/acquirer/acquire_lock/try_to_lock/log_visitor.rbs
134
135
  - sig/redis_queued_locks/acquirer/acquire_lock/with_acq_timeout.rbs
135
136
  - sig/redis_queued_locks/acquirer/acquire_lock/yield_expire.rbs
136
- - sig/redis_queued_locks/acquirer/acquire_lock/yield_with_expire/log_visitor.rbs
137
+ - sig/redis_queued_locks/acquirer/acquire_lock/yield_expire/log_visitor.rbs
137
138
  - sig/redis_queued_locks/acquirer/clear_dead_requests.rbs
138
139
  - sig/redis_queued_locks/acquirer/extend_lock_ttl.rbs
139
140
  - sig/redis_queued_locks/acquirer/is_locked.rbs