redis_queued_locks 1.5.0 → 1.7.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/CHANGELOG.md +15 -1
- data/README.md +234 -58
- data/lib/redis_queued_locks/acquier/acquire_lock/dequeue_from_lock_queue/log_visitor.rb +36 -0
- data/lib/redis_queued_locks/acquier/acquire_lock/dequeue_from_lock_queue.rb +39 -0
- data/lib/redis_queued_locks/acquier/acquire_lock/instr_visitor.rb +151 -0
- data/lib/redis_queued_locks/acquier/acquire_lock/log_visitor.rb +192 -0
- data/lib/redis_queued_locks/acquier/acquire_lock/try_to_lock/log_visitor.rb +485 -0
- data/lib/redis_queued_locks/acquier/acquire_lock/try_to_lock.rb +76 -197
- data/lib/redis_queued_locks/acquier/acquire_lock/yield_expire/log_visitor.rb +68 -0
- data/lib/redis_queued_locks/acquier/acquire_lock/yield_expire.rb +17 -21
- data/lib/redis_queued_locks/acquier/acquire_lock.rb +128 -123
- data/lib/redis_queued_locks/acquier/clear_dead_requests.rb +8 -1
- data/lib/redis_queued_locks/acquier/extend_lock_ttl.rb +12 -2
- data/lib/redis_queued_locks/acquier/release_all_locks.rb +44 -8
- data/lib/redis_queued_locks/acquier/release_lock.rb +46 -14
- data/lib/redis_queued_locks/client.rb +128 -31
- data/lib/redis_queued_locks/instrument/sampler.rb +27 -0
- data/lib/redis_queued_locks/instrument.rb +47 -0
- data/lib/redis_queued_locks/logging/sampler.rb +10 -3
- data/lib/redis_queued_locks/logging.rb +1 -0
- data/lib/redis_queued_locks/utilities.rb +0 -1
- data/lib/redis_queued_locks/version.rb +2 -2
- data/lib/redis_queued_locks/watcher.rb +1 -0
- data/redis_queued_locks.gemspec +23 -3
- metadata +15 -6
@@ -2,10 +2,10 @@
|
|
2
2
|
|
3
3
|
# @api private
|
4
4
|
# @since 1.0.0
|
5
|
+
# @version 1.7.0
|
5
6
|
# rubocop:disable Metrics/ModuleLength, Metrics/BlockNesting
|
6
7
|
module RedisQueuedLocks::Acquier::AcquireLock::TryToLock
|
7
|
-
|
8
|
-
extend RedisQueuedLocks::Utilities
|
8
|
+
require_relative 'try_to_lock/log_visitor'
|
9
9
|
|
10
10
|
# @return [String]
|
11
11
|
#
|
@@ -27,13 +27,15 @@ module RedisQueuedLocks::Acquier::AcquireLock::TryToLock
|
|
27
27
|
# @param queue_ttl [Integer]
|
28
28
|
# @param fail_fast [Boolean]
|
29
29
|
# @param conflict_strategy [Symbol]
|
30
|
+
# @param access_strategy [Symbol]
|
30
31
|
# @param meta [NilClass,Hash<String|Symbol,Any>]
|
31
32
|
# @param log_sampled [Boolean]
|
33
|
+
# @param instr_sampled [Boolean]
|
32
34
|
# @return [Hash<Symbol,Any>] Format: { ok: true/false, result: Symbol|Hash<Symbol,Any> }
|
33
35
|
#
|
34
36
|
# @api private
|
35
37
|
# @since 1.0.0
|
36
|
-
# @version 1.
|
38
|
+
# @version 1.7.0
|
37
39
|
# rubocop:disable Metrics/MethodLength
|
38
40
|
def try_to_lock(
|
39
41
|
redis,
|
@@ -47,37 +49,27 @@ module RedisQueuedLocks::Acquier::AcquireLock::TryToLock
|
|
47
49
|
queue_ttl,
|
48
50
|
fail_fast,
|
49
51
|
conflict_strategy,
|
52
|
+
access_strategy,
|
50
53
|
meta,
|
51
|
-
log_sampled
|
54
|
+
log_sampled,
|
55
|
+
instr_sampled
|
52
56
|
)
|
53
57
|
# Step X: intermediate invocation results
|
54
58
|
inter_result = nil
|
55
59
|
timestamp = nil
|
56
60
|
spc_processed_timestamp = nil
|
57
61
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
"lock_key => '#{lock_key}' " \
|
63
|
-
"queue_ttl => #{queue_ttl} " \
|
64
|
-
"acq_id => '#{acquier_id}'"
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
62
|
+
LogVisitor.start(
|
63
|
+
logger, log_sampled, log_lock_try,
|
64
|
+
lock_key, queue_ttl, acquier_id, access_strategy
|
65
|
+
)
|
68
66
|
|
69
67
|
# Step X: start to work with lock acquiring
|
70
68
|
result = redis.with do |rconn|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
"lock_key => '#{lock_key}' " \
|
76
|
-
"queue_ttl => #{queue_ttl} " \
|
77
|
-
"acq_id => '#{acquier_id}'"
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
69
|
+
LogVisitor.rconn_fetched(
|
70
|
+
logger, log_sampled, log_lock_try,
|
71
|
+
lock_key, queue_ttl, acquier_id, access_strategy
|
72
|
+
)
|
81
73
|
|
82
74
|
# Step 0:
|
83
75
|
# watch the lock key changes (and discard acquirement if lock is already
|
@@ -90,16 +82,10 @@ module RedisQueuedLocks::Acquier::AcquireLock::TryToLock
|
|
90
82
|
|
91
83
|
# SP-Conflict Step X1: calculate the current deadlock status
|
92
84
|
if current_lock_obtainer != nil && acquier_id == current_lock_obtainer
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
"lock_key => '#{lock_key}' " \
|
98
|
-
"queue_ttl => #{queue_ttl} " \
|
99
|
-
"acq_id => '#{acquier_id}'"
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
85
|
+
LogVisitor.same_process_conflict_detected(
|
86
|
+
logger, log_sampled, log_lock_try,
|
87
|
+
lock_key, queue_ttl, acquier_id, access_strategy
|
88
|
+
)
|
103
89
|
|
104
90
|
# SP-Conflict Step X2: self-process dead lock moment started.
|
105
91
|
# SP-Conflict CHECK (Step CHECK): check chosen strategy and flag the current status
|
@@ -126,17 +112,10 @@ module RedisQueuedLocks::Acquier::AcquireLock::TryToLock
|
|
126
112
|
end
|
127
113
|
# rubocop:enable Lint/DuplicateBranch
|
128
114
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
"lock_key => '#{lock_key}' " \
|
134
|
-
"queue_ttl => #{queue_ttl} " \
|
135
|
-
"acq_id => '#{acquier_id}' " \
|
136
|
-
"spc_status => '#{sp_conflict_status}'"
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
115
|
+
LogVisitor.same_process_conflict_analyzed(
|
116
|
+
logger, log_sampled, log_lock_try,
|
117
|
+
lock_key, queue_ttl, acquier_id, access_strategy, sp_conflict_status
|
118
|
+
)
|
140
119
|
end
|
141
120
|
|
142
121
|
# SP-Conflict-Step X2: switch to conflict-based logic or not
|
@@ -174,19 +153,11 @@ module RedisQueuedLocks::Acquier::AcquireLock::TryToLock
|
|
174
153
|
)
|
175
154
|
inter_result = :extendable_conflict_work_through
|
176
155
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
"queue_ttl => #{queue_ttl} " \
|
183
|
-
"acq_id => '#{acquier_id}'" \
|
184
|
-
"spc_status => '#{sp_conflict_status} '" \
|
185
|
-
"last_ext_ttl => '#{ttl}' " \
|
186
|
-
"last_ext_ts => '#{spc_processed_timestamp}'"
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
156
|
+
LogVisitor.reentrant_lock__extend_and_work_through(
|
157
|
+
logger, log_sampled, log_lock_try,
|
158
|
+
lock_key, queue_ttl, acquier_id, access_strategy,
|
159
|
+
sp_conflict_status, ttl, spc_processed_timestamp
|
160
|
+
)
|
190
161
|
# SP-Conflict-Step X2: switch to dead lock logic or not
|
191
162
|
elsif sp_conflict_status == :conflict_work_through
|
192
163
|
inter_result = :conflict_work_through
|
@@ -207,33 +178,21 @@ module RedisQueuedLocks::Acquier::AcquireLock::TryToLock
|
|
207
178
|
'l_spc_ts', (spc_processed_timestamp = Time.now.to_f)
|
208
179
|
)
|
209
180
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
"queue_ttl => #{queue_ttl} " \
|
216
|
-
"acq_id => '#{acquier_id}' " \
|
217
|
-
"spc_status => '#{sp_conflict_status} ' " \
|
218
|
-
"last_spc_ts => '#{spc_processed_timestamp}'"
|
219
|
-
end
|
220
|
-
end
|
221
|
-
end
|
181
|
+
LogVisitor.reentrant_lock__work_through(
|
182
|
+
logger, log_sampled, log_lock_try,
|
183
|
+
lock_key, queue_ttl, acquier_id, access_strategy,
|
184
|
+
sp_conflict_status, spc_processed_timestamp
|
185
|
+
)
|
222
186
|
# SP-Conflict-Step X2: switch to dead lock logic or not
|
223
187
|
elsif sp_conflict_status == :conflict_dead_lock
|
224
188
|
inter_result = :conflict_dead_lock
|
225
189
|
spc_processed_timestamp = Time.now.to_f
|
226
190
|
|
227
|
-
|
228
|
-
logger
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
"acq_id => '#{acquier_id}' " \
|
233
|
-
"spc_status => '#{sp_conflict_status}' " \
|
234
|
-
"last_spc_ts => '#{spc_processed_timestamp}'"
|
235
|
-
end
|
236
|
-
end
|
191
|
+
LogVisitor.single_process_lock_conflict__dead_lock(
|
192
|
+
logger, log_sampled, log_lock_try,
|
193
|
+
lock_key, queue_ttl, acquier_id, access_strategy,
|
194
|
+
sp_conflict_status, spc_processed_timestamp
|
195
|
+
)
|
237
196
|
# Reached the SP-Non-Conflict Mode (NOTE):
|
238
197
|
# - in other sp-conflict cases we are in <wait_for_lock> (non-conflict) status and should
|
239
198
|
# continue to work in classic way (next lines of code):
|
@@ -244,16 +203,10 @@ module RedisQueuedLocks::Acquier::AcquireLock::TryToLock
|
|
244
203
|
# Step 1: add an acquier to the lock acquirement queue
|
245
204
|
rconn.call('ZADD', lock_key_queue, 'NX', acquier_position, acquier_id)
|
246
205
|
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
"lock_key => '#{lock_key}' " \
|
252
|
-
"queue_ttl => #{queue_ttl} " \
|
253
|
-
"acq_id => '#{acquier_id}'"
|
254
|
-
end
|
255
|
-
end
|
256
|
-
end
|
206
|
+
LogVisitor.acq_added_to_queue(
|
207
|
+
logger, log_sampled, log_lock_try,
|
208
|
+
lock_key, queue_ttl, acquier_id, access_strategy
|
209
|
+
)
|
257
210
|
|
258
211
|
# Step 2.1: drop expired acquiers from the lock queue
|
259
212
|
rconn.call(
|
@@ -263,66 +216,41 @@ module RedisQueuedLocks::Acquier::AcquireLock::TryToLock
|
|
263
216
|
RedisQueuedLocks::Resource.acquier_dead_score(queue_ttl)
|
264
217
|
)
|
265
218
|
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
"lock_key => '#{lock_key}' " \
|
271
|
-
"queue_ttl => #{queue_ttl} " \
|
272
|
-
"acq_id => '#{acquier_id}'"
|
273
|
-
end
|
274
|
-
end
|
275
|
-
end
|
219
|
+
LogVisitor.remove_expired_acqs(
|
220
|
+
logger, log_sampled, log_lock_try,
|
221
|
+
lock_key, queue_ttl, acquier_id, access_strategy
|
222
|
+
)
|
276
223
|
|
277
224
|
# Step 3: get the actual acquier waiting in the queue
|
278
225
|
waiting_acquier = Array(rconn.call('ZRANGE', lock_key_queue, '0', '0')).first
|
279
226
|
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
"lock_key => '#{lock_key}' " \
|
285
|
-
"queue_ttl => #{queue_ttl} " \
|
286
|
-
"acq_id => '#{acquier_id}' " \
|
287
|
-
"first_acq_id_in_queue => '#{waiting_acquier}'"
|
288
|
-
end
|
289
|
-
end
|
290
|
-
end
|
227
|
+
LogVisitor.get_first_from_queue(
|
228
|
+
logger, log_sampled, log_lock_try,
|
229
|
+
lock_key, queue_ttl, acquier_id, access_strategy, waiting_acquier
|
230
|
+
)
|
291
231
|
|
292
232
|
# Step PRE-4.x: check if the request time limit is reached
|
293
233
|
# (when the current try self-removes itself from queue (queue ttl has come))
|
294
234
|
if waiting_acquier == nil
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
"lock_key => '#{lock_key}' " \
|
300
|
-
"queue_ttl => #{queue_ttl} " \
|
301
|
-
"acq_id => '#{acquier_id}'"
|
302
|
-
end
|
303
|
-
end
|
304
|
-
end
|
235
|
+
LogVisitor.exit__queue_ttl_reached(
|
236
|
+
logger, log_sampled, log_lock_try,
|
237
|
+
lock_key, queue_ttl, acquier_id, access_strategy
|
238
|
+
)
|
305
239
|
|
306
240
|
inter_result = :dead_score_reached
|
307
|
-
|
308
|
-
|
241
|
+
# Step STRATEGY: check the stragegy and corresponding preventing factor
|
242
|
+
# Step STRATEGY (queued): check the actual acquier: is it ours? are we aready to lock?
|
243
|
+
elsif access_strategy == :queued && waiting_acquier != acquier_id
|
309
244
|
# Step ROLLBACK 1.1: our time hasn't come yet. retry!
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
"lock_key => '#{lock_key}' " \
|
316
|
-
"queue_ttl => #{queue_ttl} " \
|
317
|
-
"acq_id => '#{acquier_id}' " \
|
318
|
-
"first_acq_id_in_queue => '#{waiting_acquier}' " \
|
319
|
-
"<current_lock_data> => <<#{rconn.call('HGETALL', lock_key).to_h}>>"
|
320
|
-
end
|
321
|
-
end
|
322
|
-
end
|
323
|
-
|
245
|
+
LogVisitor.exit__no_first(
|
246
|
+
logger, log_sampled, log_lock_try,
|
247
|
+
lock_key, queue_ttl, acquier_id, access_strategy, waiting_acquier,
|
248
|
+
rconn.call('HGETALL', lock_key).to_h
|
249
|
+
)
|
324
250
|
inter_result = :acquier_is_not_first_in_queue
|
325
|
-
|
251
|
+
# Step STRAGEY: successfull (:queued OR :random)
|
252
|
+
elsif (access_strategy == :queued && waiting_acquier == acquier_id) ||
|
253
|
+
(access_strategy == :random)
|
326
254
|
# NOTE: our time has come! let's try to acquire the lock!
|
327
255
|
|
328
256
|
# Step 5: find the lock -> check if the our lock is already acquired
|
@@ -331,20 +259,12 @@ module RedisQueuedLocks::Acquier::AcquireLock::TryToLock
|
|
331
259
|
if locked_by_acquier
|
332
260
|
# Step ROLLBACK 2: required lock is stil acquired. retry!
|
333
261
|
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
"acq_id => '#{acquier_id}' " \
|
341
|
-
"first_acq_id_in_queue => '#{waiting_acquier}' " \
|
342
|
-
"locked_by_acq_id => '#{locked_by_acquier}' " \
|
343
|
-
"<current_lock_data> => <<#{rconn.call('HGETALL', lock_key).to_h}>>"
|
344
|
-
end
|
345
|
-
end
|
346
|
-
end
|
347
|
-
|
262
|
+
LogVisitor.exit__lock_still_obtained(
|
263
|
+
logger, log_sampled, log_lock_try,
|
264
|
+
lock_key, queue_ttl, acquier_id, access_strategy,
|
265
|
+
waiting_acquier, locked_by_acquier,
|
266
|
+
rconn.call('HGETALL', lock_key).to_h
|
267
|
+
)
|
348
268
|
inter_result = :lock_is_still_acquired
|
349
269
|
else
|
350
270
|
# NOTE: required lock is free and ready to be acquired! acquire!
|
@@ -365,16 +285,10 @@ module RedisQueuedLocks::Acquier::AcquireLock::TryToLock
|
|
365
285
|
# Step 6.3: set the lock expiration time in order to prevent "infinite locks"
|
366
286
|
transact.call('PEXPIRE', lock_key, ttl) # NOTE: in milliseconds
|
367
287
|
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
"lock_key => '#{lock_key}' " \
|
373
|
-
"queue_ttl => #{queue_ttl} " \
|
374
|
-
"acq_id => '#{acquier_id}'"
|
375
|
-
end
|
376
|
-
end
|
377
|
-
end
|
288
|
+
LogVisitor.obtain__free_to_acquire(
|
289
|
+
logger, log_sampled, log_lock_try,
|
290
|
+
lock_key, queue_ttl, acquier_id, access_strategy
|
291
|
+
)
|
378
292
|
end
|
379
293
|
end
|
380
294
|
end
|
@@ -477,40 +391,5 @@ module RedisQueuedLocks::Acquier::AcquireLock::TryToLock
|
|
477
391
|
# rubocop:enable Lint/DuplicateBranch
|
478
392
|
end
|
479
393
|
# rubocop:enable Metrics/MethodLength, Metrics/PerceivedComplexity
|
480
|
-
|
481
|
-
# @param redis [RedisClient]
|
482
|
-
# @param logger [::Logger,#debug]
|
483
|
-
# @param lock_key [String]
|
484
|
-
# @param lock_key_queue [String]
|
485
|
-
# @param queue_ttl [Integer]
|
486
|
-
# @param acquier_id [String]
|
487
|
-
# @param log_sampled [Boolean]
|
488
|
-
# @return [Hash<Symbol,Any>] Format: { ok: true/false, result: Any }
|
489
|
-
#
|
490
|
-
# @api private
|
491
|
-
# @since 1.0.0
|
492
|
-
# @version 1.5.0
|
493
|
-
def dequeue_from_lock_queue(
|
494
|
-
redis,
|
495
|
-
logger,
|
496
|
-
lock_key,
|
497
|
-
lock_key_queue,
|
498
|
-
queue_ttl,
|
499
|
-
acquier_id,
|
500
|
-
log_sampled
|
501
|
-
)
|
502
|
-
result = redis.call('ZREM', lock_key_queue, acquier_id)
|
503
|
-
|
504
|
-
run_non_critical do
|
505
|
-
logger.debug do
|
506
|
-
"[redis_queued_locks.fail_fast_or_limits_reached_or_deadlock__dequeue] " \
|
507
|
-
"lock_key => '#{lock_key}' " \
|
508
|
-
"queue_ttl => '#{queue_ttl}' " \
|
509
|
-
"acq_id => '#{acquier_id}'"
|
510
|
-
end
|
511
|
-
end if log_sampled
|
512
|
-
|
513
|
-
RedisQueuedLocks::Data[ok: true, result: result]
|
514
|
-
end
|
515
394
|
end
|
516
395
|
# rubocop:enable Metrics/ModuleLength, Metrics/BlockNesting
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 1.7.0
|
5
|
+
module RedisQueuedLocks::Acquier::AcquireLock::YieldExpire::LogVisitor
|
6
|
+
extend self
|
7
|
+
|
8
|
+
# @param logger [::Logger,#debug]
|
9
|
+
# @param log_sampled [Boolean]
|
10
|
+
# @param lock_key [String]
|
11
|
+
# @param queue_ttl [Integer]
|
12
|
+
# @param acquier_id [String]
|
13
|
+
# @param access_strategy [Symbol]
|
14
|
+
# @return [void]
|
15
|
+
#
|
16
|
+
# @api private
|
17
|
+
# @since 1.7.0
|
18
|
+
def expire_lock(
|
19
|
+
logger,
|
20
|
+
log_sampled,
|
21
|
+
lock_key,
|
22
|
+
queue_ttl,
|
23
|
+
acquier_id,
|
24
|
+
access_strategy
|
25
|
+
)
|
26
|
+
return unless log_sampled
|
27
|
+
|
28
|
+
logger.debug do
|
29
|
+
"[redis_queued_locks.expire_lock] " \
|
30
|
+
"lock_key => '#{lock_key}' " \
|
31
|
+
"queue_ttl => #{queue_ttl} " \
|
32
|
+
"acq_id => '#{acquier_id}' " \
|
33
|
+
"acs_strat => '#{access_strategy}'"
|
34
|
+
end rescue nil
|
35
|
+
end
|
36
|
+
|
37
|
+
# @param logger [::Logger,#debug]
|
38
|
+
# @param log_sampled [Boolean]
|
39
|
+
# @param lock_key [String]
|
40
|
+
# @param decreased_ttl [Integer]
|
41
|
+
# @param queue_ttl [Integer]
|
42
|
+
# @param acquier_id [String]
|
43
|
+
# @param access_strategy [Symbol]
|
44
|
+
# @return [void]
|
45
|
+
#
|
46
|
+
# @api private
|
47
|
+
# @since 1.7.0
|
48
|
+
def decrease_lock(
|
49
|
+
logger,
|
50
|
+
log_sampled,
|
51
|
+
lock_key,
|
52
|
+
decreased_ttl,
|
53
|
+
queue_ttl,
|
54
|
+
acquier_id,
|
55
|
+
access_strategy
|
56
|
+
)
|
57
|
+
return unless log_sampled
|
58
|
+
|
59
|
+
logger.debug do
|
60
|
+
"[redis_queued_locks.decrease_lock] " \
|
61
|
+
"lock_key => '#{lock_key}' " \
|
62
|
+
"decreased_ttl => #{decreased_ttl} " \
|
63
|
+
"queue_ttl => #{queue_ttl} " \
|
64
|
+
"acq_id => '#{acquier_id}' " \
|
65
|
+
"acs_strat => '#{access_strategy}'"
|
66
|
+
end rescue nil
|
67
|
+
end
|
68
|
+
end
|
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
# @api private
|
4
4
|
# @since 1.3.0
|
5
|
+
# @version 1.7.0
|
5
6
|
module RedisQueuedLocks::Acquier::AcquireLock::YieldExpire
|
6
|
-
|
7
|
-
extend RedisQueuedLocks::Utilities
|
7
|
+
require_relative 'yield_expire/log_visitor'
|
8
8
|
|
9
9
|
# @return [String]
|
10
10
|
#
|
@@ -19,12 +19,14 @@ module RedisQueuedLocks::Acquier::AcquireLock::YieldExpire
|
|
19
19
|
# @param logger [::Logger,#debug] Logger object.
|
20
20
|
# @param lock_key [String] Obtained lock key that should be expired.
|
21
21
|
# @param acquier_id [String] Acquier identifier.
|
22
|
+
# @param access_strategy [Symbol] Lock obtaining strategy.
|
22
23
|
# @param timed [Boolean] Should the lock be wrapped by Timeout with with lock's ttl
|
23
24
|
# @param ttl_shift [Float] Lock's TTL shifting. Should affect block's ttl. In millisecodns.
|
24
25
|
# @param ttl [Integer,NilClass] Lock's time to live (in ms). Nil means "without timeout".
|
25
26
|
# @param queue_ttl [Integer] Lock request lifetime.
|
26
27
|
# @param block [Block] Custom logic that should be invoked unter the obtained lock.
|
27
|
-
# @param log_sampled [Boolean] Should the logic be logged or not
|
28
|
+
# @param log_sampled [Boolean] Should the logic be logged or not.
|
29
|
+
# @param instr_sampled [Boolean] Should the logic be instrumented or not.
|
28
30
|
# @param should_expire [Boolean] Should the lock be expired after the block invocation.
|
29
31
|
# @param should_decrease [Boolean]
|
30
32
|
# - Should decrease the lock TTL after the lock invocation;
|
@@ -33,18 +35,20 @@ module RedisQueuedLocks::Acquier::AcquireLock::YieldExpire
|
|
33
35
|
#
|
34
36
|
# @api private
|
35
37
|
# @since 1.3.0
|
36
|
-
# @version 1.
|
38
|
+
# @version 1.7.0
|
37
39
|
# rubocop:disable Metrics/MethodLength
|
38
40
|
def yield_expire(
|
39
41
|
redis,
|
40
42
|
logger,
|
41
43
|
lock_key,
|
42
44
|
acquier_id,
|
45
|
+
access_strategy,
|
43
46
|
timed,
|
44
47
|
ttl_shift,
|
45
48
|
ttl,
|
46
49
|
queue_ttl,
|
47
50
|
log_sampled,
|
51
|
+
instr_sampled,
|
48
52
|
should_expire,
|
49
53
|
should_decrease,
|
50
54
|
&block
|
@@ -65,29 +69,21 @@ module RedisQueuedLocks::Acquier::AcquireLock::YieldExpire
|
|
65
69
|
end
|
66
70
|
ensure
|
67
71
|
if should_expire
|
68
|
-
|
69
|
-
logger
|
70
|
-
|
71
|
-
|
72
|
-
"queue_ttl => #{queue_ttl} " \
|
73
|
-
"acq_id => '#{acquier_id}'"
|
74
|
-
end
|
75
|
-
end if log_sampled
|
72
|
+
LogVisitor.expire_lock(
|
73
|
+
logger, log_sampled,
|
74
|
+
lock_key, queue_ttl, acquier_id, access_strategy
|
75
|
+
)
|
76
76
|
redis.call('EXPIRE', lock_key, '0')
|
77
77
|
elsif should_decrease
|
78
78
|
finish_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC, :millisecond)
|
79
79
|
spent_time = (finish_time - initial_time)
|
80
80
|
decreased_ttl = ttl - spent_time - RedisQueuedLocks::Resource::REDIS_TIMESHIFT_ERROR
|
81
|
+
|
81
82
|
if decreased_ttl > 0
|
82
|
-
|
83
|
-
logger
|
84
|
-
|
85
|
-
|
86
|
-
"decreased_ttl => '#{decreased_ttl} " \
|
87
|
-
"queue_ttl => #{queue_ttl} " \
|
88
|
-
"acq_id => '#{acquier_id}' " \
|
89
|
-
end
|
90
|
-
end if log_sampled
|
83
|
+
LogVisitor.decrease_lock(
|
84
|
+
logger, log_sampled,
|
85
|
+
lock_key, decreased_ttl, queue_ttl, acquier_id, access_strategy
|
86
|
+
)
|
91
87
|
# NOTE:# NOTE: EVAL signature -> <lua script>, (number of keys), *(keys), *(arguments)
|
92
88
|
redis.call('EVAL', DECREASE_LOCK_PTTL, 1, lock_key, decreased_ttl)
|
93
89
|
# TODO: upload scripts to the redis
|