redis_queued_locks 1.12.0 → 1.13.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 (121) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -1
  3. data/.ruby-version +1 -1
  4. data/CHANGELOG.md +42 -5
  5. data/LICENSE.txt +1 -1
  6. data/README.md +231 -203
  7. data/Rakefile +12 -4
  8. data/Steepfile +16 -0
  9. data/github_ci/ruby3.3.gemfile +17 -0
  10. data/github_ci/ruby3.3.gemfile.lock +217 -0
  11. data/lib/redis_queued_locks/{acquier → acquirer}/acquire_lock/delay_execution.rb +4 -4
  12. data/lib/redis_queued_locks/acquirer/acquire_lock/dequeue_from_lock_queue/log_visitor.rb +40 -0
  13. data/lib/redis_queued_locks/{acquier → acquirer}/acquire_lock/dequeue_from_lock_queue.rb +17 -8
  14. data/lib/redis_queued_locks/acquirer/acquire_lock/instr_visitor.rb +166 -0
  15. data/lib/redis_queued_locks/acquirer/acquire_lock/log_visitor.rb +218 -0
  16. data/lib/redis_queued_locks/acquirer/acquire_lock/try_to_lock/log_visitor.rb +543 -0
  17. data/lib/redis_queued_locks/{acquier → acquirer}/acquire_lock/try_to_lock.rb +126 -92
  18. data/lib/redis_queued_locks/{acquier → acquirer}/acquire_lock/with_acq_timeout.rb +14 -13
  19. data/lib/redis_queued_locks/acquirer/acquire_lock/yield_expire/log_visitor.rb +76 -0
  20. data/lib/redis_queued_locks/{acquier → acquirer}/acquire_lock/yield_expire.rb +43 -20
  21. data/lib/redis_queued_locks/{acquier → acquirer}/acquire_lock.rb +69 -42
  22. data/lib/redis_queued_locks/{acquier → acquirer}/clear_dead_requests.rb +5 -3
  23. data/lib/redis_queued_locks/{acquier → acquirer}/extend_lock_ttl.rb +4 -3
  24. data/lib/redis_queued_locks/{acquier → acquirer}/is_locked.rb +1 -1
  25. data/lib/redis_queued_locks/{acquier → acquirer}/is_queued.rb +1 -1
  26. data/lib/redis_queued_locks/{acquier → acquirer}/keys.rb +5 -5
  27. data/lib/redis_queued_locks/{acquier → acquirer}/lock_info.rb +9 -5
  28. data/lib/redis_queued_locks/{acquier → acquirer}/locks.rb +16 -3
  29. data/lib/redis_queued_locks/{acquier → acquirer}/queue_info.rb +8 -6
  30. data/lib/redis_queued_locks/{acquier → acquirer}/queues.rb +9 -2
  31. data/lib/redis_queued_locks/{acquier → acquirer}/release_all_locks.rb +23 -18
  32. data/lib/redis_queued_locks/{acquier → acquirer}/release_lock.rb +25 -19
  33. data/lib/redis_queued_locks/acquirer.rb +18 -0
  34. data/lib/redis_queued_locks/client.rb +164 -254
  35. data/lib/redis_queued_locks/config/dsl.rb +94 -0
  36. data/lib/redis_queued_locks/config.rb +231 -0
  37. data/lib/redis_queued_locks/data.rb +2 -0
  38. data/lib/redis_queued_locks/errors.rb +27 -11
  39. data/lib/redis_queued_locks/instrument.rb +11 -4
  40. data/lib/redis_queued_locks/logging/void_logger.rb +38 -1
  41. data/lib/redis_queued_locks/logging.rb +20 -5
  42. data/lib/redis_queued_locks/resource.rb +49 -11
  43. data/lib/redis_queued_locks/swarm/acquirers.rb +17 -16
  44. data/lib/redis_queued_locks/swarm/flush_zombies.rb +26 -25
  45. data/lib/redis_queued_locks/swarm/probe_hosts.rb +20 -19
  46. data/lib/redis_queued_locks/swarm/redis_client_builder.rb +3 -3
  47. data/lib/redis_queued_locks/swarm/supervisor.rb +19 -6
  48. data/lib/redis_queued_locks/swarm/swarm_element/isolated.rb +20 -18
  49. data/lib/redis_queued_locks/swarm/swarm_element/threaded.rb +35 -27
  50. data/lib/redis_queued_locks/swarm/zombie_info.rb +9 -9
  51. data/lib/redis_queued_locks/swarm.rb +20 -41
  52. data/lib/redis_queued_locks/utilities/lock.rb +4 -2
  53. data/lib/redis_queued_locks/utilities.rb +2 -2
  54. data/lib/redis_queued_locks/version.rb +2 -2
  55. data/lib/redis_queued_locks.rb +2 -2
  56. data/rbs_collection.lock.yaml +40 -0
  57. data/rbs_collection.yaml +16 -0
  58. data/redis_queued_locks.gemspec +22 -23
  59. data/sig/manifest.yml +7 -0
  60. data/sig/redis_queued_locks/acquier.rbs +4 -0
  61. data/sig/redis_queued_locks/acquirer/acquire_lock/delay_execution.rbs +9 -0
  62. data/sig/redis_queued_locks/acquirer/acquire_lock/dequeue_from_lock_queue/log_visitor.rbs +21 -0
  63. data/sig/redis_queued_locks/acquirer/acquire_lock/dequeue_from_lock_queue.rbs +26 -0
  64. data/sig/redis_queued_locks/acquirer/acquire_lock/instr_visitor.rbs +71 -0
  65. data/sig/redis_queued_locks/acquirer/acquire_lock/log_visitor.rbs +72 -0
  66. data/sig/redis_queued_locks/acquirer/acquire_lock/try_to_lock/log_visitor.rbs +179 -0
  67. data/sig/redis_queued_locks/acquirer/acquire_lock/try_to_lock.rbs +48 -0
  68. data/sig/redis_queued_locks/acquirer/acquire_lock/with_acq_timeout.rbs +19 -0
  69. data/sig/redis_queued_locks/acquirer/acquire_lock/yield_expire.rbs +41 -0
  70. data/sig/redis_queued_locks/acquirer/acquire_lock/yield_with_expire/log_visitor.rbs +32 -0
  71. data/sig/redis_queued_locks/acquirer/acquire_lock.rbs +51 -0
  72. data/sig/redis_queued_locks/acquirer/clear_dead_requests.rbs +28 -0
  73. data/sig/redis_queued_locks/acquirer/extend_lock_ttl.rbs +28 -0
  74. data/sig/redis_queued_locks/acquirer/is_locked.rbs +9 -0
  75. data/sig/redis_queued_locks/acquirer/is_queued.rbs +9 -0
  76. data/sig/redis_queued_locks/acquirer/keys.rbs +10 -0
  77. data/sig/redis_queued_locks/acquirer/lock_info.rbs +10 -0
  78. data/sig/redis_queued_locks/acquirer/locks.rbs +16 -0
  79. data/sig/redis_queued_locks/acquirer/queue_info.rbs +13 -0
  80. data/sig/redis_queued_locks/acquirer/queues.rbs +16 -0
  81. data/sig/redis_queued_locks/acquirer/release_all_locks.rbs +30 -0
  82. data/sig/redis_queued_locks/acquirer/release_lock.rbs +38 -0
  83. data/sig/redis_queued_locks/client.rbs +195 -0
  84. data/sig/redis_queued_locks/config/dsl.rbs +26 -0
  85. data/sig/redis_queued_locks/config.rbs +23 -0
  86. data/sig/redis_queued_locks/data.rbs +4 -0
  87. data/sig/redis_queued_locks/debugger/interface.rbs +9 -0
  88. data/sig/redis_queued_locks/debugger.rbs +13 -0
  89. data/sig/redis_queued_locks/errors.rbs +43 -0
  90. data/sig/redis_queued_locks/instrument/active_support.rbs +7 -0
  91. data/sig/redis_queued_locks/instrument/sampler.rbs +9 -0
  92. data/sig/redis_queued_locks/instrument/void_notifier.rbs +7 -0
  93. data/sig/redis_queued_locks/instrument.rbs +15 -0
  94. data/sig/redis_queued_locks/logging/sampler.rbs +9 -0
  95. data/sig/redis_queued_locks/logging/void_logger.rbs +15 -0
  96. data/sig/redis_queued_locks/logging.rbs +15 -0
  97. data/sig/redis_queued_locks/resource.rbs +42 -0
  98. data/sig/redis_queued_locks/swarm/acquirers.rbs +10 -0
  99. data/sig/redis_queued_locks/swarm/flush_zombies.rbs +13 -0
  100. data/sig/redis_queued_locks/swarm/probe_hosts.rbs +13 -0
  101. data/sig/redis_queued_locks/swarm/redis_client_builder.rbs +19 -0
  102. data/sig/redis_queued_locks/swarm/supervisor.rbs +26 -0
  103. data/sig/redis_queued_locks/swarm/swarm_element/isolated.rbs +52 -0
  104. data/sig/redis_queued_locks/swarm/swarm_element/threaded.rbs +61 -0
  105. data/sig/redis_queued_locks/swarm/swarm_element.rbs +8 -0
  106. data/sig/redis_queued_locks/swarm/zombie_info.rbs +24 -0
  107. data/sig/redis_queued_locks/swarm.rbs +41 -0
  108. data/sig/redis_queued_locks/utilities/lock.rbs +10 -0
  109. data/sig/redis_queued_locks/utilities.rbs +11 -0
  110. data/sig/redis_queued_locks/version.rbs +3 -0
  111. data/sig/redis_queued_locks.rbs +14 -0
  112. data/sig/vendor/active_support.rbs +9 -0
  113. data/sig/vendor/redis_client.rbs +39 -0
  114. data/sig/vendor/semantic_logger.rbs +4 -0
  115. metadata +96 -54
  116. data/lib/redis_queued_locks/acquier/acquire_lock/dequeue_from_lock_queue/log_visitor.rb +0 -40
  117. data/lib/redis_queued_locks/acquier/acquire_lock/instr_visitor.rb +0 -166
  118. data/lib/redis_queued_locks/acquier/acquire_lock/log_visitor.rb +0 -216
  119. data/lib/redis_queued_locks/acquier/acquire_lock/try_to_lock/log_visitor.rb +0 -541
  120. data/lib/redis_queued_locks/acquier/acquire_lock/yield_expire/log_visitor.rb +0 -76
  121. data/lib/redis_queued_locks/acquier.rb +0 -18
@@ -35,7 +35,7 @@ class RedisQueuedLocks::Swarm::SwarmElement::Threaded
35
35
  # @since 1.9.0
36
36
  attr_reader :swarm_element_commands
37
37
 
38
- # @return [Thread::SizedQueue]
38
+ # @return [Thread::SizedQueue,NilClass]
39
39
  #
40
40
  # @api private
41
41
  # @since 1.9.0
@@ -106,7 +106,7 @@ class RedisQueuedLocks::Swarm::SwarmElement::Threaded
106
106
  #
107
107
  # @api private
108
108
  # @since 1.9.0
109
- def enabled?
109
+ def enabled? # steep:ignore
110
110
  # NOTE: provide an <is enabled> logic here by analyzing the redis queued locks config.
111
111
  end
112
112
 
@@ -129,12 +129,12 @@ class RedisQueuedLocks::Swarm::SwarmElement::Threaded
129
129
  def status
130
130
  sync.synchronize do
131
131
  thread_running = swarmed__alive?
132
- thread_state = swarmed? ? thread_state(swarm_element) : 'non_initialized'
132
+ thread_state = swarmed? ? thread_state(swarm_element) : 'non_initialized' # steep:ignore
133
133
 
134
134
  main_loop_running = swarmed__running?
135
135
  main_loop_state = begin
136
136
  if main_loop_running
137
- swarm_loop__status[:result][:main_loop][:state]
137
+ swarm_loop__status[:result][:main_loop][:state] # steep:ignore
138
138
  else
139
139
  'non_initialized'
140
140
  end
@@ -179,26 +179,34 @@ class RedisQueuedLocks::Swarm::SwarmElement::Threaded
179
179
 
180
180
  @swarm_element = Thread.new do
181
181
  loop do
182
- command = swarm_element_commands.pop
182
+ command = swarm_element_commands.pop # steep:ignore
183
183
 
184
184
  case command
185
185
  when :status
186
+ # steep:ignore:start
186
187
  main_loop_alive = main_loop != nil && main_loop.alive?
188
+ # steep:ignore:end
189
+
190
+ # steep:ignore:start
187
191
  main_loop_state = (main_loop == nil) ? 'non_initialized' : thread_state(main_loop)
192
+ # steep:ignore:end
193
+
194
+ # steep:ignore:start
188
195
  swarm_element_results.push({
189
196
  ok: true,
190
197
  result: { main_loop: { alive: main_loop_alive, state: main_loop_state } }
191
198
  })
199
+ # steep:ignore:end
192
200
  when :is_active
193
- is_active = main_loop != nil && main_loop.alive?
194
- swarm_element_results.push({ ok: true, result: { is_active: } })
201
+ is_active = main_loop != nil && main_loop.alive? # steep:ignore
202
+ swarm_element_results.push({ ok: true, result: { is_active: } }) # steep:ignore
195
203
  when :start
196
204
  main_loop&.kill
197
205
  @main_loop = spawn_main_loop!.tap { |thread| thread.abort_on_exception = false }
198
- swarm_element_results.push({ ok: true, result: nil })
206
+ swarm_element_results.push({ ok: true, result: nil }) # steep:ignore
199
207
  when :stop
200
208
  main_loop&.kill
201
- swarm_element_results.push({ ok: true, result: nil })
209
+ swarm_element_results.push({ ok: true, result: nil }) # steep:ignore
202
210
  end
203
211
  end
204
212
  end
@@ -209,7 +217,7 @@ class RedisQueuedLocks::Swarm::SwarmElement::Threaded
209
217
  #
210
218
  # @api private
211
219
  # @since 1.9.0
212
- def spawn_main_loop!
220
+ def spawn_main_loop! # steep:ignore
213
221
  # NOTE:
214
222
  # - provide the swarm element looped logic here wrapped into the thread;
215
223
  # - created thread will be reconfigured inside the swarm_element logic with a
@@ -238,7 +246,7 @@ class RedisQueuedLocks::Swarm::SwarmElement::Threaded
238
246
  # @api private
239
247
  # @since 1.9.0
240
248
  def swarmed__alive?
241
- swarmed? && swarm_element.alive? && !terminating?
249
+ swarmed? && swarm_element.alive? && !terminating? # steep:ignore
242
250
  end
243
251
 
244
252
  # @return [Boolean]
@@ -246,7 +254,7 @@ class RedisQueuedLocks::Swarm::SwarmElement::Threaded
246
254
  # @api private
247
255
  # @since 1.9.0
248
256
  def swarmed__dead?
249
- swarmed? && (!swarm_element.alive? || terminating?)
257
+ swarmed? && (!swarm_element.alive? || terminating?) # steep:ignore
250
258
  end
251
259
 
252
260
  # @return [Boolean]
@@ -255,7 +263,7 @@ class RedisQueuedLocks::Swarm::SwarmElement::Threaded
255
263
  # @since 1.9.0
256
264
  def swarmed__running?
257
265
  swarmed__alive? && !terminating? && (swarm_loop__is_active.yield_self do |result|
258
- result && result[:ok] && result[:result][:is_active]
266
+ result != nil && result[:ok] && result[:result][:is_active] # steep:ignore
259
267
  end)
260
268
  end
261
269
 
@@ -278,7 +286,7 @@ class RedisQueuedLocks::Swarm::SwarmElement::Threaded
278
286
  # @since 1.9.0
279
287
  def swarmed__stopped?
280
288
  swarmed__alive? && (terminating? || !(swarm_loop__is_active.yield_self do |result|
281
- result && result[:ok] && result[:result][:is_active]
289
+ result && result[:ok] && result[:result][:is_active] # steep:ignore
282
290
  end))
283
291
  end
284
292
 
@@ -289,8 +297,8 @@ class RedisQueuedLocks::Swarm::SwarmElement::Threaded
289
297
  def swarm_loop__is_active
290
298
  return if idle? || swarmed__dead? || terminating?
291
299
  sync.synchronize do
292
- swarm_element_commands.push(:is_active)
293
- swarm_element_results.pop
300
+ swarm_element_commands.push(:is_active) # steep:ignore
301
+ swarm_element_results.pop # steep:ignore
294
302
  end
295
303
  end
296
304
 
@@ -301,8 +309,8 @@ class RedisQueuedLocks::Swarm::SwarmElement::Threaded
301
309
  def swarm_loop__status
302
310
  return if idle? || swarmed__dead? || terminating?
303
311
  sync.synchronize do
304
- swarm_element_commands.push(:status)
305
- swarm_element_results.pop
312
+ swarm_element_commands.push(:status) # steep:ignore
313
+ swarm_element_results.pop # steep:ignore
306
314
  end
307
315
  end
308
316
 
@@ -313,8 +321,8 @@ class RedisQueuedLocks::Swarm::SwarmElement::Threaded
313
321
  def swarm_loop__start
314
322
  return if idle? || swarmed__dead? || terminating?
315
323
  sync.synchronize do
316
- swarm_element_commands.push(:start)
317
- swarm_element_results.pop
324
+ swarm_element_commands.push(:start) # steep:ignore
325
+ swarm_element_results.pop # steep:ignore
318
326
  end
319
327
  end
320
328
 
@@ -325,8 +333,8 @@ class RedisQueuedLocks::Swarm::SwarmElement::Threaded
325
333
  def swarm_loop__stop
326
334
  return if idle? || swarmed__dead? || terminating?
327
335
  sync.synchronize do
328
- swarm_element_commands.push(:stop)
329
- swarm_element_results.pop
336
+ swarm_element_commands.push(:stop) # steep:ignore
337
+ swarm_element_results.pop # steep:ignore
330
338
  end
331
339
  end
332
340
 
@@ -338,11 +346,11 @@ class RedisQueuedLocks::Swarm::SwarmElement::Threaded
338
346
  return if idle? || swarmed__dead?
339
347
  sync.synchronize do
340
348
  main_loop&.kill
341
- swarm_element.kill
342
- swarm_element_commands.close
343
- swarm_element_results.close
344
- swarm_element_commands.clear
345
- swarm_element_results.clear
349
+ swarm_element.kill # steep:ignore
350
+ swarm_element_commands.close # steep:ignore
351
+ swarm_element_results.close # steep:ignore
352
+ swarm_element_commands.clear # steep:ignore
353
+ swarm_element_results.clear # steep:ignore
346
354
  @swarm_element_commands = nil
347
355
  @swarm_element_results = nil
348
356
  end
@@ -54,9 +54,9 @@ module RedisQueuedLocks::Swarm::ZombieInfo
54
54
  #
55
55
  # @api private
56
56
  # @since 1.9.0
57
- def zombie_acquiers(redis_client, zombie_ttl, lock_scan_size)
57
+ def zombie_acquirers(redis_client, zombie_ttl, lock_scan_size)
58
58
  redis_client.with do |rconn|
59
- extract_zombie_acquiers(rconn, zombie_ttl, lock_scan_size)
59
+ extract_zombie_acquirers(rconn, zombie_ttl, lock_scan_size)
60
60
  end
61
61
  end
62
62
 
@@ -69,7 +69,7 @@ module RedisQueuedLocks::Swarm::ZombieInfo
69
69
  # @api private
70
70
  # @since 1.9.0
71
71
  def extract_zombie_hosts(rconn, zombie_ttl)
72
- zombie_score = RedisQueuedLocks::Resource.calc_zombie_score(zombie_ttl / 1_000)
72
+ zombie_score = RedisQueuedLocks::Resource.calc_zombie_score(zombie_ttl / 1_000.0)
73
73
  swarmed_hosts = rconn.call('HGETALL', RedisQueuedLocks::Resource::SWARM_KEY)
74
74
  swarmed_hosts.each_with_object(Set.new) do |(hst_id, ts), zombies|
75
75
  (zombies << hst_id) if (zombie_score > ts.to_f)
@@ -89,7 +89,7 @@ module RedisQueuedLocks::Swarm::ZombieInfo
89
89
  rconn.scan(
90
90
  'MATCH', RedisQueuedLocks::Resource::LOCK_PATTERN, count: lock_scan_size
91
91
  ) do |lock_key|
92
- _acquier_id, host_id = rconn.call('HMGET', lock_key, 'acq_id', 'hst_id')
92
+ _acquirer_id, host_id = rconn.call('HMGET', lock_key, 'acq_id', 'hst_id')
93
93
  zombie_locks << lock_key if zombie_hosts.include?(host_id)
94
94
  end
95
95
  zombie_locks
@@ -102,14 +102,14 @@ module RedisQueuedLocks::Swarm::ZombieInfo
102
102
  #
103
103
  # @api private
104
104
  # @since 1.9.0
105
- def extract_zombie_acquiers(rconn, zombie_ttl, lock_scan_size)
105
+ def extract_zombie_acquirers(rconn, zombie_ttl, lock_scan_size)
106
106
  zombie_hosts = extract_zombie_hosts(rconn, zombie_ttl)
107
107
  zombie_acquirers = Set.new
108
108
  rconn.scan(
109
109
  'MATCH', RedisQueuedLocks::Resource::LOCK_PATTERN, count: lock_scan_size
110
110
  ) do |lock_key|
111
- acquier_id, host_id = rconn.call('HMGET', lock_key, 'acq_id', 'hst_id')
112
- zombie_acquirers << acquier_id if zombie_hosts.include?(host_id)
111
+ acquirer_id, host_id = rconn.call('HMGET', lock_key, 'acq_id', 'hst_id')
112
+ zombie_acquirers << acquirer_id if zombie_hosts.include?(host_id)
113
113
  end
114
114
  zombie_acquirers
115
115
  end
@@ -133,9 +133,9 @@ module RedisQueuedLocks::Swarm::ZombieInfo
133
133
  rconn.scan(
134
134
  'MATCH', RedisQueuedLocks::Resource::LOCK_PATTERN, count: lock_scan_size
135
135
  ) do |lock_key|
136
- acquier_id, host_id = rconn.call('HMGET', lock_key, 'acq_id', 'hst_id')
136
+ acquirer_id, host_id = rconn.call('HMGET', lock_key, 'acq_id', 'hst_id')
137
137
  if zombie_hosts.include?(host_id)
138
- zombie_acquirers << acquier_id
138
+ zombie_acquirers << acquirer_id
139
139
  zombie_locks << lock_key
140
140
  end
141
141
  end
@@ -62,7 +62,7 @@ class RedisQueuedLocks::Swarm
62
62
  def swarm_status
63
63
  sync.synchronize do
64
64
  {
65
- auto_swarm: rql_client.config[:swarm][:auto_swarm],
65
+ auto_swarm: rql_client.config['swarm.auto_swarm'],
66
66
  supervisor: supervisor.status,
67
67
  probe_hosts: probe_hosts_element.status,
68
68
  flush_zombies: flush_zombies_element.status
@@ -76,23 +76,14 @@ class RedisQueuedLocks::Swarm
76
76
  #
77
77
  # @api public
78
78
  # @since 1.9.0
79
- def swarm_info(zombie_ttl: rql_client.config[:swarm][:flush_zombies][:zombie_ttl])
79
+ def swarm_info(zombie_ttl: rql_client.config['swarm.flush_zombies.zombie_ttl'])
80
80
  RedisQueuedLocks::Swarm::Acquirers.acquirers(
81
81
  rql_client.redis_client,
82
82
  zombie_ttl
83
83
  )
84
84
  end
85
85
 
86
- # @return [
87
- # RedisQueuedLocks::Data[
88
- # ok: <Boolean>,
89
- # result: {
90
- # host_id1 <String> => score1 <String>,
91
- # host_id2 <String> => score2 <String>,
92
- # etc...
93
- # }
94
- # ]
95
- # ]
86
+ # @return [Hash<Symbol,Hash[String,Float]]
96
87
  #
97
88
  # @api public
98
89
  # @since 1.9.0
@@ -106,21 +97,14 @@ class RedisQueuedLocks::Swarm
106
97
  # @option zombie_ttl [Integer]
107
98
  # @option lock_scan_size [Integer]
108
99
  # @option queue_scan_size [Integer]
109
- # @return [
110
- # RedisQueuedLocks::Data[
111
- # ok: <Boolean>,
112
- # deleted_zombie_hosts: <Set<String>>,
113
- # deleted_zombie_acquiers: <Set<String>>,
114
- # deleted_zombie_locks: <Set<String>>
115
- # ]
116
- # ]
100
+ # @return [Hash<Bool,Set<String>]
117
101
  #
118
102
  # @api public
119
103
  # @since 1.9.0
120
104
  def flush_zombies(
121
- zombie_ttl: rql_client.config[:swarm][:flush_zombies][:zombie_ttl],
122
- lock_scan_size: rql_client.config[:swarm][:flush_zombies][:zombie_lock_scan_size],
123
- queue_scan_size: rql_client.config[:swarm][:flush_zombies][:zombie_queue_scan_size]
105
+ zombie_ttl: rql_client.config['swarm.flush_zombies.zombie_ttl'],
106
+ lock_scan_size: rql_client.config['swarm.flush_zombies.zombie_lock_scan_size'],
107
+ queue_scan_size: rql_client.config['swarm.flush_zombies.zombie_queue_scan_size']
124
108
  )
125
109
  RedisQueuedLocks::Swarm::FlushZombies.flush_zombies(
126
110
  rql_client.redis_client,
@@ -137,8 +121,8 @@ class RedisQueuedLocks::Swarm
137
121
  # @api public
138
122
  # @since 1.9.0
139
123
  def zombie_locks(
140
- zombie_ttl: rql_client.config[:swarm][:flush_zombies][:zombie_ttl],
141
- lock_scan_size: rql_client.config[:swarm][:flush_zombies][:zombie_lock_scan_size]
124
+ zombie_ttl: rql_client.config['swarm.flush_zombies.zombie_ttl'],
125
+ lock_scan_size: rql_client.config['swarm.flush_zombies.zombie_lock_scan_size']
142
126
  )
143
127
  RedisQueuedLocks::Swarm::ZombieInfo.zombie_locks(
144
128
  rql_client.redis_client,
@@ -153,11 +137,11 @@ class RedisQueuedLocks::Swarm
153
137
  #
154
138
  # @api ppublic
155
139
  # @since 1.9.0
156
- def zombie_acquiers(
157
- zombie_ttl: rql_client.config[:swarm][:flush_zombies][:zombie_ttl],
158
- lock_scan_size: rql_client.config[:swarm][:flush_zombies][:zombie_lock_scan_size]
140
+ def zombie_acquirers(
141
+ zombie_ttl: rql_client.config['swarm.flush_zombies.zombie_ttl'],
142
+ lock_scan_size: rql_client.config['swarm.flush_zombies.zombie_lock_scan_size']
159
143
  )
160
- RedisQueuedLocks::Swarm::ZombieInfo.zombie_acquiers(
144
+ RedisQueuedLocks::Swarm::ZombieInfo.zombie_acquirers(
161
145
  rql_client.redis_client,
162
146
  zombie_ttl,
163
147
  lock_scan_size
@@ -169,24 +153,19 @@ class RedisQueuedLocks::Swarm
169
153
  #
170
154
  # @api public
171
155
  # @since 1.9.0
172
- def zombie_hosts(zombie_ttl: rql_client.config[:swarm][:flush_zombies][:zombie_ttl])
156
+ def zombie_hosts(zombie_ttl: rql_client.config['swarm.flush_zombies.zombie_ttl'])
173
157
  RedisQueuedLocks::Swarm::ZombieInfo.zombie_hosts(rql_client.redis_client, zombie_ttl)
174
158
  end
175
159
 
176
160
  # @option zombie_ttl [Integer]
177
161
  # @option lock_sacn_size [Integer]
178
162
  # @return [Hash<Symbol,Set<String>>]
179
- # Format: {
180
- # zombie_hosts: <Set<String>>,
181
- # zombie_acquirers: <Set<String>>,
182
- # zombie_locks: <Set<String>>
183
- # }
184
163
  #
185
164
  # @api public
186
165
  # @since 1.9.0
187
166
  def zombies_info(
188
- zombie_ttl: rql_client.config[:swarm][:flush_zombies][:zombie_ttl],
189
- lock_scan_size: rql_client.config[:swarm][:flush_zombies][:zombie_lock_scan_size]
167
+ zombie_ttl: rql_client.config['swarm.flush_zombies.zombie_ttl'],
168
+ lock_scan_size: rql_client.config['swarm.flush_zombies.zombie_lock_scan_size']
190
169
  )
191
170
  RedisQueuedLocks::Swarm::ZombieInfo.zombies_info(
192
171
  rql_client.redis_client,
@@ -195,7 +174,7 @@ class RedisQueuedLocks::Swarm
195
174
  )
196
175
  end
197
176
 
198
- # @return [NilClass,Hash<Symbol,Symbol|Boolean>]
177
+ # @return [Hash<Symbol,Symbol|Boolean>] Example: { ok: true, result: :swarming }
199
178
  #
200
179
  # @api public
201
180
  # @since 1.9.0
@@ -222,11 +201,11 @@ class RedisQueuedLocks::Swarm
222
201
  # NOTE: need to give a little timespot to initialize ractor objects and their main loops;
223
202
  sleep(0.1)
224
203
 
225
- RedisQueuedLocks::Data[ok: true, result: :swarming]
204
+ { ok: true, result: :swarming }
226
205
  end
227
206
  end
228
207
 
229
- # @return [NilClass,Hash<Symbol,Symbol|Boolean>]
208
+ # @return [Hash<Symbol,Symbol|Boolean>] Example: { ok: true, result: :terminating }
230
209
  #
231
210
  # @api public
232
211
  # @since 1.9.0
@@ -239,7 +218,7 @@ class RedisQueuedLocks::Swarm
239
218
  # NOTE: need to give a little timespot to stop ractor objects and their main loops;
240
219
  sleep(0.1)
241
220
 
242
- RedisQueuedLocks::Data[ok: true, result: :terminating]
221
+ { ok: true, result: :terminating }
243
222
  end
244
223
  end
245
224
  end
@@ -7,8 +7,9 @@ class RedisQueuedLocks::Utilities::Lock
7
7
  #
8
8
  # @api private
9
9
  # @since 1.9.0
10
+ # @version 1.13.0
10
11
  def initialize
11
- @lock = ::Mutex.new
12
+ @lock = ::Monitor.new
12
13
  end
13
14
 
14
15
  # @param block [Block]
@@ -16,7 +17,8 @@ class RedisQueuedLocks::Utilities::Lock
16
17
  #
17
18
  # @api private
18
19
  # @since 1.9.0
20
+ # @version 1.13.0
19
21
  def synchronize(&block)
20
- @lock.owned? ? yield : @lock.synchronize(&block)
22
+ @lock.synchronize(&block)
21
23
  end
22
24
  end
@@ -56,7 +56,7 @@ module RedisQueuedLocks::Utilities
56
56
  # @api private
57
57
  # @since 1.9.0
58
58
  def ractor_status(ractor)
59
- ractor.to_s.match(RACTOR_STATUS_PATTERN)[:status]
59
+ ractor.to_s.match(RACTOR_STATUS_PATTERN)[:status] # steep:ignore
60
60
  end
61
61
 
62
62
  # @param ractor [Ractor]
@@ -86,6 +86,6 @@ module RedisQueuedLocks::Utilities
86
86
  status = thread.status
87
87
  return 'dead' if status == false
88
88
  return 'failed' if status == nil
89
- status
89
+ status #: String
90
90
  end
91
91
  end
@@ -5,6 +5,6 @@ module RedisQueuedLocks
5
5
  #
6
6
  # @api public
7
7
  # @since 0.0.1
8
- # @version 1.12.0
9
- VERSION = '1.12.0'
8
+ # @version 1.13.0
9
+ VERSION = '1.13.0'
10
10
  end
@@ -2,7 +2,6 @@
2
2
 
3
3
  require 'timeout'
4
4
  require 'redis-client'
5
- require 'qonfig'
6
5
  require 'securerandom'
7
6
  require 'logger'
8
7
  require 'objspace'
@@ -17,10 +16,11 @@ module RedisQueuedLocks
17
16
  require_relative 'redis_queued_locks/data'
18
17
  require_relative 'redis_queued_locks/debugger'
19
18
  require_relative 'redis_queued_locks/resource'
20
- require_relative 'redis_queued_locks/acquier'
19
+ require_relative 'redis_queued_locks/acquirer'
21
20
  require_relative 'redis_queued_locks/instrument'
22
21
  require_relative 'redis_queued_locks/swarm'
23
22
  require_relative 'redis_queued_locks/client'
23
+ require_relative 'redis_queued_locks/config'
24
24
 
25
25
  # @since 1.0.0
26
26
  extend RedisQueuedLocks::Debugger::Interface
@@ -0,0 +1,40 @@
1
+ ---
2
+ path: ".gem_rbs_collection"
3
+ gems:
4
+ - name: base64
5
+ version: '0.1'
6
+ source:
7
+ type: git
8
+ name: ruby/gem_rbs_collection
9
+ revision: e2749137770bcff57a062d47b0d08922071f3d37
10
+ remote: https://github.com/ruby/gem_rbs_collection.git
11
+ repo_dir: gems
12
+ - name: connection_pool
13
+ version: '2.4'
14
+ source:
15
+ type: git
16
+ name: ruby/gem_rbs_collection
17
+ revision: 0a6ea105a0afc7eaee4494585a7775f47eea6145
18
+ remote: https://github.com/ruby/gem_rbs_collection.git
19
+ repo_dir: gems
20
+ - name: logger
21
+ version: '0'
22
+ source:
23
+ type: stdlib
24
+ - name: monitor
25
+ version: '0'
26
+ source:
27
+ type: stdlib
28
+ - name: objspace
29
+ version: '0'
30
+ source:
31
+ type: stdlib
32
+ - name: securerandom
33
+ version: '0'
34
+ source:
35
+ type: stdlib
36
+ - name: timeout
37
+ version: '0'
38
+ source:
39
+ type: stdlib
40
+ gemfile_lock_path: Gemfile.lock
@@ -0,0 +1,16 @@
1
+ sources:
2
+ - type: git
3
+ name: ruby/gem_rbs_collection
4
+ remote: https://github.com/ruby/gem_rbs_collection.git
5
+ revision: main
6
+ repo_dir: gems
7
+
8
+ path: .gem_rbs_collection
9
+
10
+ gems:
11
+ - name: timeout
12
+ - name: redis-client
13
+ - name: securerandom
14
+ - name: logger
15
+ - name: objspace
16
+ - name: monitor
@@ -3,38 +3,38 @@
3
3
  require_relative 'lib/redis_queued_locks/version'
4
4
 
5
5
  Gem::Specification.new do |spec|
6
- spec.required_ruby_version = '>= 3.1'
6
+ spec.required_ruby_version = '>= 3.3'
7
7
 
8
- spec.name = 'redis_queued_locks'
8
+ spec.name = 'redis_queued_locks'
9
9
  spec.version = RedisQueuedLocks::VERSION
10
10
  spec.authors = ['Rustam Ibragimov']
11
- spec.email = ['iamdaiver@gmail.com']
11
+ spec.email = ['iamdaiver@gmail.com']
12
12
 
13
13
  spec.summary =
14
14
  'Distributed locks with "prioritized lock acquisition queue" ' \
15
15
  'capabilities based on the Redis Database.'
16
16
 
17
17
  spec.description =
18
- '|> Distributed locks with "prioritized lock acquisition queue" capabilities ' \
19
- 'based on the Redis Database. ' \
20
- '|> Each lock request is put into the request queue ' \
21
- '(each lock is hosted by it\'s own queue separately from other queues) and processed ' \
22
- 'in order of their priority (FIFO). ' \
23
- '|> Each lock request lives some period of time (RTTL) ' \
24
- '(with requeue capabilities) which guarantees the request queue will never be stacked. ' \
25
- '|> In addition to the classic `queued` (FIFO) strategy RQL supports ' \
26
- '`random` (RANDOM) lock obtaining strategy when any acquirer from the lock queue ' \
27
- 'can obtain the lock regardless the position in the queue. ' \
28
- '|> Provides flexible invocation flow, parametrized limits ' \
29
- '(lock request ttl, lock ttl, queue ttl, lock attempts limit, fast failing, etc), ' \
30
- 'logging and instrumentation.'
31
-
32
- spec.homepage = 'https://github.com/0exp/redis_queued_locks'
33
- spec.license = 'MIT'
34
-
35
- spec.metadata['homepage_uri'] = spec.homepage
18
+ "|> Distributed locks with \"prioritized lock acquisition queue\" capabilities " \
19
+ "based on the Redis Database.\n" \
20
+ "|> Each lock request is put into the request queue " \
21
+ "(each lock is hosted by it's own queue separately from other queues) and processed " \
22
+ "in order of their priority (FIFO).\n" \
23
+ "|> Each lock request lives some period of time (RTTL) " \
24
+ "(with requeue capabilities) which guarantees the request queue will never be stacked.\n" \
25
+ "|> In addition to the classic `queued` (FIFO) strategy RQL supports " \
26
+ "`random` (RANDOM) lock obtaining strategy when any acquirer from the lock queue " \
27
+ "can obtain the lock regardless the position in the queue.\n" \
28
+ "|> Provides flexible invocation flow, parametrized limits " \
29
+ "(lock request ttl, lock ttl, queue ttl, lock attempts limit, fast failing, etc), " \
30
+ "logging and instrumentation."
31
+
32
+ spec.homepage = 'https://github.com/0exp/redis_queued_locks'
33
+ spec.license = 'MIT'
34
+
35
+ spec.metadata['homepage_uri'] = spec.homepage
36
36
  spec.metadata['source_code_uri'] = "#{spec.homepage}/blob/master"
37
- spec.metadata['changelog_uri'] = "#{spec.homepage}/blob/master/CHANGELOG.md"
37
+ spec.metadata['changelog_uri'] = "#{spec.homepage}/blob/master/CHANGELOG.md"
38
38
 
39
39
  spec.files = Dir.chdir(__dir__) do
40
40
  `git ls-files -z`.split("\x0").reject do |f|
@@ -48,5 +48,4 @@ Gem::Specification.new do |spec|
48
48
  spec.require_paths = ['lib']
49
49
 
50
50
  spec.add_dependency 'redis-client', '~> 0.20'
51
- spec.add_dependency 'qonfig', '~> 0.28'
52
51
  end
data/sig/manifest.yml ADDED
@@ -0,0 +1,7 @@
1
+ dependencies:
2
+ - timeout
3
+ - redis-client
4
+ - securerandom
5
+ - logger
6
+ - objspace
7
+ - monitor
@@ -0,0 +1,4 @@
1
+ module RedisQueuedLocks
2
+ module Acquirer
3
+ end
4
+ end
@@ -0,0 +1,9 @@
1
+ module RedisQueuedLocks
2
+ module Acquirer
3
+ module AcquireLock
4
+ module DelayExecution
5
+ def delay_execution: (Integer retry_delay, Integer retry_jitter) -> Integer
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,21 @@
1
+ use RedisQueuedLocks as RQL
2
+
3
+ module RedisQueuedLocks
4
+ module Acquirer
5
+ module AcquireLock
6
+ module DequeueFromLockQueue
7
+ module LogVisitor
8
+ def self.dequeue_from_lock_queue: (
9
+ RQL::loggerObj logger,
10
+ bool log_sampled,
11
+ String lock_key,
12
+ Integer queue_ttl,
13
+ String acquirer_id,
14
+ String host_id,
15
+ Symbol access_strategy
16
+ ) -> void
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,26 @@
1
+ use RedisQueuedLocks as RQL
2
+ use RedisClient as RC
3
+
4
+ module RedisQueuedLocks
5
+ module Acquirer
6
+ module AcquireLock
7
+ module DequeueFromLockQueue
8
+ def dequeue_from_lock_queue: (
9
+ RC::client redis,
10
+ RQL::loggerObj logger,
11
+ String lock_key,
12
+ Symbol read_write_mode,
13
+ String lock_key_queue,
14
+ String read_lock_key_queue,
15
+ String write_lock_key_queue,
16
+ Integer queue_ttl,
17
+ String acquirer_id,
18
+ String host_id,
19
+ Symbol access_strategy,
20
+ bool log_sampled,
21
+ bool instr_sampled
22
+ ) -> { ok: bool, result: Integer }
23
+ end
24
+ end
25
+ end
26
+ end