redis_queued_locks 1.19.0 → 1.21.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 (80) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/project-overview.md +96 -23
  3. data/.claude/rules/acquirer.md +39 -20
  4. data/.claude/rules/arguments.md +3 -2
  5. data/.claude/rules/git.md +3 -2
  6. data/.claude/rules/logic.md +32 -8
  7. data/.claude/rules/swarm.md +14 -9
  8. data/.claude/rules/tests.md +12 -3
  9. data/.claude/rules/type-checking.md +2 -1
  10. data/.claude/rules/visitors.md +10 -11
  11. data/.claude/skills/rql-code-review/SKILL.md +386 -0
  12. data/.claude/skills/rql-code-review/templates/report.en.md +31 -0
  13. data/.claude/skills/rql-code-review/templates/report.ru.md +31 -0
  14. data/CHANGELOG.md +194 -0
  15. data/CLAUDE.md +6 -3
  16. data/README.md +502 -92
  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 +42 -0
  19. data/lib/redis_queued_locks/acquirer/acquire_lock/log_visitor.rb +45 -0
  20. data/lib/redis_queued_locks/acquirer/acquire_lock/try_to_lock/log_visitor.rb +1 -0
  21. data/lib/redis_queued_locks/acquirer/acquire_lock/try_to_lock.rb +695 -128
  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 +8 -6
  25. data/lib/redis_queued_locks/acquirer/acquire_lock.rb +134 -26
  26. data/lib/redis_queued_locks/acquirer/clear_dead_requests.rb +229 -24
  27. data/lib/redis_queued_locks/acquirer/extend_lock_ttl.rb +189 -18
  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 +151 -7
  31. data/lib/redis_queued_locks/acquirer/lock_info.rb +39 -41
  32. data/lib/redis_queued_locks/acquirer/lock_series_poc/instr_visitor.rb +3 -2
  33. data/lib/redis_queued_locks/acquirer/lock_series_poc/log_visitor.rb +5 -4
  34. data/lib/redis_queued_locks/acquirer/lock_series_poc.rb +79 -20
  35. data/lib/redis_queued_locks/acquirer/locks.rb +212 -83
  36. data/lib/redis_queued_locks/acquirer/queue_info.rb +11 -18
  37. data/lib/redis_queued_locks/acquirer/queues.rb +123 -50
  38. data/lib/redis_queued_locks/acquirer/reindex_locks.rb +253 -0
  39. data/lib/redis_queued_locks/acquirer/release_all_locks.rb +177 -61
  40. data/lib/redis_queued_locks/acquirer/release_lock.rb +84 -25
  41. data/lib/redis_queued_locks/acquirer/release_locks_of.rb +274 -70
  42. data/lib/redis_queued_locks/acquirer/release_read_lock.rb +22 -3
  43. data/lib/redis_queued_locks/acquirer.rb +1 -0
  44. data/lib/redis_queued_locks/client.rb +164 -36
  45. data/lib/redis_queued_locks/config.rb +16 -13
  46. data/lib/redis_queued_locks/errors.rb +34 -4
  47. data/lib/redis_queued_locks/instrument/sampler.rb +4 -7
  48. data/lib/redis_queued_locks/logging/sampler.rb +4 -8
  49. data/lib/redis_queued_locks/resource.rb +113 -6
  50. data/lib/redis_queued_locks/swarm/flush_zombies.rb +333 -61
  51. data/lib/redis_queued_locks/swarm/redis_client_builder.rb +8 -4
  52. data/lib/redis_queued_locks/swarm/swarm_element/threaded.rb +3 -2
  53. data/lib/redis_queued_locks/swarm/zombie_info.rb +203 -53
  54. data/lib/redis_queued_locks/swarm.rb +97 -5
  55. data/lib/redis_queued_locks/utilities.rb +1 -1
  56. data/lib/redis_queued_locks/version.rb +2 -2
  57. data/sig/redis_queued_locks/acquirer/acquire_lock/instr_visitor.rbs +14 -0
  58. data/sig/redis_queued_locks/acquirer/acquire_lock/log_visitor.rbs +13 -0
  59. data/sig/redis_queued_locks/acquirer/acquire_lock/try_to_lock.rbs +107 -1
  60. data/sig/redis_queued_locks/acquirer/acquire_lock/yield_expire.rbs +3 -3
  61. data/sig/redis_queued_locks/acquirer/acquire_lock.rbs +3 -1
  62. data/sig/redis_queued_locks/acquirer/clear_dead_requests.rbs +19 -1
  63. data/sig/redis_queued_locks/acquirer/extend_lock_ttl.rbs +20 -4
  64. data/sig/redis_queued_locks/acquirer/keys.rbs +11 -1
  65. data/sig/redis_queued_locks/acquirer/locks.rbs +15 -6
  66. data/sig/redis_queued_locks/acquirer/queues.rbs +9 -2
  67. data/sig/redis_queued_locks/acquirer/reindex_locks.rbs +52 -0
  68. data/sig/redis_queued_locks/acquirer/release_all_locks.rbs +8 -1
  69. data/sig/redis_queued_locks/acquirer/release_lock.rbs +6 -3
  70. data/sig/redis_queued_locks/acquirer/release_locks_of.rbs +20 -1
  71. data/sig/redis_queued_locks/acquirer/release_read_lock.rbs +1 -1
  72. data/sig/redis_queued_locks/client.rbs +21 -2
  73. data/sig/redis_queued_locks/errors.rbs +5 -2
  74. data/sig/redis_queued_locks/instrument/sampler.rbs +0 -2
  75. data/sig/redis_queued_locks/logging/sampler.rbs +0 -2
  76. data/sig/redis_queued_locks/resource.rbs +7 -1
  77. data/sig/redis_queued_locks/swarm/flush_zombies.rbs +51 -1
  78. data/sig/redis_queued_locks/swarm/zombie_info.rbs +58 -7
  79. data/sig/vendor/redis_client.rbs +2 -0
  80. metadata +6 -1
@@ -6,6 +6,13 @@ module RedisQueuedLocks
6
6
  module AcquireLock
7
7
  module TryToLock
8
8
  EXTEND_LOCK_PTTL: String
9
+ NO_LOCK_DATA: Hash[String, untyped]
10
+ LOCK_STATE_OBTAINER_REPLY: Integer
11
+ LOCK_STATE_REDIS_TIME_REPLY: Integer
12
+ LOCK_STATE_OWN_READ_LOCK_REPLY: Integer
13
+ LOCK_STATE_QUEUE_REPLIES_AT: Integer
14
+ QUEUE_HEAD_REPLY: Integer
15
+ OPPOSITE_QUEUE_HEAD_REPLY: Integer
9
16
 
10
17
  # { ok: bool, result: Symbol }
11
18
  # { ok: bool, result: Symbol }
@@ -31,19 +38,118 @@ module RedisQueuedLocks
31
38
  String lock_key_queue,
32
39
  String read_lock_key_queue,
33
40
  String lock_readers_key,
34
- String read_lock_key,
41
+ String? read_lock_key,
42
+ String lock_name,
35
43
  String acquirer_id,
36
44
  String host_id,
37
45
  Integer|Float acquirer_position,
38
46
  Integer? ttl,
39
47
  Integer queue_ttl,
48
+ bool lock_index_enabled,
49
+ Integer lock_index_grace_period,
40
50
  bool fail_fast,
41
51
  Symbol conflict_strategy,
42
52
  Symbol access_strategy,
43
53
  Hash[String|Symbol,untyped]? meta,
54
+ bool retry_attempt,
44
55
  bool log_sampled,
45
56
  bool instr_sampled
46
57
  ) -> { ok: bool, result: Symbol|Hash[Symbol,untyped] }
58
+
59
+ private
60
+
61
+ def queue_lock_request: (
62
+ RedisClient::Pipeline pipeline,
63
+ String request_queue,
64
+ String opposite_request_queue,
65
+ Integer|Float acquirer_position,
66
+ String acquirer_id,
67
+ Float acquirer_dead_score,
68
+ String lock_name,
69
+ Integer queue_ttl,
70
+ bool lock_index_enabled,
71
+ Integer lock_index_grace_period
72
+ ) -> void
73
+
74
+ def pipeline_lock_state: (
75
+ RedisClient::Pipeline pipeline,
76
+ String lock_key,
77
+ String lock_readers_key,
78
+ String acquirer_id,
79
+ bool read_mode,
80
+ bool queueing,
81
+ String request_queue,
82
+ String opposite_request_queue,
83
+ Integer|Float acquirer_position,
84
+ Float acquirer_dead_score,
85
+ String lock_name,
86
+ Integer queue_ttl,
87
+ bool lock_index_enabled,
88
+ Integer lock_index_grace_period
89
+ ) -> void
90
+
91
+ def find_opposite_request_ahead: (
92
+ Symbol access_strategy,
93
+ [String, Float]? opposite_waiting_request,
94
+ Integer|Float acquirer_position,
95
+ String acquirer_id
96
+ ) -> String?
97
+
98
+ type lockObstacle = :dead_score_reached
99
+ | :acquirer_is_not_first_in_queue
100
+ | :write_request_is_ahead
101
+ | :read_request_is_ahead
102
+ | :lock_is_still_acquired
103
+ | :read_lock_is_still_acquired
104
+
105
+ def lock_obstacle: (
106
+ bool read_mode,
107
+ Symbol access_strategy,
108
+ String acquirer_id,
109
+ String? waiting_acquirer,
110
+ String? opposite_request_ahead,
111
+ String? current_lock_obtainer,
112
+ bool read_locked
113
+ ) -> lockObstacle?
114
+
115
+ def log_lock_obstacle: (
116
+ RC::client rconn,
117
+ Symbol obstacle,
118
+ RQL::loggerObj logger,
119
+ bool log_sampled,
120
+ bool log_lock_try,
121
+ String lock_key,
122
+ Integer queue_ttl,
123
+ String acquirer_id,
124
+ String host_id,
125
+ Symbol access_strategy,
126
+ Symbol read_write_mode,
127
+ String? waiting_acquirer,
128
+ String? opposite_request_ahead,
129
+ String? current_lock_obtainer
130
+ ) -> void
131
+
132
+ def precheck_lock: (
133
+ RC::client rconn,
134
+ RQL::loggerObj logger,
135
+ bool log_sampled,
136
+ bool log_lock_try,
137
+ String lock_key,
138
+ Symbol read_write_mode,
139
+ String lock_readers_key,
140
+ String request_queue,
141
+ String opposite_request_queue,
142
+ String lock_name,
143
+ String acquirer_id,
144
+ String host_id,
145
+ Integer|Float acquirer_position,
146
+ Float acquirer_dead_score,
147
+ Integer queue_ttl,
148
+ bool lock_index_enabled,
149
+ Integer lock_index_grace_period,
150
+ bool fail_fast,
151
+ Symbol access_strategy
152
+ ) -> (lockObstacle | :fail_fast_no_try)?
47
153
  end
48
154
  end
49
155
  end
@@ -12,14 +12,14 @@ module RedisQueuedLocks
12
12
  RQL::loggerObj logger,
13
13
  String lock_key,
14
14
  String lock_readers_key,
15
- String read_lock_key,
15
+ String? read_lock_key,
16
16
  Symbol rw_mode,
17
17
  String acquirer_id,
18
18
  String host_id,
19
19
  Symbol access_strategy,
20
20
  bool timed,
21
21
  Integer|Float ttl_shift,
22
- Integer? ttl,
22
+ Integer ttl,
23
23
  Integer queue_ttl,
24
24
  Hash[String|Symbol,untyped]? meta,
25
25
  bool log_sampled,
@@ -33,7 +33,7 @@ module RedisQueuedLocks
33
33
  def yield_with_timeout: (
34
34
  Float timeout,
35
35
  String lock_key,
36
- Integer? lock_ttl,
36
+ Integer lock_ttl,
37
37
  String acquirer_id,
38
38
  String host_id,
39
39
  Hash[String|Symbol,untyped]? meta,
@@ -19,8 +19,10 @@ module RedisQueuedLocks
19
19
  thread_id: Integer|String,
20
20
  fiber_id: Integer|String,
21
21
  ractor_id: Integer|String,
22
- ttl: Integer?,
22
+ ttl: Integer,
23
23
  queue_ttl: Integer,
24
+ lock_index_enabled: bool,
25
+ lock_index_grace_period: Integer,
24
26
  timeout: Integer?,
25
27
  timed: bool,
26
28
  retry_count: Integer?,
@@ -4,11 +4,14 @@ use RedisClient as RC
4
4
  module RedisQueuedLocks
5
5
  module Acquirer
6
6
  module ClearDeadRequests
7
+ extend RQL::Utilities
8
+
7
9
  type clearResult = { ok: bool, result: { processed_queues: Set[String] } }
8
10
  def self.clear_dead_requests: (
9
11
  RC::client redis_client,
10
12
  Integer scan_size,
11
13
  Integer dead_ttl,
14
+ bool lock_index_enabled,
12
15
  RQL::loggerObj logger,
13
16
  RQL::instrObj instrumenter,
14
17
  untyped? instrument,
@@ -22,7 +25,22 @@ module RedisQueuedLocks
22
25
  bool instr_sample_this
23
26
  ) -> clearResult
24
27
 
25
- private def self.each_lock_queue: (RC::client redis_client, Integer scan_size) { (String lock_queue) -> untyped } -> Enumerator[String]
28
+ private def self.fully_clear_dead_requests: (
29
+ RC::client redis_client,
30
+ Integer scan_size,
31
+ Integer dead_ttl,
32
+ bool lock_index_enabled
33
+ ) -> Set[String]
34
+
35
+ private def self.each_lock_queue: (RC::client redis_client, Integer scan_size) { (String lock_queue) -> void } -> void
36
+ private def self.drop_dead_requests: (RC::client redis_client, Array[String] lock_queues, Float dead_score) -> void
37
+ private def self.drop_dead_requests_of_locks: (
38
+ RC::client redis_client,
39
+ Array[String] lock_names,
40
+ Float dead_score,
41
+ Set[String] processed_queues
42
+ ) -> void
43
+ private def self.each_lock_name_batch: (RC::client redis_client, Integer scan_size) { (Array[String] lock_names) -> void } -> void
26
44
  end
27
45
  end
28
46
  end
@@ -4,6 +4,8 @@ use RedisClient as RC
4
4
  module RedisQueuedLocks
5
5
  module Acquirer
6
6
  module ExtendLockTTL
7
+ extend RQL::Utilities
8
+
7
9
  EXTEND_LOCK_PTTL: String
8
10
 
9
11
  type extendResult = { ok: bool, result: { extended_locks_count: Integer } | Symbol }
@@ -14,32 +16,46 @@ module RedisQueuedLocks
14
16
  Symbol read_write_mode,
15
17
  bool all_read_locks,
16
18
  String acquirer_id,
19
+ bool lock_index_enabled,
17
20
  RQL::loggerObj logger,
18
21
  RQL::instrObj instrumenter,
19
22
  untyped? instrument,
20
- bool log_samling_enabled,
23
+ bool log_sampling_enabled,
21
24
  Integer log_sampling_percent,
22
25
  RQL::Logging::samplerObj log_sampler,
23
- bool sample_this,
26
+ bool log_sample_this,
24
27
  bool instr_sampling_enabled,
25
28
  Integer instr_sampling_percent,
26
29
  RQL::Instrument::samplerObj instr_sampler,
27
30
  bool instr_sample_this
28
31
  ) -> extendResult
29
32
 
33
+ private def self.fully_extend_lock_ttl: (
34
+ RC::client redis_client,
35
+ String lock_name,
36
+ String lock_key,
37
+ Integer milliseconds,
38
+ Symbol read_write_mode,
39
+ bool all_read_locks,
40
+ String acquirer_id,
41
+ bool lock_index_enabled
42
+ ) -> extendResult
43
+
30
44
  private def self.extend_read_lock_ttl: (
31
45
  RC::client redis_client,
32
46
  String lock_name,
33
47
  String lock_key,
34
48
  String acquirer_id,
35
- Integer milliseconds
49
+ Integer milliseconds,
50
+ bool lock_index_enabled
36
51
  ) -> extendResult
37
52
 
38
53
  private def self.extend_all_read_locks_ttl: (
39
54
  RC::client redis_client,
40
55
  String lock_name,
41
56
  String lock_key,
42
- Integer milliseconds
57
+ Integer milliseconds,
58
+ bool lock_index_enabled
43
59
  ) -> extendResult
44
60
  end
45
61
  end
@@ -4,7 +4,17 @@ module RedisQueuedLocks
4
4
  module Acquirer
5
5
  module Keys
6
6
  type keyList = Set[String]
7
- def self.keys: (RC::client redis_client, scan_size: Integer) -> keyList
7
+
8
+ KEY_STATE_REPLIES: Integer
9
+
10
+ def self.keys: (
11
+ RC::client redis_client,
12
+ scan_size: Integer,
13
+ lock_index_enabled: bool
14
+ ) -> keyList
15
+
16
+ private def self.collect_lock_keys: (RC::client redis_client, Array[String] lock_names, keyList keyset) -> void
17
+ private def self.each_lock_name_batch: (RC::client redis_client, Integer scan_size) { (Array[String] lock_names) -> void } -> void
8
18
  end
9
19
  end
10
20
  end
@@ -9,16 +9,25 @@ module RedisQueuedLocks
9
9
  type locksInfo = Set[{ lock: String, status: Symbol, info: lockInfo }]
10
10
  type locks = lockList | locksInfo
11
11
 
12
- def self.locks: (RC::client redis_client, scan_size: Integer, with_info: bool) -> locks
12
+ LOCK_STATE_REPLIES: Integer
13
+
14
+ def self.locks: (
15
+ RC::client redis_client,
16
+ scan_size: Integer,
17
+ with_info: bool,
18
+ lock_index_enabled: bool
19
+ ) -> locks
13
20
 
14
21
  private def self.scan_locks: (RC::client redis_client, Integer scan_size) -> lockList
15
- private def self.extract_locks_info: (RC::client redis_client, Set[::String] lock_keys) -> locksInfo
22
+ private def self.index_locks: (RC::client redis_client, Integer scan_size) -> lockList
23
+ private def self.each_lock_name_batch: (RC::client redis_client, Integer scan_size) { (Array[String] lock_names) -> void } -> void
24
+ private def self.extract_locks_info: (RC::client redis_client, Set[::String] lock_keys, Integer scan_size) -> locksInfo
16
25
  private def self.read_lock_info: (
17
- RC::client redis_client,
18
- String lock_name,
19
26
  String lock_key,
20
- Array[String] redis_time,
21
- Array[[String, Float]] read_locks
27
+ Integer now,
28
+ Array[[String, Float]] live_read_locks,
29
+ Array[Hash[String,String]] read_locks_data,
30
+ Integer read_locks_data_at
22
31
  ) -> lockInfo?
23
32
  end
24
33
  end
@@ -7,10 +7,17 @@ module RedisQueuedLocks
7
7
  type queuesInfo = Set[{ queue: String, requests: Array[Hash[String,String|Float]] }]
8
8
  type queues = queueList | queuesInfo
9
9
 
10
- def self.queues: (RC::client redis_client, scan_size: Integer, with_info: bool) -> queues
10
+ def self.queues: (
11
+ RC::client redis_client,
12
+ scan_size: Integer,
13
+ with_info: bool,
14
+ lock_index_enabled: bool
15
+ ) -> queues
11
16
 
12
17
  private def self.scan_queues: (RC::client redis_client, Integer scan_size) -> queueList
13
- private def self.extract_queues_info: (RC::client redis_client, Set[String] lock_queues) -> queuesInfo
18
+ private def self.index_queues: (RC::client redis_client, Integer scan_size) -> queueList
19
+ private def self.each_lock_name_batch: (RC::client redis_client, Integer scan_size) { (Array[String] lock_names) -> void } -> void
20
+ private def self.extract_queues_info: (RC::client redis_client, Set[String] lock_queues, Integer scan_size) -> queuesInfo
14
21
  end
15
22
  end
16
23
  end
@@ -0,0 +1,52 @@
1
+ use RedisQueuedLocks as RQL
2
+ use RedisClient as RC
3
+
4
+ module RedisQueuedLocks
5
+ module Acquirer
6
+ module ReindexLocks
7
+ extend RQL::Utilities
8
+
9
+ type reindexResult = { ok: bool, result: { idx_key_cnt: Integer } }
10
+ def self.reindex_locks: (
11
+ RC::client redis_client,
12
+ Integer scan_size,
13
+ Integer queue_ttl,
14
+ Integer lock_index_grace_period,
15
+ RQL::loggerObj logger,
16
+ RQL::instrObj instrumenter,
17
+ untyped? instrument,
18
+ bool log_sampling_enabled,
19
+ Integer log_sampling_percent,
20
+ RQL::Logging::samplerObj log_sampler,
21
+ bool log_sample_this,
22
+ bool instr_sampling_enabled,
23
+ Integer instr_sampling_percent,
24
+ RQL::Instrument::samplerObj instr_sampler,
25
+ bool instr_sample_this
26
+ ) -> reindexResult
27
+
28
+ private def self.fully_reindex_locks: (
29
+ RC::client redis_client,
30
+ Integer scan_size,
31
+ Integer queue_ttl,
32
+ Integer lock_index_grace_period
33
+ ) -> Integer
34
+
35
+ private def self.index_lock_keys: (
36
+ RC::client redis_client,
37
+ Array[String] lock_keys,
38
+ Array[String] lock_queues,
39
+ Integer queue_pttl,
40
+ Integer lock_index_grace_period
41
+ ) -> Integer
42
+
43
+ private def self.index_lock_key: (
44
+ RedisClient::Pipeline pipeline,
45
+ String key,
46
+ Integer key_ttl,
47
+ Integer lock_index_time,
48
+ Integer lock_index_grace_period
49
+ ) -> Integer
50
+ end
51
+ end
52
+ end
@@ -10,6 +10,7 @@ module RedisQueuedLocks
10
10
  def self.release_all_locks: (
11
11
  RC::client redis,
12
12
  Integer batch_size,
13
+ bool lock_index_enabled,
13
14
  RQL::loggerObj logger,
14
15
  RQL::instrObj instrumenter,
15
16
  untyped instrument,
@@ -24,7 +25,13 @@ module RedisQueuedLocks
24
25
  ) -> releaseResult
25
26
 
26
27
  type fullRelesaeResult = { ok: bool, result: { rel_key_cnt: Integer } }
27
- private def self.fully_release_all_locks: (RC::client redis, Integer batch_size) -> fullRelesaeResult
28
+ private def self.fully_release_all_locks: (
29
+ RC::client redis,
30
+ Integer batch_size,
31
+ bool lock_index_enabled
32
+ ) -> fullRelesaeResult
33
+ private def self.release_locks: (RC::client redis_client, Array[String] lock_names) -> Integer
34
+ private def self.each_lock_name_batch: (RC::client redis_client, Integer scan_size) { (Array[String] lock_names) -> void } -> void
28
35
  end
29
36
  end
30
37
  end
@@ -19,10 +19,12 @@ module RedisQueuedLocks
19
19
  def self.release_lock: (
20
20
  RC::client redis,
21
21
  String lock_name,
22
- RQL::instrObj instrumenter,
22
+ bool lock_index_enabled,
23
23
  RQL::loggerObj logger,
24
+ RQL::instrObj instrumenter,
25
+ untyped? instrument,
24
26
  bool log_sampling_enabled,
25
- Integer log_samplingPercent,
27
+ Integer log_sampling_percent,
26
28
  RQL::Logging::samplerObj log_sampler,
27
29
  bool log_sample_this,
28
30
  bool instr_sampling_enabled,
@@ -38,7 +40,8 @@ module RedisQueuedLocks
38
40
  String lock_key,
39
41
  String lock_key_queue,
40
42
  String read_lock_key_queue,
41
- String lock_readers_key
43
+ String lock_readers_key,
44
+ bool lock_index_enabled
42
45
  ) -> fullReleaseResult
43
46
  end
44
47
  end
@@ -20,6 +20,7 @@ module RedisQueuedLocks
20
20
  RC::client redis,
21
21
  Integer lock_scan_size,
22
22
  Integer queue_scan_size,
23
+ bool lock_index_enabled,
23
24
  RQL::loggerObj logger,
24
25
  RQL::instrObj instrumenter,
25
26
  untyped instrument,
@@ -39,8 +40,26 @@ module RedisQueuedLocks
39
40
  String refused_acquirer_id,
40
41
  RC::client redis,
41
42
  Integer locks_scan_size,
42
- Integer queue_scan_size
43
+ Integer queue_scan_size,
44
+ bool lock_index_enabled
43
45
  ) -> fullyReleaseAllLocksResult
46
+ private def self.release_refused_locks: (
47
+ RC::client redis_client,
48
+ Array[String] lock_keys,
49
+ String refused_host_id,
50
+ String refused_acquirer_id
51
+ ) -> Integer
52
+ private def self.release_refused_read_locks: (
53
+ RC::client redis_client,
54
+ Array[String] lock_readers_keys,
55
+ String refused_acquirer_id
56
+ ) -> Integer
57
+ private def self.dequeue_refused_acquirer: (
58
+ RC::client redis_client,
59
+ Array[String] lock_queues,
60
+ String refused_acquirer_id
61
+ ) -> Integer
62
+ private def self.each_lock_name_batch: (RC::client redis_client, Integer scan_size) { (Array[String] lock_names) -> void } -> void
44
63
  end
45
64
  end
46
65
  end
@@ -19,8 +19,8 @@ module RedisQueuedLocks
19
19
  RC::client redis,
20
20
  String lock_name,
21
21
  String acquirer_id,
22
- RQL::instrObj instrumenter,
23
22
  RQL::loggerObj logger,
23
+ RQL::instrObj instrumenter,
24
24
  untyped? instrument,
25
25
  bool log_sampling_enabled,
26
26
  Integer log_sampling_percent,
@@ -36,6 +36,7 @@ module RedisQueuedLocks
36
36
  String lock_name,
37
37
  ?ttl: Integer,
38
38
  ?queue_ttl: Integer,
39
+ ?lock_index_grace_period: Integer,
39
40
  ?timeout: Integer?,
40
41
  ?timed: bool,
41
42
  ?retry_count: Integer?,
@@ -67,6 +68,7 @@ module RedisQueuedLocks
67
68
  String lock_name,
68
69
  ?ttl: Integer,
69
70
  ?queue_ttl: Integer,
71
+ ?lock_index_grace_period: Integer,
70
72
  ?timeout: Integer?,
71
73
  ?timed: bool,
72
74
  ?retry_count: Integer?,
@@ -139,7 +141,7 @@ module RedisQueuedLocks
139
141
  ?ractor_id: Integer|String,
140
142
  ?identity: String
141
143
  ) -> String
142
- alias ccurrent_acq_id current_acquirer_id
144
+ alias current_acq_id current_acquirer_id
143
145
  alias acq_id current_acquirer_id
144
146
 
145
147
  def current_host_id: (
@@ -234,7 +236,7 @@ module RedisQueuedLocks
234
236
  | (?scan_size: Integer, ?with_info: true) -> RQL::Acquirer::Queues::queuesInfo
235
237
  | (?scan_size: Integer, ?with_info: false) -> RQL::Acquirer::Queues::queueList
236
238
 
237
- def queues_info: (?scan_size: Integer) -> RQL::Acquirer::Queues::queues
239
+ def queues_info: (?scan_size: Integer) -> RQL::Acquirer::Queues::queuesInfo
238
240
  def keys: (?scan_size: Integer) -> RQL::Acquirer::Keys::keyList
239
241
 
240
242
  def clear_dead_requests: (
@@ -252,5 +254,22 @@ module RedisQueuedLocks
252
254
  ?instr_sampler: RQL::Instrument::samplerObj,
253
255
  ?instr_sample_this: bool
254
256
  ) -> RQL::Acquirer::ClearDeadRequests::clearResult
257
+
258
+ def reindex_locks: (
259
+ ?scan_size: Integer,
260
+ ?queue_ttl: Integer,
261
+ ?lock_index_grace_period: Integer,
262
+ ?logger: RQL::loggerObj,
263
+ ?instrumenter: RQL::instrObj,
264
+ ?instrument: untyped?,
265
+ ?log_sampling_enabled: bool,
266
+ ?log_sampling_percent: Integer,
267
+ ?log_sampler: RQL::Logging::samplerObj,
268
+ ?log_sample_this: bool,
269
+ ?instr_sampling_enabled: bool,
270
+ ?instr_sampling_percent: Integer,
271
+ ?instr_sampler: RQL::Instrument::samplerObj,
272
+ ?instr_sample_this: bool
273
+ ) -> RQL::Acquirer::ReindexLocks::reindexResult
255
274
  end
256
275
  end
@@ -5,10 +5,13 @@ module RedisQueuedLocks
5
5
  class ArgumentError < ::ArgumentError
6
6
  end
7
7
 
8
+ class Exception < ::Exception
9
+ end
10
+
8
11
  class LockAlreadyObtainedError < Error
9
12
  end
10
13
 
11
- class LockAcquirementIntermediateTimeoutError < ::Timeout::Error
14
+ class LockAcquirementIntermediateTimeoutError < Exception
12
15
  end
13
16
 
14
17
  class LockAcquirementTimeoutError < Error
@@ -17,7 +20,7 @@ module RedisQueuedLocks
17
20
  class LockAcquirementRetryLimitError < Error
18
21
  end
19
22
 
20
- class TimedLockIntermediateTimeoutError < ::Timeout::Error
23
+ class TimedLockIntermediateTimeoutError < Exception
21
24
  end
22
25
 
23
26
  class TimedLockTimeoutError < Error
@@ -1,8 +1,6 @@
1
1
  module RedisQueuedLocks
2
2
  module Instrument
3
3
  module Sampler
4
- SAMPLING_PERCENT_RANGE: Range[Integer]
5
-
6
4
  def self.sampling_happened?: (Integer sampling_percent) -> bool
7
5
  end
8
6
  end
@@ -1,8 +1,6 @@
1
1
  module RedisQueuedLocks
2
2
  module Logging
3
3
  module Sampler
4
- SAMPLING_PERCENT_RANGE: Range[Integer]
5
-
6
4
  def self.sampling_happened?: (Integer sampling_percent) -> bool
7
5
  end
8
6
  end
@@ -6,7 +6,9 @@ module RedisQueuedLocks
6
6
  READ_LOCK_QUEUE_PATTERN: String
7
7
  LOCK_READERS_PATTERN: String
8
8
  READ_LOCK_PATTERN: String
9
+ ALL_LOCK_QUEUES_PATTERN: String
9
10
  SWARM_KEY: String
11
+ LOCK_INDEX_KEY: String
10
12
  REDIS_TIMESHIFT_ERROR: Integer
11
13
 
12
14
  def self.calc_uniq_identity: () -> String
@@ -31,6 +33,10 @@ module RedisQueuedLocks
31
33
  def self.prepare_lock_readers: (String lock_name) -> String
32
34
  def self.prepare_read_lock_key: (String lock_name, String acquirer_id) -> String
33
35
  def self.lock_queue_rw_mode: (String lock_queue) -> String?
36
+ type lockKeyFamily = :lock | :lock_queue | :lock_readers | :read_lock_queue | :read_lock
37
+ def self.lock_key_family: (String key) -> lockKeyFamily?
38
+ def self.lock_name_from_key: (String key, lockKeyFamily? key_family) -> String?
39
+ def self.lock_index_time: () -> Integer
34
40
  def self.lock_name_from_readers: (String lock_readers_key) -> String
35
41
  def self.lock_key_from_readers: (String lock_readers_key) -> String
36
42
  def self.host_identifier_from_acquirer: (String acquirer_id) -> String
@@ -39,7 +45,7 @@ module RedisQueuedLocks
39
45
  def self.acquirer_dead_score: (Integer|Float queue_ttl) -> Float
40
46
  def self.calc_zombie_score: (Float zombie_ttl) -> Float
41
47
  def self.dead_score_reached?: (Float acquirer_position, Integer queue_ttl) -> bool
42
- def self.lock_key_from_queue: (String lock_queue) -> String
48
+ def self.lock_key_from_queue: (String lock_queue) -> String?
43
49
  def self.get_thread_id: () -> Integer
44
50
  def self.get_fiber_id: () -> Integer
45
51
  def self.get_ractor_id: () -> Integer
@@ -4,7 +4,57 @@ module RedisQueuedLocks
4
4
  class Swarm
5
5
  class FlushZombies < SwarmElement::Isolated
6
6
  type flushedZombies = { ok: bool, deleted_zombie_hosts: Set[String], deleted_zombie_acquirers: Set[String], deleted_zombie_locks: Set[String] }
7
- def self.flush_zombies: (RC::client redis_client, Integer zombie_ttl, Integer lock_scan_size, Integer queue_scan_size) -> flushedZombies
7
+ def self.flush_zombies: (
8
+ RC::client redis_client,
9
+ Integer zombie_ttl,
10
+ Integer lock_scan_size,
11
+ Integer queue_scan_size,
12
+ bool lock_index_enabled
13
+ ) -> flushedZombies
14
+ private def self.flush_keyspace_zombies: (
15
+ RC::client rconn,
16
+ Set[String] zombie_hosts,
17
+ Integer lock_scan_size,
18
+ Integer queue_scan_size,
19
+ Set[String] zombie_locks,
20
+ Set[String] zombie_acquirers
21
+ ) -> void
22
+ private def self.flush_lock_index_zombies: (
23
+ RC::client rconn,
24
+ Set[String] zombie_hosts,
25
+ Integer lock_scan_size,
26
+ Integer queue_scan_size,
27
+ Set[String] zombie_locks,
28
+ Set[String] zombie_acquirers
29
+ ) -> void
30
+ private def self.batch_zombie_requests: (
31
+ RC::client redis_client,
32
+ Array[String] lock_queues,
33
+ String lock_queue,
34
+ Integer queue_scan_size,
35
+ Set[String] zombie_hosts,
36
+ Set[String] zombie_acquirers
37
+ ) -> void
38
+ private def self.flush_zombie_locks: (
39
+ RC::client redis_client,
40
+ Array[String] lock_keys,
41
+ Set[String] zombie_hosts,
42
+ Set[String] zombie_locks,
43
+ Set[String] zombie_acquirers
44
+ ) -> void
45
+ private def self.flush_zombie_read_locks: (
46
+ RC::client redis_client,
47
+ Array[String] lock_readers_keys,
48
+ Set[String] zombie_hosts,
49
+ Set[String] zombie_locks,
50
+ Set[String] zombie_acquirers
51
+ ) -> void
52
+ private def self.flush_zombie_requests: (
53
+ RC::client redis_client,
54
+ Array[String] lock_queues,
55
+ Set[String] zombie_hosts,
56
+ Set[String] zombie_acquirers
57
+ ) -> void
8
58
 
9
59
  def enabled?: () -> bool
10
60
  def spawn_swarm_element!: (Ractor::Port[SwarmElement::Isolated::resultsPortMessage] swarm_element_results_port) -> Ractor