redis_queued_locks 1.16.2 → 1.18.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/.claude/project-overview.md +281 -0
- data/.claude/rules/acquirer.md +81 -0
- data/.claude/rules/arguments.md +60 -0
- data/.claude/rules/git.md +46 -0
- data/.claude/rules/logic.md +63 -0
- data/.claude/rules/swarm.md +120 -0
- data/.claude/rules/tests.md +48 -0
- data/.claude/rules/type-checking.md +50 -0
- data/.claude/rules/visitors.md +69 -0
- data/.rubocop.rbs.yml +31 -0
- data/.rubocop.yml +3 -3
- data/.ruby-version +1 -1
- data/CHANGELOG.md +80 -0
- data/CLAUDE.md +36 -0
- data/README.md +367 -82
- data/Rakefile +31 -2
- data/github_ci/.keep +0 -0
- data/lib/redis_queued_locks/acquirer/acquire_lock/delay_execution.rb +2 -2
- data/lib/redis_queued_locks/acquirer/acquire_lock/dequeue_from_lock_queue/log_visitor.rb +6 -3
- data/lib/redis_queued_locks/acquirer/acquire_lock/dequeue_from_lock_queue.rb +9 -7
- data/lib/redis_queued_locks/acquirer/acquire_lock/instr_visitor.rb +20 -10
- data/lib/redis_queued_locks/acquirer/acquire_lock/log_visitor.rb +34 -16
- data/lib/redis_queued_locks/acquirer/acquire_lock/try_to_lock/log_visitor.rb +240 -28
- data/lib/redis_queued_locks/acquirer/acquire_lock/try_to_lock.rb +398 -132
- data/lib/redis_queued_locks/acquirer/acquire_lock/yield_expire/log_visitor.rb +12 -6
- data/lib/redis_queued_locks/acquirer/acquire_lock/yield_expire.rb +33 -9
- data/lib/redis_queued_locks/acquirer/acquire_lock.rb +73 -24
- data/lib/redis_queued_locks/acquirer/clear_dead_requests.rb +9 -1
- data/lib/redis_queued_locks/acquirer/extend_lock_ttl.rb +182 -3
- data/lib/redis_queued_locks/acquirer/is_locked.rb +19 -2
- data/lib/redis_queued_locks/acquirer/is_queued.rb +6 -2
- data/lib/redis_queued_locks/acquirer/lock_info.rb +96 -6
- data/lib/redis_queued_locks/acquirer/lock_series_poc/instr_visitor.rb +8 -4
- data/lib/redis_queued_locks/acquirer/lock_series_poc/log_visitor.rb +18 -7
- data/lib/redis_queued_locks/acquirer/lock_series_poc.rb +126 -29
- data/lib/redis_queued_locks/acquirer/locks.rb +103 -6
- data/lib/redis_queued_locks/acquirer/queue_info.rb +38 -9
- data/lib/redis_queued_locks/acquirer/queues.rb +28 -4
- data/lib/redis_queued_locks/acquirer/release_all_locks.rb +35 -1
- data/lib/redis_queued_locks/acquirer/release_lock.rb +40 -9
- data/lib/redis_queued_locks/acquirer/release_locks_of.rb +43 -3
- data/lib/redis_queued_locks/acquirer/release_read_lock.rb +143 -0
- data/lib/redis_queued_locks/acquirer.rb +1 -0
- data/lib/redis_queued_locks/client.rb +274 -158
- data/lib/redis_queued_locks/config/dsl.rb +4 -10
- data/lib/redis_queued_locks/resource.rb +117 -9
- data/lib/redis_queued_locks/swarm/flush_zombies.rb +46 -6
- data/lib/redis_queued_locks/swarm/supervisor.rb +1 -1
- data/lib/redis_queued_locks/swarm/swarm_element/isolated.rb +166 -44
- data/lib/redis_queued_locks/swarm/swarm_element/threaded.rb +45 -47
- data/lib/redis_queued_locks/swarm/zombie_info.rb +42 -0
- data/lib/redis_queued_locks/version.rb +2 -2
- data/rbs_collection.lock.yaml +10 -2
- data/rbs_collection.yaml +0 -2
- data/redis_queued_locks.gemspec +1 -1
- data/sig/redis_queued_locks/acquirer/acquire_lock/dequeue_from_lock_queue/log_visitor.rbs +2 -1
- data/sig/redis_queued_locks/acquirer/acquire_lock/dequeue_from_lock_queue.rbs +0 -1
- data/sig/redis_queued_locks/acquirer/acquire_lock/instr_visitor.rbs +5 -0
- data/sig/redis_queued_locks/acquirer/acquire_lock/log_visitor.rbs +12 -6
- data/sig/redis_queued_locks/acquirer/acquire_lock/try_to_lock/log_visitor.rbs +74 -7
- data/sig/redis_queued_locks/acquirer/acquire_lock/try_to_lock.rbs +4 -2
- data/sig/redis_queued_locks/acquirer/acquire_lock/yield_expire.rbs +3 -0
- data/sig/redis_queued_locks/acquirer/acquire_lock/yield_with_expire/log_visitor.rbs +4 -2
- data/sig/redis_queued_locks/acquirer/extend_lock_ttl.rbs +19 -1
- data/sig/redis_queued_locks/acquirer/lock_info.rbs +9 -1
- data/sig/redis_queued_locks/acquirer/locks.rbs +10 -1
- data/sig/redis_queued_locks/acquirer/queue_info.rbs +2 -4
- data/sig/redis_queued_locks/acquirer/queues.rbs +1 -1
- data/sig/redis_queued_locks/acquirer/release_lock.rbs +8 -1
- data/sig/redis_queued_locks/acquirer/release_read_lock.rbs +44 -0
- data/sig/redis_queued_locks/client.rbs +22 -2
- data/sig/redis_queued_locks/resource.rbs +9 -2
- data/sig/redis_queued_locks/swarm/flush_zombies.rbs +1 -1
- data/sig/redis_queued_locks/swarm/swarm_element/isolated.rbs +13 -5
- data/sig/redis_queued_locks/swarm/swarm_element/threaded.rbs +6 -6
- data/sig/redis_queued_locks/swarm/zombie_info.rbs +5 -0
- metadata +17 -5
- data/github_ci/ruby3.3.gemfile +0 -17
- data/github_ci/ruby3.3.gemfile.lock +0 -216
|
@@ -11,6 +11,7 @@ module RedisQueuedLocks::Acquirer::ReleaseLock
|
|
|
11
11
|
# - 1. clear lock queue: al; related processes released
|
|
12
12
|
# from the lock aquierment and should retry;
|
|
13
13
|
# - 2. delete the lock: drop lock key from Redis;
|
|
14
|
+
# - 3. (RW) clear the read lock queue and drop all read locks (the readers registry);
|
|
14
15
|
# It is safe because the lock obtain logic is transactional and
|
|
15
16
|
# watches the original lock for changes.
|
|
16
17
|
#
|
|
@@ -71,7 +72,7 @@ module RedisQueuedLocks::Acquirer::ReleaseLock
|
|
|
71
72
|
#
|
|
72
73
|
# @api private
|
|
73
74
|
# @since 1.0.0
|
|
74
|
-
# @version 1.
|
|
75
|
+
# @version 1.18.0
|
|
75
76
|
# rubocop:disable Metrics/MethodLength
|
|
76
77
|
def release_lock(
|
|
77
78
|
redis,
|
|
@@ -89,9 +90,15 @@ module RedisQueuedLocks::Acquirer::ReleaseLock
|
|
|
89
90
|
)
|
|
90
91
|
lock_key = RedisQueuedLocks::Resource.prepare_lock_key(lock_name)
|
|
91
92
|
lock_key_queue = RedisQueuedLocks::Resource.prepare_lock_queue(lock_name)
|
|
93
|
+
read_lock_key_queue = RedisQueuedLocks::Resource.prepare_read_lock_queue(lock_name)
|
|
94
|
+
lock_readers_key = RedisQueuedLocks::Resource.prepare_lock_readers(lock_name)
|
|
92
95
|
|
|
93
96
|
rel_start_time = clock_gettime
|
|
94
|
-
|
|
97
|
+
# steep:ignore:start
|
|
98
|
+
fully_release_lock(
|
|
99
|
+
redis, lock_name, lock_key, lock_key_queue, read_lock_key_queue, lock_readers_key
|
|
100
|
+
) => { ok:, result: }
|
|
101
|
+
# steep:ignore:end
|
|
95
102
|
|
|
96
103
|
# @type var ok: bool
|
|
97
104
|
# @type var result: Hash[Symbol,Symbol]
|
|
@@ -131,36 +138,60 @@ module RedisQueuedLocks::Acquirer::ReleaseLock
|
|
|
131
138
|
|
|
132
139
|
private
|
|
133
140
|
|
|
134
|
-
# Realease the lock: clear the lock
|
|
141
|
+
# Realease the lock: clear the lock queues and expire the lock (write lock and read locks).
|
|
135
142
|
#
|
|
136
143
|
# @param redis [RedisClient]
|
|
144
|
+
# @param lock_name [String]
|
|
137
145
|
# @param lock_key [String]
|
|
138
146
|
# @param lock_key_queue [String]
|
|
147
|
+
# @param read_lock_key_queue [String]
|
|
148
|
+
# @param lock_readers_key [String]
|
|
139
149
|
# @return [Hash<Symbol,Boolean|Hash<Symbol,Symbol>>]
|
|
140
150
|
# Format: {
|
|
141
151
|
# ok: true/false,
|
|
142
152
|
# result: {
|
|
143
|
-
# queue: :released/:nothing_to_release,
|
|
144
|
-
# lock: :released/:nothing_to_release
|
|
153
|
+
# queue: :released/:nothing_to_release, # (any of the lock queues)
|
|
154
|
+
# lock: :released/:nothing_to_release # (write lock or read locks)
|
|
145
155
|
# }
|
|
146
156
|
# }
|
|
147
157
|
#
|
|
148
158
|
# @api private
|
|
149
159
|
# @since 1.0.0
|
|
150
|
-
|
|
151
|
-
|
|
160
|
+
# @version 1.18.0
|
|
161
|
+
def fully_release_lock(
|
|
162
|
+
redis,
|
|
163
|
+
lock_name,
|
|
164
|
+
lock_key,
|
|
165
|
+
lock_key_queue,
|
|
166
|
+
read_lock_key_queue,
|
|
167
|
+
lock_readers_key
|
|
168
|
+
)
|
|
169
|
+
# @type var result: [Integer,Integer,Integer,Integer]
|
|
152
170
|
result = redis.with do |rconn|
|
|
171
|
+
# NOTE: (RW) data of read locks (it is a data carrier only: read locks are released via
|
|
172
|
+
# the readers registry, so the data of concurrently obtained read locks expires itself)
|
|
173
|
+
# @type var read_lock_acquirers: Array[String]
|
|
174
|
+
read_lock_acquirers = rconn.call('ZRANGE', lock_readers_key, '0', '-1')
|
|
175
|
+
|
|
153
176
|
rconn.multi do |transact|
|
|
154
177
|
transact.call('ZREMRANGEBYSCORE', lock_key_queue, '-inf', '+inf')
|
|
155
178
|
transact.call('EXPIRE', lock_key, '0')
|
|
179
|
+
transact.call('ZREMRANGEBYSCORE', read_lock_key_queue, '-inf', '+inf')
|
|
180
|
+
transact.call('EXPIRE', lock_readers_key, '0')
|
|
181
|
+
read_lock_acquirers.each do |acquirer_id|
|
|
182
|
+
transact.call(
|
|
183
|
+
'DEL',
|
|
184
|
+
RedisQueuedLocks::Resource.prepare_read_lock_key(lock_name, acquirer_id)
|
|
185
|
+
)
|
|
186
|
+
end
|
|
156
187
|
end
|
|
157
188
|
end
|
|
158
189
|
|
|
159
190
|
{
|
|
160
191
|
ok: true,
|
|
161
192
|
result: {
|
|
162
|
-
queue: (result[0] != 0) ? :released : :nothing_to_release,
|
|
163
|
-
lock: (result[1] != 0) ? :released : :nothing_to_release
|
|
193
|
+
queue: (result[0] != 0 || result[2] != 0) ? :released : :nothing_to_release,
|
|
194
|
+
lock: (result[1] != 0 || result[3] != 0) ? :released : :nothing_to_release
|
|
164
195
|
}
|
|
165
196
|
}
|
|
166
197
|
end
|
|
@@ -2,12 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
# @api private
|
|
4
4
|
# @since 1.14.0
|
|
5
|
+
# @version 1.18.0
|
|
6
|
+
# rubocop:disable Metrics/ModuleLength
|
|
5
7
|
module RedisQueuedLocks::Acquirer::ReleaseLocksOf
|
|
6
8
|
# @since 1.14.0
|
|
7
9
|
extend RedisQueuedLocks::Utilities
|
|
8
10
|
|
|
11
|
+
# rubocop:disable Metrics/ClassLength
|
|
9
12
|
class << self
|
|
10
|
-
# Release all queues and locks that belong to the given host
|
|
13
|
+
# Release all queues and locks (write locks and read locks) that belong to the given host
|
|
14
|
+
# and its associated acquirer.
|
|
11
15
|
#
|
|
12
16
|
# @param refused_host_id [String]
|
|
13
17
|
# A host whose locks and queues should be released.
|
|
@@ -84,7 +88,7 @@ module RedisQueuedLocks::Acquirer::ReleaseLocksOf
|
|
|
84
88
|
#
|
|
85
89
|
# @api private
|
|
86
90
|
# @since 1.14.0
|
|
87
|
-
# @version 1.
|
|
91
|
+
# @version 1.18.0
|
|
88
92
|
# rubocop:disable Metrics/MethodLength
|
|
89
93
|
def release_locks_of(
|
|
90
94
|
refused_host_id,
|
|
@@ -164,6 +168,7 @@ module RedisQueuedLocks::Acquirer::ReleaseLocksOf
|
|
|
164
168
|
#
|
|
165
169
|
# @api private
|
|
166
170
|
# @since 1.14.0
|
|
171
|
+
# @version 1.18.0
|
|
167
172
|
# rubocop:disable Metrics/MethodLength
|
|
168
173
|
def fully_release_locks_of(
|
|
169
174
|
refused_host_id,
|
|
@@ -203,6 +208,30 @@ module RedisQueuedLocks::Acquirer::ReleaseLocksOf
|
|
|
203
208
|
rel_key_cnt += refused_locks.size
|
|
204
209
|
end
|
|
205
210
|
|
|
211
|
+
# Step A (RW): drop read locks of the passed host/acquirer
|
|
212
|
+
# - read locks store acquirer ids only (the host is a part of the acquirer id);
|
|
213
|
+
if RedisQueuedLocks::Resource.host_identifier_from_acquirer(refused_acquirer_id) ==
|
|
214
|
+
refused_host_id
|
|
215
|
+
rconn.scan(
|
|
216
|
+
'MATCH',
|
|
217
|
+
RedisQueuedLocks::Resource::LOCK_READERS_PATTERN,
|
|
218
|
+
count: lock_scan_size
|
|
219
|
+
) do |lock_readers_key|
|
|
220
|
+
res = rconn.call('ZREM', lock_readers_key, refused_acquirer_id)
|
|
221
|
+
next if res == 0
|
|
222
|
+
|
|
223
|
+
rel_key_cnt += 1
|
|
224
|
+
# NOTE: drop the read lock data
|
|
225
|
+
rconn.call(
|
|
226
|
+
'DEL',
|
|
227
|
+
RedisQueuedLocks::Resource.prepare_read_lock_key(
|
|
228
|
+
RedisQueuedLocks::Resource.lock_name_from_readers(lock_readers_key),
|
|
229
|
+
refused_acquirer_id
|
|
230
|
+
)
|
|
231
|
+
)
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
206
235
|
# Step B: drop passed host/acquirer from lock queues
|
|
207
236
|
rconn.scan(
|
|
208
237
|
'MATCH',
|
|
@@ -212,10 +241,21 @@ module RedisQueuedLocks::Acquirer::ReleaseLocksOf
|
|
|
212
241
|
res = rconn.call('ZREM', lock_queue, refused_acquirer_id)
|
|
213
242
|
tch_queue_cnt += 1 if res != 0
|
|
214
243
|
end
|
|
244
|
+
|
|
245
|
+
# Step B (RW): drop passed host/acquirer from read lock queues
|
|
246
|
+
rconn.scan(
|
|
247
|
+
'MATCH',
|
|
248
|
+
RedisQueuedLocks::Resource::READ_LOCK_QUEUE_PATTERN,
|
|
249
|
+
count: queue_scan_size
|
|
250
|
+
) do |read_lock_queue|
|
|
251
|
+
res = rconn.call('ZREM', read_lock_queue, refused_acquirer_id)
|
|
252
|
+
tch_queue_cnt += 1 if res != 0
|
|
253
|
+
end
|
|
215
254
|
end
|
|
216
255
|
|
|
217
256
|
{ ok: true, result: { rel_key_cnt:, tch_queue_cnt: } }
|
|
218
257
|
end
|
|
219
258
|
end
|
|
220
|
-
# rubocop:enable Metrics/MethodLength
|
|
259
|
+
# rubocop:enable Metrics/MethodLength, Metrics/ClassLength
|
|
221
260
|
end
|
|
261
|
+
# rubocop:enable Metrics/ModuleLength
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# @api private
|
|
4
|
+
# @since 1.18.0
|
|
5
|
+
module RedisQueuedLocks::Acquirer::ReleaseReadLock
|
|
6
|
+
# @since 1.18.0
|
|
7
|
+
extend RedisQueuedLocks::Utilities
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
# Release the read lock of the concrete acquirer (other read locks, the write lock and
|
|
11
|
+
# lock requests are not affected): drop the acquirer from the readers registry and drop
|
|
12
|
+
# its read lock data.
|
|
13
|
+
#
|
|
14
|
+
# @param redis [RedisClient]
|
|
15
|
+
# Redis connection client.
|
|
16
|
+
# @param lock_name [String]
|
|
17
|
+
# The lock name whose read lock should be released.
|
|
18
|
+
# @param acquirer_id [String]
|
|
19
|
+
# The read lock acquirer.
|
|
20
|
+
# @param instrumenter [#notify]
|
|
21
|
+
# See RedisQueuedLocks::Instrument::ActiveSupport for example.
|
|
22
|
+
# @param logger [::Logger,#debug]
|
|
23
|
+
# - Logger object used from `configuration` layer (see config['logger']);
|
|
24
|
+
# - See RedisQueuedLocks::Logging::VoidLogger for example;
|
|
25
|
+
# @param instrument [NilClass,Any]
|
|
26
|
+
# - Custom instrumentation data wich will be passed to the instrumenter's payload
|
|
27
|
+
# with :instrument key;
|
|
28
|
+
# @param log_sampling_enabled [Boolean]
|
|
29
|
+
# @param log_sampling_percent [Integer]
|
|
30
|
+
# @param log_sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
|
|
31
|
+
# @param log_sample_this [Boolean]
|
|
32
|
+
# @param instr_sampling_enabled [Boolean]
|
|
33
|
+
# - enables <instrumentaion sampling>: only the configured percent
|
|
34
|
+
# of RQL cases will be instrumented;
|
|
35
|
+
# @param instr_sampling_percent [Integer]
|
|
36
|
+
# - the percent of cases that should be instrumented;
|
|
37
|
+
# @param instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
|
|
38
|
+
# - percent-based sampler that decides should be RQL case instrumented or not;
|
|
39
|
+
# @param instr_sample_this [Boolean]
|
|
40
|
+
# - marks the method that everything should be instrumneted
|
|
41
|
+
# despite the enabled instrumentation sampling;
|
|
42
|
+
# @return [Hash<Symbol,Boolean<Hash<Symbol,Numeric|String|Symbol>>]
|
|
43
|
+
# Format: {
|
|
44
|
+
# ok: true,
|
|
45
|
+
# result: {
|
|
46
|
+
# rel_time: Numeric, # <milliseconds>
|
|
47
|
+
# rel_key: String, # lock key
|
|
48
|
+
# rel_acq_id: String, # read lock acquirer
|
|
49
|
+
# lock_res: Symbol # :released or :nothing_to_release
|
|
50
|
+
# }
|
|
51
|
+
# }
|
|
52
|
+
#
|
|
53
|
+
# @api private
|
|
54
|
+
# @since 1.18.0
|
|
55
|
+
# rubocop:disable Metrics/MethodLength
|
|
56
|
+
def release_read_lock(
|
|
57
|
+
redis,
|
|
58
|
+
lock_name,
|
|
59
|
+
acquirer_id,
|
|
60
|
+
instrumenter,
|
|
61
|
+
logger,
|
|
62
|
+
instrument,
|
|
63
|
+
log_sampling_enabled,
|
|
64
|
+
log_sampling_percent,
|
|
65
|
+
log_sampler,
|
|
66
|
+
log_sample_this,
|
|
67
|
+
instr_sampling_enabled,
|
|
68
|
+
instr_sampling_percent,
|
|
69
|
+
instr_sampler,
|
|
70
|
+
instr_sample_this
|
|
71
|
+
)
|
|
72
|
+
lock_key = RedisQueuedLocks::Resource.prepare_lock_key(lock_name)
|
|
73
|
+
lock_readers_key = RedisQueuedLocks::Resource.prepare_lock_readers(lock_name)
|
|
74
|
+
read_lock_key = RedisQueuedLocks::Resource.prepare_read_lock_key(lock_name, acquirer_id)
|
|
75
|
+
|
|
76
|
+
rel_start_time = clock_gettime
|
|
77
|
+
# steep:ignore:start
|
|
78
|
+
fully_release_read_lock(
|
|
79
|
+
redis, lock_readers_key, read_lock_key, acquirer_id
|
|
80
|
+
) => { ok:, result: }
|
|
81
|
+
# steep:ignore:end
|
|
82
|
+
|
|
83
|
+
# @type var ok: bool
|
|
84
|
+
# @type var result: Hash[Symbol,Symbol]
|
|
85
|
+
|
|
86
|
+
time_at = Time.now.to_f
|
|
87
|
+
rel_end_time = clock_gettime
|
|
88
|
+
rel_time = ((rel_end_time - rel_start_time) / 1_000.0).ceil(2)
|
|
89
|
+
|
|
90
|
+
instr_sampled = RedisQueuedLocks::Instrument.should_instrument?(
|
|
91
|
+
instr_sampling_enabled,
|
|
92
|
+
instr_sample_this,
|
|
93
|
+
instr_sampling_percent,
|
|
94
|
+
instr_sampler
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
run_non_critical do
|
|
98
|
+
instrumenter.notify('redis_queued_locks.explicit_read_lock_release', {
|
|
99
|
+
lock_key: lock_key,
|
|
100
|
+
acq_id: acquirer_id,
|
|
101
|
+
lock_res: result[:lock],
|
|
102
|
+
rel_time: rel_time,
|
|
103
|
+
at: time_at,
|
|
104
|
+
instrument: instrument
|
|
105
|
+
})
|
|
106
|
+
end if instr_sampled
|
|
107
|
+
|
|
108
|
+
{
|
|
109
|
+
ok: true,
|
|
110
|
+
result: {
|
|
111
|
+
rel_time: rel_time,
|
|
112
|
+
rel_key: lock_key,
|
|
113
|
+
rel_acq_id: acquirer_id,
|
|
114
|
+
lock_res: result[:lock]
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
end
|
|
118
|
+
# rubocop:enable Metrics/MethodLength
|
|
119
|
+
|
|
120
|
+
private
|
|
121
|
+
|
|
122
|
+
# @param redis [RedisClient]
|
|
123
|
+
# @param lock_readers_key [String]
|
|
124
|
+
# @param read_lock_key [String]
|
|
125
|
+
# @param acquirer_id [String]
|
|
126
|
+
# @return [Hash<Symbol,Boolean|Hash<Symbol,Symbol>>]
|
|
127
|
+
# Format: { ok: true, result: { lock: :released/:nothing_to_release } }
|
|
128
|
+
#
|
|
129
|
+
# @api private
|
|
130
|
+
# @since 1.18.0
|
|
131
|
+
def fully_release_read_lock(redis, lock_readers_key, read_lock_key, acquirer_id)
|
|
132
|
+
# @type var result: [Integer,Integer]
|
|
133
|
+
result = redis.with do |rconn|
|
|
134
|
+
rconn.multi do |transact|
|
|
135
|
+
transact.call('ZREM', lock_readers_key, acquirer_id)
|
|
136
|
+
transact.call('DEL', read_lock_key)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
{ ok: true, result: { lock: (result[0] != 0) ? :released : :nothing_to_release } }
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
@@ -6,6 +6,7 @@ module RedisQueuedLocks::Acquirer
|
|
|
6
6
|
require_relative 'acquirer/acquire_lock'
|
|
7
7
|
require_relative 'acquirer/lock_series_poc'
|
|
8
8
|
require_relative 'acquirer/release_lock'
|
|
9
|
+
require_relative 'acquirer/release_read_lock'
|
|
9
10
|
require_relative 'acquirer/release_all_locks'
|
|
10
11
|
require_relative 'acquirer/release_locks_of'
|
|
11
12
|
require_relative 'acquirer/is_locked'
|