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.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -1
- data/.ruby-version +1 -1
- data/CHANGELOG.md +42 -5
- data/LICENSE.txt +1 -1
- data/README.md +231 -203
- data/Rakefile +12 -4
- data/Steepfile +16 -0
- data/github_ci/ruby3.3.gemfile +17 -0
- data/github_ci/ruby3.3.gemfile.lock +217 -0
- data/lib/redis_queued_locks/{acquier → acquirer}/acquire_lock/delay_execution.rb +4 -4
- data/lib/redis_queued_locks/acquirer/acquire_lock/dequeue_from_lock_queue/log_visitor.rb +40 -0
- data/lib/redis_queued_locks/{acquier → acquirer}/acquire_lock/dequeue_from_lock_queue.rb +17 -8
- data/lib/redis_queued_locks/acquirer/acquire_lock/instr_visitor.rb +166 -0
- data/lib/redis_queued_locks/acquirer/acquire_lock/log_visitor.rb +218 -0
- data/lib/redis_queued_locks/acquirer/acquire_lock/try_to_lock/log_visitor.rb +543 -0
- data/lib/redis_queued_locks/{acquier → acquirer}/acquire_lock/try_to_lock.rb +126 -92
- data/lib/redis_queued_locks/{acquier → acquirer}/acquire_lock/with_acq_timeout.rb +14 -13
- data/lib/redis_queued_locks/acquirer/acquire_lock/yield_expire/log_visitor.rb +76 -0
- data/lib/redis_queued_locks/{acquier → acquirer}/acquire_lock/yield_expire.rb +43 -20
- data/lib/redis_queued_locks/{acquier → acquirer}/acquire_lock.rb +69 -42
- data/lib/redis_queued_locks/{acquier → acquirer}/clear_dead_requests.rb +5 -3
- data/lib/redis_queued_locks/{acquier → acquirer}/extend_lock_ttl.rb +4 -3
- data/lib/redis_queued_locks/{acquier → acquirer}/is_locked.rb +1 -1
- data/lib/redis_queued_locks/{acquier → acquirer}/is_queued.rb +1 -1
- data/lib/redis_queued_locks/{acquier → acquirer}/keys.rb +5 -5
- data/lib/redis_queued_locks/{acquier → acquirer}/lock_info.rb +9 -5
- data/lib/redis_queued_locks/{acquier → acquirer}/locks.rb +16 -3
- data/lib/redis_queued_locks/{acquier → acquirer}/queue_info.rb +8 -6
- data/lib/redis_queued_locks/{acquier → acquirer}/queues.rb +9 -2
- data/lib/redis_queued_locks/{acquier → acquirer}/release_all_locks.rb +23 -18
- data/lib/redis_queued_locks/{acquier → acquirer}/release_lock.rb +25 -19
- data/lib/redis_queued_locks/acquirer.rb +18 -0
- data/lib/redis_queued_locks/client.rb +164 -254
- data/lib/redis_queued_locks/config/dsl.rb +94 -0
- data/lib/redis_queued_locks/config.rb +231 -0
- data/lib/redis_queued_locks/data.rb +2 -0
- data/lib/redis_queued_locks/errors.rb +27 -11
- data/lib/redis_queued_locks/instrument.rb +11 -4
- data/lib/redis_queued_locks/logging/void_logger.rb +38 -1
- data/lib/redis_queued_locks/logging.rb +20 -5
- data/lib/redis_queued_locks/resource.rb +49 -11
- data/lib/redis_queued_locks/swarm/acquirers.rb +17 -16
- data/lib/redis_queued_locks/swarm/flush_zombies.rb +26 -25
- data/lib/redis_queued_locks/swarm/probe_hosts.rb +20 -19
- data/lib/redis_queued_locks/swarm/redis_client_builder.rb +3 -3
- data/lib/redis_queued_locks/swarm/supervisor.rb +19 -6
- data/lib/redis_queued_locks/swarm/swarm_element/isolated.rb +20 -18
- data/lib/redis_queued_locks/swarm/swarm_element/threaded.rb +35 -27
- data/lib/redis_queued_locks/swarm/zombie_info.rb +9 -9
- data/lib/redis_queued_locks/swarm.rb +20 -41
- data/lib/redis_queued_locks/utilities/lock.rb +4 -2
- data/lib/redis_queued_locks/utilities.rb +2 -2
- data/lib/redis_queued_locks/version.rb +2 -2
- data/lib/redis_queued_locks.rb +2 -2
- data/rbs_collection.lock.yaml +40 -0
- data/rbs_collection.yaml +16 -0
- data/redis_queued_locks.gemspec +22 -23
- data/sig/manifest.yml +7 -0
- data/sig/redis_queued_locks/acquier.rbs +4 -0
- data/sig/redis_queued_locks/acquirer/acquire_lock/delay_execution.rbs +9 -0
- data/sig/redis_queued_locks/acquirer/acquire_lock/dequeue_from_lock_queue/log_visitor.rbs +21 -0
- data/sig/redis_queued_locks/acquirer/acquire_lock/dequeue_from_lock_queue.rbs +26 -0
- data/sig/redis_queued_locks/acquirer/acquire_lock/instr_visitor.rbs +71 -0
- data/sig/redis_queued_locks/acquirer/acquire_lock/log_visitor.rbs +72 -0
- data/sig/redis_queued_locks/acquirer/acquire_lock/try_to_lock/log_visitor.rbs +179 -0
- data/sig/redis_queued_locks/acquirer/acquire_lock/try_to_lock.rbs +48 -0
- data/sig/redis_queued_locks/acquirer/acquire_lock/with_acq_timeout.rbs +19 -0
- data/sig/redis_queued_locks/acquirer/acquire_lock/yield_expire.rbs +41 -0
- data/sig/redis_queued_locks/acquirer/acquire_lock/yield_with_expire/log_visitor.rbs +32 -0
- data/sig/redis_queued_locks/acquirer/acquire_lock.rbs +51 -0
- data/sig/redis_queued_locks/acquirer/clear_dead_requests.rbs +28 -0
- data/sig/redis_queued_locks/acquirer/extend_lock_ttl.rbs +28 -0
- data/sig/redis_queued_locks/acquirer/is_locked.rbs +9 -0
- data/sig/redis_queued_locks/acquirer/is_queued.rbs +9 -0
- data/sig/redis_queued_locks/acquirer/keys.rbs +10 -0
- data/sig/redis_queued_locks/acquirer/lock_info.rbs +10 -0
- data/sig/redis_queued_locks/acquirer/locks.rbs +16 -0
- data/sig/redis_queued_locks/acquirer/queue_info.rbs +13 -0
- data/sig/redis_queued_locks/acquirer/queues.rbs +16 -0
- data/sig/redis_queued_locks/acquirer/release_all_locks.rbs +30 -0
- data/sig/redis_queued_locks/acquirer/release_lock.rbs +38 -0
- data/sig/redis_queued_locks/client.rbs +195 -0
- data/sig/redis_queued_locks/config/dsl.rbs +26 -0
- data/sig/redis_queued_locks/config.rbs +23 -0
- data/sig/redis_queued_locks/data.rbs +4 -0
- data/sig/redis_queued_locks/debugger/interface.rbs +9 -0
- data/sig/redis_queued_locks/debugger.rbs +13 -0
- data/sig/redis_queued_locks/errors.rbs +43 -0
- data/sig/redis_queued_locks/instrument/active_support.rbs +7 -0
- data/sig/redis_queued_locks/instrument/sampler.rbs +9 -0
- data/sig/redis_queued_locks/instrument/void_notifier.rbs +7 -0
- data/sig/redis_queued_locks/instrument.rbs +15 -0
- data/sig/redis_queued_locks/logging/sampler.rbs +9 -0
- data/sig/redis_queued_locks/logging/void_logger.rbs +15 -0
- data/sig/redis_queued_locks/logging.rbs +15 -0
- data/sig/redis_queued_locks/resource.rbs +42 -0
- data/sig/redis_queued_locks/swarm/acquirers.rbs +10 -0
- data/sig/redis_queued_locks/swarm/flush_zombies.rbs +13 -0
- data/sig/redis_queued_locks/swarm/probe_hosts.rbs +13 -0
- data/sig/redis_queued_locks/swarm/redis_client_builder.rbs +19 -0
- data/sig/redis_queued_locks/swarm/supervisor.rbs +26 -0
- data/sig/redis_queued_locks/swarm/swarm_element/isolated.rbs +52 -0
- data/sig/redis_queued_locks/swarm/swarm_element/threaded.rbs +61 -0
- data/sig/redis_queued_locks/swarm/swarm_element.rbs +8 -0
- data/sig/redis_queued_locks/swarm/zombie_info.rbs +24 -0
- data/sig/redis_queued_locks/swarm.rbs +41 -0
- data/sig/redis_queued_locks/utilities/lock.rbs +10 -0
- data/sig/redis_queued_locks/utilities.rbs +11 -0
- data/sig/redis_queued_locks/version.rbs +3 -0
- data/sig/redis_queued_locks.rbs +14 -0
- data/sig/vendor/active_support.rbs +9 -0
- data/sig/vendor/redis_client.rbs +39 -0
- data/sig/vendor/semantic_logger.rbs +4 -0
- metadata +96 -54
- data/lib/redis_queued_locks/acquier/acquire_lock/dequeue_from_lock_queue/log_visitor.rb +0 -40
- data/lib/redis_queued_locks/acquier/acquire_lock/instr_visitor.rb +0 -166
- data/lib/redis_queued_locks/acquier/acquire_lock/log_visitor.rb +0 -216
- data/lib/redis_queued_locks/acquier/acquire_lock/try_to_lock/log_visitor.rb +0 -541
- data/lib/redis_queued_locks/acquier/acquire_lock/yield_expire/log_visitor.rb +0 -76
- 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
|
57
|
+
def zombie_acquirers(redis_client, zombie_ttl, lock_scan_size)
|
58
58
|
redis_client.with do |rconn|
|
59
|
-
|
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
|
-
|
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
|
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
|
-
|
112
|
-
zombie_acquirers <<
|
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
|
-
|
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 <<
|
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[
|
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[
|
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[
|
122
|
-
lock_scan_size: rql_client.config[
|
123
|
-
queue_scan_size: rql_client.config[
|
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[
|
141
|
-
lock_scan_size: rql_client.config[
|
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
|
157
|
-
zombie_ttl: rql_client.config[
|
158
|
-
lock_scan_size: rql_client.config[
|
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.
|
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[
|
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[
|
189
|
-
lock_scan_size: rql_client.config[
|
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 [
|
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
|
-
|
204
|
+
{ ok: true, result: :swarming }
|
226
205
|
end
|
227
206
|
end
|
228
207
|
|
229
|
-
# @return [
|
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
|
-
|
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 = ::
|
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.
|
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
|
data/lib/redis_queued_locks.rb
CHANGED
@@ -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/
|
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
|
data/rbs_collection.yaml
ADDED
@@ -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
|
data/redis_queued_locks.gemspec
CHANGED
@@ -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.
|
6
|
+
spec.required_ruby_version = '>= 3.3'
|
7
7
|
|
8
|
-
spec.name
|
8
|
+
spec.name = 'redis_queued_locks'
|
9
9
|
spec.version = RedisQueuedLocks::VERSION
|
10
10
|
spec.authors = ['Rustam Ibragimov']
|
11
|
-
spec.email
|
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
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
spec.homepage
|
33
|
-
spec.license
|
34
|
-
|
35
|
-
spec.metadata['homepage_uri']
|
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']
|
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,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
|