redis_queued_locks 1.20.0 → 1.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.claude/project-overview.md +35 -13
- data/.claude/rules/acquirer.md +10 -9
- data/.claude/rules/logic.md +28 -5
- data/.claude/rules/swarm.md +2 -2
- data/.claude/rules/tests.md +6 -3
- data/.claude/rules/visitors.md +9 -10
- data/.claude/skills/rql-code-review/SKILL.md +24 -10
- data/CHANGELOG.md +126 -0
- data/CLAUDE.md +2 -1
- data/README.md +245 -70
- data/lib/redis_queued_locks/acquirer/acquire_lock/dequeue_from_lock_queue/log_visitor.rb +1 -0
- data/lib/redis_queued_locks/acquirer/acquire_lock/instr_visitor.rb +42 -0
- data/lib/redis_queued_locks/acquirer/acquire_lock/log_visitor.rb +45 -0
- data/lib/redis_queued_locks/acquirer/acquire_lock/try_to_lock/log_visitor.rb +1 -0
- data/lib/redis_queued_locks/acquirer/acquire_lock/try_to_lock.rb +12 -1
- data/lib/redis_queued_locks/acquirer/acquire_lock/with_acq_timeout.rb +2 -2
- data/lib/redis_queued_locks/acquirer/acquire_lock/yield_expire/log_visitor.rb +1 -0
- data/lib/redis_queued_locks/acquirer/acquire_lock/yield_expire.rb +5 -5
- data/lib/redis_queued_locks/acquirer/acquire_lock.rb +111 -24
- data/lib/redis_queued_locks/acquirer/clear_dead_requests.rb +86 -8
- data/lib/redis_queued_locks/acquirer/extend_lock_ttl.rb +122 -12
- data/lib/redis_queued_locks/acquirer/is_locked.rb +0 -1
- data/lib/redis_queued_locks/acquirer/is_queued.rb +0 -1
- data/lib/redis_queued_locks/acquirer/keys.rb +10 -1
- data/lib/redis_queued_locks/acquirer/lock_info.rb +31 -39
- data/lib/redis_queued_locks/acquirer/lock_series_poc/instr_visitor.rb +3 -2
- data/lib/redis_queued_locks/acquirer/lock_series_poc/log_visitor.rb +5 -4
- data/lib/redis_queued_locks/acquirer/lock_series_poc.rb +55 -15
- data/lib/redis_queued_locks/acquirer/locks.rb +26 -9
- data/lib/redis_queued_locks/acquirer/queue_info.rb +0 -1
- data/lib/redis_queued_locks/acquirer/queues.rb +10 -1
- data/lib/redis_queued_locks/acquirer/reindex_locks.rb +117 -4
- data/lib/redis_queued_locks/acquirer/release_all_locks.rb +31 -4
- data/lib/redis_queued_locks/acquirer/release_lock.rb +33 -7
- data/lib/redis_queued_locks/acquirer/release_locks_of.rb +39 -4
- data/lib/redis_queued_locks/acquirer/release_read_lock.rb +22 -3
- data/lib/redis_queued_locks/client.rb +82 -40
- data/lib/redis_queued_locks/config.rb +12 -13
- data/lib/redis_queued_locks/errors.rb +34 -4
- data/lib/redis_queued_locks/instrument/sampler.rb +4 -7
- data/lib/redis_queued_locks/logging/sampler.rb +4 -8
- data/lib/redis_queued_locks/resource.rb +14 -4
- data/lib/redis_queued_locks/swarm/flush_zombies.rb +1 -0
- data/lib/redis_queued_locks/swarm/redis_client_builder.rb +8 -4
- data/lib/redis_queued_locks/swarm/swarm_element/threaded.rb +3 -2
- data/lib/redis_queued_locks/swarm.rb +86 -5
- data/lib/redis_queued_locks/utilities.rb +1 -1
- data/lib/redis_queued_locks/version.rb +2 -2
- data/sig/redis_queued_locks/acquirer/acquire_lock/instr_visitor.rbs +14 -0
- data/sig/redis_queued_locks/acquirer/acquire_lock/log_visitor.rbs +13 -0
- data/sig/redis_queued_locks/acquirer/acquire_lock/yield_expire.rbs +2 -2
- data/sig/redis_queued_locks/acquirer/acquire_lock.rbs +1 -1
- data/sig/redis_queued_locks/acquirer/clear_dead_requests.rbs +9 -0
- data/sig/redis_queued_locks/acquirer/extend_lock_ttl.rbs +15 -2
- data/sig/redis_queued_locks/acquirer/reindex_locks.rbs +22 -1
- data/sig/redis_queued_locks/acquirer/release_lock.rbs +3 -2
- data/sig/redis_queued_locks/acquirer/release_read_lock.rbs +1 -1
- data/sig/redis_queued_locks/client.rbs +14 -3
- data/sig/redis_queued_locks/errors.rbs +5 -2
- data/sig/redis_queued_locks/instrument/sampler.rbs +0 -2
- data/sig/redis_queued_locks/logging/sampler.rbs +0 -2
- data/sig/redis_queued_locks/resource.rbs +1 -1
- data/sig/vendor/redis_client.rbs +1 -0
- metadata +1 -1
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
# @api private
|
|
4
4
|
# @since 1.20.0
|
|
5
|
+
# @version 1.21.0
|
|
6
|
+
# rubocop:disable Metrics/ModuleLength
|
|
5
7
|
module RedisQueuedLocks::Acquirer::ReindexLocks
|
|
8
|
+
# @since 1.21.0
|
|
9
|
+
extend RedisQueuedLocks::Utilities
|
|
10
|
+
|
|
11
|
+
# rubocop:disable Metrics/ClassLength
|
|
6
12
|
class << self
|
|
7
13
|
# Adds the lock keys without the lock index entry (keys of older RQL versions created before
|
|
8
14
|
# the lock index) to the lock index (`RedisQueuedLocks::Resource::LOCK_INDEX_KEY`):
|
|
@@ -16,18 +22,125 @@ module RedisQueuedLocks::Acquirer::ReindexLocks
|
|
|
16
22
|
# - keys without TTL (unreachable for RQL keys) are indexed forever (`+inf` score);
|
|
17
23
|
# - the index score is never decreased (`ZADD GT`): the operation is idempotent and can be
|
|
18
24
|
# invoked at any time (keys of the current RQL version are indexed already);
|
|
25
|
+
# - the operation is reported with one log and one instrumentation event
|
|
26
|
+
# (`redis_queued_locks.reindex_locks`) with the time of the whole operation;
|
|
19
27
|
#
|
|
20
28
|
# @param redis_client [RedisClient]
|
|
21
29
|
# @param scan_size [Integer]
|
|
22
30
|
# @param queue_ttl [Integer] TTL of the lock queues without TTL (in seconds).
|
|
23
31
|
# @param lock_index_grace_period [Integer]
|
|
24
32
|
# The lock index score margin over the key lifetime (in milliseconds).
|
|
33
|
+
# @param logger [::Logger,#debug]
|
|
34
|
+
# @param instrumenter [#notify]
|
|
35
|
+
# @param instrument [NilClass,Any]
|
|
36
|
+
# @param log_sampling_enabled [Boolean]
|
|
37
|
+
# @param log_sampling_percent [Integer]
|
|
38
|
+
# @param log_sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
|
|
39
|
+
# @param log_sample_this [Boolean]
|
|
40
|
+
# @param instr_sampling_enabled [Boolean]
|
|
41
|
+
# @param instr_sampling_percent [Integer]
|
|
42
|
+
# @param instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
|
|
43
|
+
# @param instr_sample_this [Boolean]
|
|
25
44
|
# @return [Hash<Symbol,Boolean|Hash<Symbol,Integer>>]
|
|
26
45
|
# Format: { ok: true, result: { idx_key_cnt: Integer } } (the number of indexed keys)
|
|
27
46
|
#
|
|
28
47
|
# @api private
|
|
29
48
|
# @since 1.20.0
|
|
30
|
-
|
|
49
|
+
# @version 1.21.0
|
|
50
|
+
# rubocop:disable Metrics/MethodLength
|
|
51
|
+
def reindex_locks(
|
|
52
|
+
redis_client,
|
|
53
|
+
scan_size,
|
|
54
|
+
queue_ttl,
|
|
55
|
+
lock_index_grace_period,
|
|
56
|
+
logger,
|
|
57
|
+
instrumenter,
|
|
58
|
+
instrument,
|
|
59
|
+
log_sampling_enabled,
|
|
60
|
+
log_sampling_percent,
|
|
61
|
+
log_sampler,
|
|
62
|
+
log_sample_this,
|
|
63
|
+
instr_sampling_enabled,
|
|
64
|
+
instr_sampling_percent,
|
|
65
|
+
instr_sampler,
|
|
66
|
+
instr_sample_this
|
|
67
|
+
)
|
|
68
|
+
# NOTE: (arguments) the same ranges as the config keys: zero/negative sizes fail SCAN
|
|
69
|
+
# (`COUNT 0`), a non-positive queue ttl expires the lock queues without TTL at once;
|
|
70
|
+
if !scan_size.is_a?(::Integer) || scan_size <= 0
|
|
71
|
+
raise(
|
|
72
|
+
RedisQueuedLocks::ArgumentError,
|
|
73
|
+
"`:scan_size` argument should be a positive Integer, got #{scan_size.inspect}."
|
|
74
|
+
)
|
|
75
|
+
end
|
|
76
|
+
if !queue_ttl.is_a?(::Integer) || queue_ttl <= 0
|
|
77
|
+
raise(
|
|
78
|
+
RedisQueuedLocks::ArgumentError,
|
|
79
|
+
"`:queue_ttl` argument should be a positive Integer, got #{queue_ttl.inspect}."
|
|
80
|
+
)
|
|
81
|
+
end
|
|
82
|
+
if !lock_index_grace_period.is_a?(::Integer) || lock_index_grace_period < 0
|
|
83
|
+
raise(
|
|
84
|
+
RedisQueuedLocks::ArgumentError,
|
|
85
|
+
"`:lock_index_grace_period` argument should be a non-negative Integer, " \
|
|
86
|
+
"got #{lock_index_grace_period.inspect}."
|
|
87
|
+
)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
idx_start_time = clock_gettime
|
|
91
|
+
idx_key_cnt = fully_reindex_locks(redis_client, scan_size, queue_ttl, lock_index_grace_period)
|
|
92
|
+
time_at = Time.now.to_f
|
|
93
|
+
idx_end_time = clock_gettime
|
|
94
|
+
idx_time = ((idx_end_time - idx_start_time) / 1_000.0).ceil(2)
|
|
95
|
+
|
|
96
|
+
log_sampled = RedisQueuedLocks::Logging.should_log?(
|
|
97
|
+
log_sampling_enabled,
|
|
98
|
+
log_sample_this,
|
|
99
|
+
log_sampling_percent,
|
|
100
|
+
log_sampler
|
|
101
|
+
)
|
|
102
|
+
instr_sampled = RedisQueuedLocks::Instrument.should_instrument?(
|
|
103
|
+
instr_sampling_enabled,
|
|
104
|
+
instr_sample_this,
|
|
105
|
+
instr_sampling_percent,
|
|
106
|
+
instr_sampler
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
run_non_critical do
|
|
110
|
+
logger.debug do
|
|
111
|
+
"[redis_queued_locks.reindex_locks] " \
|
|
112
|
+
"idx_key_cnt => #{idx_key_cnt} " \
|
|
113
|
+
"idx_time => #{idx_time} " \
|
|
114
|
+
"at => #{time_at}"
|
|
115
|
+
end
|
|
116
|
+
end if log_sampled
|
|
117
|
+
|
|
118
|
+
run_non_critical do
|
|
119
|
+
instrumenter.notify('redis_queued_locks.reindex_locks', {
|
|
120
|
+
idx_key_cnt: idx_key_cnt,
|
|
121
|
+
idx_time: idx_time,
|
|
122
|
+
at: time_at,
|
|
123
|
+
instrument: instrument
|
|
124
|
+
})
|
|
125
|
+
end if instr_sampled
|
|
126
|
+
|
|
127
|
+
{ ok: true, result: { idx_key_cnt: } }
|
|
128
|
+
end
|
|
129
|
+
# rubocop:enable Metrics/MethodLength
|
|
130
|
+
|
|
131
|
+
private
|
|
132
|
+
|
|
133
|
+
# Adds the lock keys without the lock index entry to the lock index (see `reindex_locks`).
|
|
134
|
+
#
|
|
135
|
+
# @param redis_client [RedisClient]
|
|
136
|
+
# @param scan_size [Integer]
|
|
137
|
+
# @param queue_ttl [Integer] TTL of the lock queues without TTL (in seconds).
|
|
138
|
+
# @param lock_index_grace_period [Integer]
|
|
139
|
+
# @return [Integer] The number of indexed keys.
|
|
140
|
+
#
|
|
141
|
+
# @api private
|
|
142
|
+
# @since 1.21.0
|
|
143
|
+
def fully_reindex_locks(redis_client, scan_size, queue_ttl, lock_index_grace_period)
|
|
31
144
|
# NOTE: `ceil` - queue ttl can be passed as a Float (in seconds), PEXPIRE requires Integer
|
|
32
145
|
queue_pttl = (queue_ttl * 1_000).ceil
|
|
33
146
|
idx_key_cnt = 0
|
|
@@ -61,11 +174,9 @@ module RedisQueuedLocks::Acquirer::ReindexLocks
|
|
|
61
174
|
end
|
|
62
175
|
end
|
|
63
176
|
|
|
64
|
-
|
|
177
|
+
idx_key_cnt
|
|
65
178
|
end
|
|
66
179
|
|
|
67
|
-
private
|
|
68
|
-
|
|
69
180
|
# Adds the given batch of lock keys to the lock index (two round trips: key TTLs, then
|
|
70
181
|
# the index entries).
|
|
71
182
|
#
|
|
@@ -137,4 +248,6 @@ module RedisQueuedLocks::Acquirer::ReindexLocks
|
|
|
137
248
|
1
|
|
138
249
|
end
|
|
139
250
|
end
|
|
251
|
+
# rubocop:enable Metrics/ClassLength
|
|
140
252
|
end
|
|
253
|
+
# rubocop:enable Metrics/ModuleLength
|
|
@@ -39,7 +39,7 @@ module RedisQueuedLocks::Acquirer::ReleaseAllLocks
|
|
|
39
39
|
# - works in tandem with <config['log_sampling_percent']> and <config['log_sampler']>;
|
|
40
40
|
# @param log_sampling_percent [Integer]
|
|
41
41
|
# - the percent of cases that should be logged;
|
|
42
|
-
# - take an effect when <config['
|
|
42
|
+
# - take an effect when <config['log_sampling_enabled']> is true;
|
|
43
43
|
# - works in tandem with <config['log_sampling_enabled']> and <config['log_sampler']> configs;
|
|
44
44
|
# @param log_sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
|
|
45
45
|
# - percent-based log sampler that decides should be RQL case logged or not;
|
|
@@ -60,7 +60,7 @@ module RedisQueuedLocks::Acquirer::ReleaseAllLocks
|
|
|
60
60
|
# - works in tandem with <config['instr_sampling_percent']> and <config['instr_sampler']>;
|
|
61
61
|
# @param instr_sampling_percent [Integer]
|
|
62
62
|
# - the percent of cases that should be instrumented;
|
|
63
|
-
# - take an effect when <config['
|
|
63
|
+
# - take an effect when <config['instr_sampling_enabled']> is true;
|
|
64
64
|
# - works in tandem with <config['instr_sampling_enabled']>
|
|
65
65
|
# and <config['instr_sampler']> configs;
|
|
66
66
|
# @param instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
|
|
@@ -81,7 +81,8 @@ module RedisQueuedLocks::Acquirer::ReleaseAllLocks
|
|
|
81
81
|
#
|
|
82
82
|
# @api private
|
|
83
83
|
# @since 1.0.0
|
|
84
|
-
# @version 1.
|
|
84
|
+
# @version 1.21.0
|
|
85
|
+
# rubocop:disable Metrics/MethodLength
|
|
85
86
|
def release_all_locks(
|
|
86
87
|
redis,
|
|
87
88
|
batch_size,
|
|
@@ -98,6 +99,15 @@ module RedisQueuedLocks::Acquirer::ReleaseAllLocks
|
|
|
98
99
|
instr_sampler,
|
|
99
100
|
instr_sample_this
|
|
100
101
|
)
|
|
102
|
+
# NOTE: (arguments) the same ranges as the config keys: zero/negative sizes fail SCAN/ZSCAN
|
|
103
|
+
# (`COUNT 0`) and the batching (`each_slice(0)`);
|
|
104
|
+
if !batch_size.is_a?(::Integer) || batch_size <= 0
|
|
105
|
+
raise(
|
|
106
|
+
RedisQueuedLocks::ArgumentError,
|
|
107
|
+
"`:batch_size` argument should be a positive Integer, got #{batch_size.inspect}."
|
|
108
|
+
)
|
|
109
|
+
end
|
|
110
|
+
|
|
101
111
|
rel_start_time = clock_gettime
|
|
102
112
|
# steep:ignore:start
|
|
103
113
|
fully_release_all_locks(redis, batch_size, lock_index_enabled) => { ok:, result: }
|
|
@@ -110,6 +120,12 @@ module RedisQueuedLocks::Acquirer::ReleaseAllLocks
|
|
|
110
120
|
rel_end_time = clock_gettime
|
|
111
121
|
rel_time = ((rel_end_time - rel_start_time) / 1_000.0).ceil(2)
|
|
112
122
|
|
|
123
|
+
log_sampled = RedisQueuedLocks::Logging.should_log?(
|
|
124
|
+
log_sampling_enabled,
|
|
125
|
+
log_sample_this,
|
|
126
|
+
log_sampling_percent,
|
|
127
|
+
log_sampler
|
|
128
|
+
)
|
|
113
129
|
instr_sampled = RedisQueuedLocks::Instrument.should_instrument?(
|
|
114
130
|
instr_sampling_enabled,
|
|
115
131
|
instr_sample_this,
|
|
@@ -117,11 +133,21 @@ module RedisQueuedLocks::Acquirer::ReleaseAllLocks
|
|
|
117
133
|
instr_sampler
|
|
118
134
|
)
|
|
119
135
|
|
|
136
|
+
run_non_critical do
|
|
137
|
+
logger.debug do
|
|
138
|
+
"[redis_queued_locks.explicit_all_locks_release] " \
|
|
139
|
+
"at => #{time_at} " \
|
|
140
|
+
"rel_time => #{rel_time} " \
|
|
141
|
+
"rel_key_cnt => #{result[:rel_key_cnt]}"
|
|
142
|
+
end
|
|
143
|
+
end if log_sampled
|
|
144
|
+
|
|
120
145
|
run_non_critical do
|
|
121
146
|
instrumenter.notify('redis_queued_locks.explicit_all_locks_release', {
|
|
122
147
|
at: time_at,
|
|
123
148
|
rel_time: rel_time,
|
|
124
|
-
rel_key_cnt: result[:rel_key_cnt]
|
|
149
|
+
rel_key_cnt: result[:rel_key_cnt],
|
|
150
|
+
instrument: instrument
|
|
125
151
|
})
|
|
126
152
|
end if instr_sampled
|
|
127
153
|
|
|
@@ -130,6 +156,7 @@ module RedisQueuedLocks::Acquirer::ReleaseAllLocks
|
|
|
130
156
|
result: { rel_key_cnt: result[:rel_key_cnt], rel_time: rel_time }
|
|
131
157
|
}
|
|
132
158
|
end
|
|
159
|
+
# rubocop:enable Metrics/MethodLength
|
|
133
160
|
|
|
134
161
|
private
|
|
135
162
|
|
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
# @api private
|
|
4
4
|
# @since 1.0.0
|
|
5
|
+
# @version 1.21.0
|
|
6
|
+
# rubocop:disable Metrics/ModuleLength
|
|
5
7
|
module RedisQueuedLocks::Acquirer::ReleaseLock
|
|
6
8
|
# @since 1.0.0
|
|
7
9
|
extend RedisQueuedLocks::Utilities
|
|
8
10
|
|
|
11
|
+
# rubocop:disable Metrics/ClassLength
|
|
9
12
|
class << self
|
|
10
13
|
# Release the concrete lock:
|
|
11
14
|
# - 1. clear lock queue: al; related processes released
|
|
@@ -22,18 +25,21 @@ module RedisQueuedLocks::Acquirer::ReleaseLock
|
|
|
22
25
|
# The lock name that should be released.
|
|
23
26
|
# @param lock_index_enabled [Boolean]
|
|
24
27
|
# Drop the lock name from the lock index (the enabled lock index).
|
|
25
|
-
# @param instrumenter [#notify]
|
|
26
|
-
# See RedisQueuedLocks::Instrument::ActiveSupport for example.
|
|
27
28
|
# @param logger [::Logger,#debug]
|
|
28
29
|
# - Logger object used from `configuration` layer (see config['logger']);
|
|
29
30
|
# - See RedisQueuedLocks::Logging::VoidLogger for example;
|
|
31
|
+
# @param instrumenter [#notify]
|
|
32
|
+
# See RedisQueuedLocks::Instrument::ActiveSupport for example.
|
|
33
|
+
# @param instrument [NilClass,Any]
|
|
34
|
+
# - Custom instrumentation data wich will be passed to the instrumenter's payload
|
|
35
|
+
# with :instrument key;
|
|
30
36
|
# @param log_sampling_enabled [Boolean]
|
|
31
37
|
# - enables <log sampling>: only the configured percent of RQL cases will be logged;
|
|
32
38
|
# - disabled by default;
|
|
33
39
|
# - works in tandem with <config['log_sampling_percent']> and <config['log_sampler']>;
|
|
34
40
|
# @param log_sampling_percent [Integer]
|
|
35
41
|
# - the percent of cases that should be logged;
|
|
36
|
-
# - take an effect when <config['
|
|
42
|
+
# - take an effect when <config['log_sampling_enabled']> is true;
|
|
37
43
|
# - works in tandem with <config['log_sampling_enabled']> and <config['log_sampler']> configs;
|
|
38
44
|
# @param log_sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
|
|
39
45
|
# - percent-based log sampler that decides should be RQL case logged or not;
|
|
@@ -54,7 +60,7 @@ module RedisQueuedLocks::Acquirer::ReleaseLock
|
|
|
54
60
|
# - works in tandem with <config['instr_sampling_percent']> and <config['instr_sampler']>;
|
|
55
61
|
# @param instr_sampling_percent [Integer]
|
|
56
62
|
# - the percent of cases that should be instrumented;
|
|
57
|
-
# - take an effect when <config['
|
|
63
|
+
# - take an effect when <config['instr_sampling_enabled']> is true;
|
|
58
64
|
# - works in tandem with <config['instr_sampling_enabled']>
|
|
59
65
|
# and <config['instr_sampler']> configs;
|
|
60
66
|
# @param instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
|
|
@@ -75,14 +81,15 @@ module RedisQueuedLocks::Acquirer::ReleaseLock
|
|
|
75
81
|
#
|
|
76
82
|
# @api private
|
|
77
83
|
# @since 1.0.0
|
|
78
|
-
# @version 1.
|
|
84
|
+
# @version 1.21.0
|
|
79
85
|
# rubocop:disable Metrics/MethodLength
|
|
80
86
|
def release_lock(
|
|
81
87
|
redis,
|
|
82
88
|
lock_name,
|
|
83
89
|
lock_index_enabled,
|
|
84
|
-
instrumenter,
|
|
85
90
|
logger,
|
|
91
|
+
instrumenter,
|
|
92
|
+
instrument,
|
|
86
93
|
log_sampling_enabled,
|
|
87
94
|
log_sampling_percent,
|
|
88
95
|
log_sampler,
|
|
@@ -112,6 +119,12 @@ module RedisQueuedLocks::Acquirer::ReleaseLock
|
|
|
112
119
|
rel_end_time = clock_gettime
|
|
113
120
|
rel_time = ((rel_end_time - rel_start_time) / 1_000.0).ceil(2)
|
|
114
121
|
|
|
122
|
+
log_sampled = RedisQueuedLocks::Logging.should_log?(
|
|
123
|
+
log_sampling_enabled,
|
|
124
|
+
log_sample_this,
|
|
125
|
+
log_sampling_percent,
|
|
126
|
+
log_sampler
|
|
127
|
+
)
|
|
115
128
|
instr_sampled = RedisQueuedLocks::Instrument.should_instrument?(
|
|
116
129
|
instr_sampling_enabled,
|
|
117
130
|
instr_sample_this,
|
|
@@ -119,12 +132,23 @@ module RedisQueuedLocks::Acquirer::ReleaseLock
|
|
|
119
132
|
instr_sampler
|
|
120
133
|
)
|
|
121
134
|
|
|
135
|
+
run_non_critical do
|
|
136
|
+
logger.debug do
|
|
137
|
+
"[redis_queued_locks.explicit_lock_release] " \
|
|
138
|
+
"lock_key => '#{lock_key}' " \
|
|
139
|
+
"lock_key_queue => '#{lock_key_queue}' " \
|
|
140
|
+
"rel_time => #{rel_time} " \
|
|
141
|
+
"at => #{time_at}"
|
|
142
|
+
end
|
|
143
|
+
end if log_sampled
|
|
144
|
+
|
|
122
145
|
run_non_critical do
|
|
123
146
|
instrumenter.notify('redis_queued_locks.explicit_lock_release', {
|
|
124
147
|
lock_key: lock_key,
|
|
125
148
|
lock_key_queue: lock_key_queue,
|
|
126
149
|
rel_time: rel_time,
|
|
127
|
-
at: time_at
|
|
150
|
+
at: time_at,
|
|
151
|
+
instrument: instrument
|
|
128
152
|
})
|
|
129
153
|
end if instr_sampled
|
|
130
154
|
|
|
@@ -229,4 +253,6 @@ module RedisQueuedLocks::Acquirer::ReleaseLock
|
|
|
229
253
|
end
|
|
230
254
|
# rubocop:enable Metrics/MethodLength
|
|
231
255
|
end
|
|
256
|
+
# rubocop:enable Metrics/ClassLength
|
|
232
257
|
end
|
|
258
|
+
# rubocop:enable Metrics/ModuleLength
|
|
@@ -44,7 +44,7 @@ module RedisQueuedLocks::Acquirer::ReleaseLocksOf
|
|
|
44
44
|
# - works in tandem with <config['log_sampling_percent']> and <config['log_sampler']>;
|
|
45
45
|
# @param log_sampling_percent [Integer]
|
|
46
46
|
# - the percent of cases that should be logged;
|
|
47
|
-
# - take an effect when <config['
|
|
47
|
+
# - take an effect when <config['log_sampling_enabled']> is true;
|
|
48
48
|
# - works in tandem with <config['log_sampling_enabled']> and <config['log_sampler']> configs;
|
|
49
49
|
# @param log_sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
|
|
50
50
|
# - percent-based log sampler that decides should be RQL case logged or not;
|
|
@@ -65,7 +65,7 @@ module RedisQueuedLocks::Acquirer::ReleaseLocksOf
|
|
|
65
65
|
# - works in tandem with <config['instr_sampling_percent']> and <config['instr_sampler']>;
|
|
66
66
|
# @param instr_sampling_percent [Integer]
|
|
67
67
|
# - the percent of cases that should be instrumented;
|
|
68
|
-
# - take an effect when <config['
|
|
68
|
+
# - take an effect when <config['instr_sampling_enabled']> is true;
|
|
69
69
|
# - works in tandem with <config['instr_sampling_enabled']>
|
|
70
70
|
# and <config['instr_sampler']> configs;
|
|
71
71
|
# @param instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
|
|
@@ -93,7 +93,7 @@ module RedisQueuedLocks::Acquirer::ReleaseLocksOf
|
|
|
93
93
|
#
|
|
94
94
|
# @api private
|
|
95
95
|
# @since 1.14.0
|
|
96
|
-
# @version 1.
|
|
96
|
+
# @version 1.21.0
|
|
97
97
|
# rubocop:disable Metrics/MethodLength
|
|
98
98
|
def release_locks_of(
|
|
99
99
|
refused_host_id,
|
|
@@ -114,6 +114,22 @@ module RedisQueuedLocks::Acquirer::ReleaseLocksOf
|
|
|
114
114
|
instr_sampler,
|
|
115
115
|
instr_sample_this
|
|
116
116
|
)
|
|
117
|
+
# NOTE: (arguments) the same ranges as the config keys: zero/negative sizes fail SCAN/ZSCAN
|
|
118
|
+
# (`COUNT 0`) and the batching (`each_slice(0)`);
|
|
119
|
+
if !lock_scan_size.is_a?(::Integer) || lock_scan_size <= 0
|
|
120
|
+
raise(
|
|
121
|
+
RedisQueuedLocks::ArgumentError,
|
|
122
|
+
"`:lock_scan_size` argument should be a positive Integer, got #{lock_scan_size.inspect}."
|
|
123
|
+
)
|
|
124
|
+
end
|
|
125
|
+
if !queue_scan_size.is_a?(::Integer) || queue_scan_size <= 0
|
|
126
|
+
raise(
|
|
127
|
+
RedisQueuedLocks::ArgumentError,
|
|
128
|
+
"`:queue_scan_size` argument should be a positive Integer, " \
|
|
129
|
+
"got #{queue_scan_size.inspect}."
|
|
130
|
+
)
|
|
131
|
+
end
|
|
132
|
+
|
|
117
133
|
rel_start_time = clock_gettime
|
|
118
134
|
|
|
119
135
|
# steep:ignore:start
|
|
@@ -134,6 +150,12 @@ module RedisQueuedLocks::Acquirer::ReleaseLocksOf
|
|
|
134
150
|
rel_end_time = clock_gettime
|
|
135
151
|
rel_time = ((rel_end_time - rel_start_time) / 1_000.0).ceil(2)
|
|
136
152
|
|
|
153
|
+
log_sampled = RedisQueuedLocks::Logging.should_log?(
|
|
154
|
+
log_sampling_enabled,
|
|
155
|
+
log_sample_this,
|
|
156
|
+
log_sampling_percent,
|
|
157
|
+
log_sampler
|
|
158
|
+
)
|
|
137
159
|
instr_sampled = RedisQueuedLocks::Instrument.should_instrument?(
|
|
138
160
|
instr_sampling_enabled,
|
|
139
161
|
instr_sample_this,
|
|
@@ -141,6 +163,18 @@ module RedisQueuedLocks::Acquirer::ReleaseLocksOf
|
|
|
141
163
|
instr_sampler
|
|
142
164
|
)
|
|
143
165
|
|
|
166
|
+
run_non_critical do
|
|
167
|
+
logger.debug do
|
|
168
|
+
"[redis_queued_locks.release_locks_of] " \
|
|
169
|
+
"at => #{time_at} " \
|
|
170
|
+
"hst_id => '#{refused_host_id}' " \
|
|
171
|
+
"acq_id => '#{refused_acquirer_id}' " \
|
|
172
|
+
"rel_time => #{rel_time} " \
|
|
173
|
+
"rel_key_cnt => #{result[:rel_key_cnt]} " \
|
|
174
|
+
"tch_queue_cnt => #{result[:tch_queue_cnt]}"
|
|
175
|
+
end
|
|
176
|
+
end if log_sampled
|
|
177
|
+
|
|
144
178
|
run_non_critical do
|
|
145
179
|
instrumenter.notify('redis_queued_locks.release_locks_of', {
|
|
146
180
|
at: time_at,
|
|
@@ -148,7 +182,8 @@ module RedisQueuedLocks::Acquirer::ReleaseLocksOf
|
|
|
148
182
|
acq_id: refused_acquirer_id,
|
|
149
183
|
rel_time: rel_time,
|
|
150
184
|
rel_key_cnt: result[:rel_key_cnt],
|
|
151
|
-
tch_queue_cnt: result[:tch_queue_cnt]
|
|
185
|
+
tch_queue_cnt: result[:tch_queue_cnt],
|
|
186
|
+
instrument: instrument
|
|
152
187
|
})
|
|
153
188
|
end if instr_sampled
|
|
154
189
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# @api private
|
|
4
4
|
# @since 1.18.0
|
|
5
|
+
# @version 1.21.0
|
|
5
6
|
module RedisQueuedLocks::Acquirer::ReleaseReadLock
|
|
6
7
|
# @since 1.18.0
|
|
7
8
|
extend RedisQueuedLocks::Utilities
|
|
@@ -17,11 +18,11 @@ module RedisQueuedLocks::Acquirer::ReleaseReadLock
|
|
|
17
18
|
# The lock name whose read lock should be released.
|
|
18
19
|
# @param acquirer_id [String]
|
|
19
20
|
# The read lock acquirer.
|
|
20
|
-
# @param instrumenter [#notify]
|
|
21
|
-
# See RedisQueuedLocks::Instrument::ActiveSupport for example.
|
|
22
21
|
# @param logger [::Logger,#debug]
|
|
23
22
|
# - Logger object used from `configuration` layer (see config['logger']);
|
|
24
23
|
# - See RedisQueuedLocks::Logging::VoidLogger for example;
|
|
24
|
+
# @param instrumenter [#notify]
|
|
25
|
+
# See RedisQueuedLocks::Instrument::ActiveSupport for example.
|
|
25
26
|
# @param instrument [NilClass,Any]
|
|
26
27
|
# - Custom instrumentation data wich will be passed to the instrumenter's payload
|
|
27
28
|
# with :instrument key;
|
|
@@ -52,13 +53,14 @@ module RedisQueuedLocks::Acquirer::ReleaseReadLock
|
|
|
52
53
|
#
|
|
53
54
|
# @api private
|
|
54
55
|
# @since 1.18.0
|
|
56
|
+
# @version 1.21.0
|
|
55
57
|
# rubocop:disable Metrics/MethodLength
|
|
56
58
|
def release_read_lock(
|
|
57
59
|
redis,
|
|
58
60
|
lock_name,
|
|
59
61
|
acquirer_id,
|
|
60
|
-
instrumenter,
|
|
61
62
|
logger,
|
|
63
|
+
instrumenter,
|
|
62
64
|
instrument,
|
|
63
65
|
log_sampling_enabled,
|
|
64
66
|
log_sampling_percent,
|
|
@@ -87,6 +89,12 @@ module RedisQueuedLocks::Acquirer::ReleaseReadLock
|
|
|
87
89
|
rel_end_time = clock_gettime
|
|
88
90
|
rel_time = ((rel_end_time - rel_start_time) / 1_000.0).ceil(2)
|
|
89
91
|
|
|
92
|
+
log_sampled = RedisQueuedLocks::Logging.should_log?(
|
|
93
|
+
log_sampling_enabled,
|
|
94
|
+
log_sample_this,
|
|
95
|
+
log_sampling_percent,
|
|
96
|
+
log_sampler
|
|
97
|
+
)
|
|
90
98
|
instr_sampled = RedisQueuedLocks::Instrument.should_instrument?(
|
|
91
99
|
instr_sampling_enabled,
|
|
92
100
|
instr_sample_this,
|
|
@@ -94,6 +102,17 @@ module RedisQueuedLocks::Acquirer::ReleaseReadLock
|
|
|
94
102
|
instr_sampler
|
|
95
103
|
)
|
|
96
104
|
|
|
105
|
+
run_non_critical do
|
|
106
|
+
logger.debug do
|
|
107
|
+
"[redis_queued_locks.explicit_read_lock_release] " \
|
|
108
|
+
"lock_key => '#{lock_key}' " \
|
|
109
|
+
"acq_id => '#{acquirer_id}' " \
|
|
110
|
+
"lock_res => '#{result[:lock]}' " \
|
|
111
|
+
"rel_time => #{rel_time} " \
|
|
112
|
+
"at => #{time_at}"
|
|
113
|
+
end
|
|
114
|
+
end if log_sampled
|
|
115
|
+
|
|
97
116
|
run_non_critical do
|
|
98
117
|
instrumenter.notify('redis_queued_locks.explicit_read_lock_release', {
|
|
99
118
|
lock_key: lock_key,
|