redis_queued_locks 0.0.0 → 0.0.1
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 +5 -0
- data/README.md +15 -0
- data/lib/redis_queued_locks/acquier/release.rb +10 -2
- data/lib/redis_queued_locks/acquier/try.rb +3 -3
- data/lib/redis_queued_locks/acquier.rb +58 -11
- data/lib/redis_queued_locks/client.rb +52 -12
- data/lib/redis_queued_locks/debugger.rb +1 -1
- data/lib/redis_queued_locks/instrument/active_support.rb +17 -0
- data/lib/redis_queued_locks/instrument/void_notifier.rb +15 -0
- data/lib/redis_queued_locks/instrument.rb +48 -0
- data/lib/redis_queued_locks/version.rb +2 -2
- data/lib/redis_queued_locks.rb +1 -1
- data/redis_queued_locks.gemspec +1 -1
- metadata +7 -5
- data/lib/redis_queued_locks/instrumentation.rb +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f78a90d3830a3797bfd973b8ce48a879ba8400c3daec8827c0c14c25c650bb3
|
4
|
+
data.tar.gz: a8e09fae141ff16d142234a4200c86f05abea787fb627e23b4187dd11fa06086
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fe28a66ec0d028453a0e43f2e140b907a100a70b8a547af8067f45f60392339dd9d0540ef9b8638d0bc9588dd0152f4e21ac488d031170cb872679c7ed4bc34a
|
7
|
+
data.tar.gz: 6608fc1f6a9b2b2000254ba0b4a39d5d16c50f9265bcf58c7b138066e08c29c32d31047e3419db09aa0bfda88c09af10111254c3bf2ba35df775248f2d732d63
|
data/.rubocop.yml
CHANGED
@@ -5,7 +5,7 @@ inherit_gem:
|
|
5
5
|
- lib/rubocop.rspec.yml
|
6
6
|
|
7
7
|
AllCops:
|
8
|
-
TargetRubyVersion: 3.
|
8
|
+
TargetRubyVersion: 3.1
|
9
9
|
NewCops: enable
|
10
10
|
Include:
|
11
11
|
- lib/**/*.rb
|
@@ -33,3 +33,6 @@ Metrics/AbcSize:
|
|
33
33
|
|
34
34
|
Metrics/CyclomaticComplexity:
|
35
35
|
Enabled: false
|
36
|
+
|
37
|
+
Metrics/PerceivedComplexity:
|
38
|
+
Enabled: false
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.
|
1
|
+
3.1.2
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,3 +1,18 @@
|
|
1
1
|
# RedisQueuedLocks
|
2
2
|
|
3
3
|
Distributed lock implementation with "lock acquisition queue" capabilities based on the Redis Database.
|
4
|
+
|
5
|
+
## Instrumentation events
|
6
|
+
|
7
|
+
- `"redis_queued_locks.lock_obtained"`
|
8
|
+
- the moment when the lock was obtained;
|
9
|
+
- payload:
|
10
|
+
- `ttl` - `integer`/`milliseconds` - lock ttl;
|
11
|
+
- `acq_id` - `string` - lock acquier identifier;
|
12
|
+
- `lock_key` - `string` - lock name ;
|
13
|
+
- `ts` - `integer`/`epoch` - the time when the lock was obtaiend;
|
14
|
+
- `acq_time` - `float`/`milliseconds` - time spent on lock acquiring;
|
15
|
+
|
16
|
+
## Todo
|
17
|
+
|
18
|
+
- CI (github actions);
|
@@ -29,7 +29,11 @@ module RedisQueuedLocks::Acquier::Release
|
|
29
29
|
# @since 0.1.0
|
30
30
|
def fully_release_all_locks(redis, batch_size)
|
31
31
|
# Step A: release all queus and their related locks
|
32
|
-
redis.scan(
|
32
|
+
redis.scan(
|
33
|
+
'MATCH',
|
34
|
+
RedisQueuedLocks::Resource::LOCK_QUEUE_PATTERN,
|
35
|
+
count: batch_size
|
36
|
+
) do |lock_queue|
|
33
37
|
redis.pipelined do |pipeline|
|
34
38
|
pipeline.call('ZREMRANGEBYSCORE', lock_queue, '-inf', '+inf')
|
35
39
|
pipeline.call('EXPIRE', RedisQueuedLocks::Resource.lock_key_from_queue(lock_queue))
|
@@ -38,7 +42,11 @@ module RedisQueuedLocks::Acquier::Release
|
|
38
42
|
|
39
43
|
# Step B: release all locks
|
40
44
|
redis.pipelined do |pipeline|
|
41
|
-
redis.scan(
|
45
|
+
redis.scan(
|
46
|
+
'MATCH',
|
47
|
+
RedisQueuedLocks::Resource::LOCK_PATTERN,
|
48
|
+
count: batch_size
|
49
|
+
) do |lock_key|
|
42
50
|
pipeline.call('EXPIRE', lock_key, '0')
|
43
51
|
end
|
44
52
|
end
|
@@ -14,7 +14,7 @@ module RedisQueuedLocks::Acquier::Try
|
|
14
14
|
#
|
15
15
|
# @api private
|
16
16
|
# @since 0.1.0
|
17
|
-
# rubocop:disable Metrics/MethodLength
|
17
|
+
# rubocop:disable Metrics/MethodLength
|
18
18
|
def try_to_lock(redis, lock_key, lock_key_queue, acquier_id, acquier_position, ttl, queue_ttl)
|
19
19
|
# Step X: intermediate invocation results
|
20
20
|
inter_result = nil
|
@@ -111,13 +111,13 @@ module RedisQueuedLocks::Acquier::Try
|
|
111
111
|
when result == nil || (result.is_a?(::Array) && result.empty?)
|
112
112
|
# Step 7.b: lock is already acquired durign the acquire race => failed to acquire
|
113
113
|
{ ok: false, result: :lock_is_acquired_during_acquire_race }
|
114
|
-
when result.is_a?(::Array) && result.size == 3 # NOTE: 3 is a count of lock commands
|
114
|
+
when result.is_a?(::Array) && result.size == 3 # NOTE: 3 is a count of redis lock commands
|
115
115
|
# TODO:
|
116
116
|
# => (!) analyze the command result and do actions with the depending on it;
|
117
117
|
# => (*) at this moment we accept that all comamnds are completed successfully;
|
118
118
|
# => (!) need to analyze:
|
119
119
|
# 1. zpopmin should return our process (array with <acq_id> and <score>)
|
120
|
-
# 2. hset should return 2 (lock key is added to the redis
|
120
|
+
# 2. hset should return 2 (lock key is added to the redis as a hashmap with 2 fields)
|
121
121
|
# 3. pexpire should return 1 (expiration time is successfully applied)
|
122
122
|
|
123
123
|
# Step 7.c: locked! :) let's go! => successfully acquired
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
# @api private
|
4
4
|
# @since 0.1.0
|
5
|
+
# rubocop:disable Metrics/ModuleLength
|
5
6
|
module RedisQueuedLocks::Acquier
|
6
7
|
require_relative 'acquier/try'
|
7
8
|
require_relative 'acquier/delay'
|
@@ -26,6 +27,7 @@ module RedisQueuedLocks::Acquier
|
|
26
27
|
# @since 0.1.0
|
27
28
|
REDIS_EXPIRATION_DEVIATION = 2 # NOTE: milliseconds
|
28
29
|
|
30
|
+
# rubocop:disable Metrics/ClassLength
|
29
31
|
class << self
|
30
32
|
# @param redis [RedisClient]
|
31
33
|
# Redis connection client.
|
@@ -47,6 +49,10 @@ module RedisQueuedLocks::Acquier
|
|
47
49
|
# A time-interval between the each retry (in milliseconds).
|
48
50
|
# @option retry_jitter [Integer]
|
49
51
|
# Time-shift range for retry-delay (in milliseconds).
|
52
|
+
# @option raise_errors [Boolean]
|
53
|
+
# Raise errors on exceptional cases.
|
54
|
+
# @option instrumenter [#notify]
|
55
|
+
# See RedisQueuedLocks::Instrument::ActiveSupport for example.
|
50
56
|
# @param [Block]
|
51
57
|
# A block of code that should be executed after the successfully acquired lock.
|
52
58
|
# @return [Hash<Symbol,Any>]
|
@@ -66,6 +72,8 @@ module RedisQueuedLocks::Acquier
|
|
66
72
|
retry_count:,
|
67
73
|
retry_delay:,
|
68
74
|
retry_jitter:,
|
75
|
+
raise_errors:,
|
76
|
+
instrumenter:,
|
69
77
|
&block
|
70
78
|
)
|
71
79
|
# Step 1: prepare lock requirements (generate lock name, calc lock ttl, etc).
|
@@ -76,11 +84,20 @@ module RedisQueuedLocks::Acquier
|
|
76
84
|
acquier_position = RedisQueuedLocks::Resource.calc_initial_acquier_position
|
77
85
|
|
78
86
|
# Step X: intermediate result observer
|
79
|
-
acq_process = {
|
87
|
+
acq_process = {
|
88
|
+
lock_info: {},
|
89
|
+
should_try: true,
|
90
|
+
tries: 0,
|
91
|
+
acquired: false,
|
92
|
+
result: nil,
|
93
|
+
acq_time: nil # NOTE: in milliseconds
|
94
|
+
}
|
80
95
|
acq_dequeue = -> { dequeue_from_lock_queue(redis, lock_key_queue, acquier_id) }
|
81
96
|
|
82
97
|
# Step 2: try to lock with timeout
|
83
|
-
with_timeout(timeout, lock_key, on_timeout: acq_dequeue) do
|
98
|
+
with_timeout(timeout, lock_key, raise_errors, on_timeout: acq_dequeue) do
|
99
|
+
acq_start_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
100
|
+
|
84
101
|
# Step 2.1: caclically try to obtain the lock
|
85
102
|
while acq_process[:should_try]
|
86
103
|
try_to_lock(
|
@@ -93,15 +110,33 @@ module RedisQueuedLocks::Acquier
|
|
93
110
|
queue_ttl
|
94
111
|
) => { ok:, result: }
|
95
112
|
|
113
|
+
acq_end_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
114
|
+
acq_time = ((acq_end_time - acq_start_time) * 1_000).ceil
|
115
|
+
|
96
116
|
# Step X: save the intermediate results to the result observer
|
97
117
|
acq_process[:result] = result
|
98
118
|
|
99
119
|
# Step 2.1: analyze an acquirement attempt
|
100
120
|
if ok
|
121
|
+
# INSTRUMENT: lock obtained
|
122
|
+
instrumenter.notify('redis_queued_locks.lock_obtained', {
|
123
|
+
lock_key: result[:lock_key],
|
124
|
+
ttl: result[:ttl],
|
125
|
+
acq_id: result[:acq_id],
|
126
|
+
ts: result[:ts],
|
127
|
+
acq_time: acq_time
|
128
|
+
})
|
129
|
+
|
101
130
|
# Step 2.1.a: successfully acquired => build the result
|
102
|
-
acq_process[:lock_info] =
|
131
|
+
acq_process[:lock_info] = {
|
132
|
+
lock_key: result[:lock_key],
|
133
|
+
acq_id: result[:acq_id],
|
134
|
+
ts: result[:ts],
|
135
|
+
ttl: result[:ttl]
|
136
|
+
}
|
103
137
|
acq_process[:acquired] = true
|
104
138
|
acq_process[:should_try] = false
|
139
|
+
acq_process[:acq_time] = acq_time
|
105
140
|
else
|
106
141
|
# Step 2.1.b: failed acquirement => retry
|
107
142
|
acq_process[:tries] += 1
|
@@ -125,7 +160,7 @@ module RedisQueuedLocks::Acquier
|
|
125
160
|
if acq_process[:acquired]
|
126
161
|
# Step 3.a: acquired successfully => run logic or return the result of acquirement
|
127
162
|
if block_given?
|
128
|
-
yield_with_expire(redis, lock_key, &block)
|
163
|
+
yield_with_expire(redis, lock_key, &block) # INSTRUMENT: lock release
|
129
164
|
else
|
130
165
|
{ ok: true, result: acq_process[:lock_info] }
|
131
166
|
end
|
@@ -154,6 +189,7 @@ module RedisQueuedLocks::Acquier
|
|
154
189
|
lock_key = RedisQueuedLocks::Resource.prepare_lock_key(lock_name)
|
155
190
|
lock_key_queue = RedisQueuedLocks::Resource.prepare_lock_queue(lock_name)
|
156
191
|
|
192
|
+
# INSTRUMENT: lock release
|
157
193
|
result = fully_release_lock(redis, lock_key, lock_key_queue)
|
158
194
|
{ ok: true, result: result }
|
159
195
|
end
|
@@ -169,26 +205,37 @@ module RedisQueuedLocks::Acquier
|
|
169
205
|
# @api private
|
170
206
|
# @since 0.1.0
|
171
207
|
def release_all_locks!(redis, batch_size)
|
208
|
+
# INSTRUMENT: all locks released
|
172
209
|
result = fully_release_all_locks(redis, batch_size)
|
173
210
|
{ ok: true, result: result }
|
174
211
|
end
|
175
212
|
|
176
213
|
private
|
177
214
|
|
178
|
-
# @param timeout [Integer]
|
179
|
-
#
|
180
|
-
# @
|
215
|
+
# @param timeout [NilClass,Integer]
|
216
|
+
# Time period after which the logic will fail with timeout error.
|
217
|
+
# @param lock_key [String]
|
218
|
+
# Lock name.
|
219
|
+
# @param raise_errors [Boolean]
|
220
|
+
# Raise erros on exceptional cases.
|
221
|
+
# @option on_timeout [Proc,NilClass]
|
222
|
+
# Callback invoked on Timeout::Error.
|
181
223
|
# @return [Any]
|
182
224
|
#
|
183
225
|
# @api private
|
184
226
|
# @since 0.1.0
|
185
|
-
def with_timeout(timeout, lock_key, on_timeout: nil, &block)
|
227
|
+
def with_timeout(timeout, lock_key, raise_errors, on_timeout: nil, &block)
|
186
228
|
::Timeout.timeout(timeout, &block)
|
187
229
|
rescue ::Timeout::Error
|
188
230
|
on_timeout.call unless on_timeout == nil
|
189
|
-
|
190
|
-
|
191
|
-
|
231
|
+
|
232
|
+
if raise_errors
|
233
|
+
raise(RedisQueuedLocks::LockAcquiermentTimeoutError, <<~ERROR_MESSAGE.strip)
|
234
|
+
Failed to acquire the lock "#{lock_key}" for the given timeout (#{timeout} seconds).
|
235
|
+
ERROR_MESSAGE
|
236
|
+
end
|
192
237
|
end
|
193
238
|
end
|
239
|
+
# rubocop:enable Metrics/ClassLength
|
194
240
|
end
|
241
|
+
# rubocop:enable Metrics/ModuleLength
|
@@ -10,23 +10,25 @@ class RedisQueuedLocks::Client
|
|
10
10
|
setting :retry_count, 3
|
11
11
|
setting :retry_delay, 200 # NOTE: milliseconds
|
12
12
|
setting :retry_jitter, 50 # NOTE: milliseconds
|
13
|
-
setting :
|
13
|
+
setting :default_timeout, 10 # NOTE: seconds
|
14
14
|
setting :exp_precision, 1 # NOTE: milliseconds
|
15
15
|
setting :default_lock_ttl, 10_000 # NOTE: milliseconds
|
16
16
|
setting :default_queue_ttl, 5 # NOTE: seconds
|
17
17
|
setting :lock_release_batch_size, 100
|
18
|
+
setting :instrumenter, RedisQueuedLocks::Instrument::VoidNotifier
|
18
19
|
|
19
20
|
# TODO: setting :logger, Logger.new(IO::NULL)
|
20
21
|
# TODO: setting :debug, true/false
|
21
22
|
|
22
|
-
validate
|
23
|
-
validate
|
24
|
-
validate
|
25
|
-
validate
|
26
|
-
validate
|
27
|
-
validate
|
28
|
-
validate
|
29
|
-
validate
|
23
|
+
validate('retry_count', :integer)
|
24
|
+
validate('retry_delay', :integer)
|
25
|
+
validate('retry_jitter', :integer)
|
26
|
+
validate('default_timeout', :integer)
|
27
|
+
validate('exp_precision', :integer)
|
28
|
+
validate('default_lock_tt', :integer)
|
29
|
+
validate('default_queue_ttl', :integer)
|
30
|
+
validate('lock_release_batch_size', :integer)
|
31
|
+
validate('instrumenter') { |instr| RedisQueuedLocks::Instrument.valid_interface?(instr) }
|
30
32
|
end
|
31
33
|
|
32
34
|
# @return [RedisClient]
|
@@ -67,6 +69,10 @@ class RedisQueuedLocks::Client
|
|
67
69
|
# A time-interval between the each retry (in milliseconds).
|
68
70
|
# @option retry_jitter [Integer]
|
69
71
|
# Time-shift range for retry-delay (in milliseconds).
|
72
|
+
# @option instrumenter [#notify]
|
73
|
+
# See RedisQueuedLocks::Instrument::ActiveSupport for example.
|
74
|
+
# @option raise_errors [Boolean]
|
75
|
+
# Raise errors on library-related limits such as timeout or failed lock obtain.
|
70
76
|
# @param [Block]
|
71
77
|
# A block of code that should be executed after the successfully acquired lock.
|
72
78
|
# @return [Hash<Symbol,Any>]
|
@@ -80,10 +86,11 @@ class RedisQueuedLocks::Client
|
|
80
86
|
thread_id: RedisQueuedLocks::Resource.get_thread_id,
|
81
87
|
ttl: config[:default_lock_ttl],
|
82
88
|
queue_ttl: config[:default_queue_ttl],
|
83
|
-
timeout: config[:
|
89
|
+
timeout: config[:default_timeout],
|
84
90
|
retry_count: config[:retry_count],
|
85
91
|
retry_delay: config[:retry_delay],
|
86
92
|
retry_jitter: config[:retry_jitter],
|
93
|
+
raise_errors: false,
|
87
94
|
&block
|
88
95
|
)
|
89
96
|
RedisQueuedLocks::Acquier.acquire_lock!(
|
@@ -97,12 +104,45 @@ class RedisQueuedLocks::Client
|
|
97
104
|
retry_count:,
|
98
105
|
retry_delay:,
|
99
106
|
retry_jitter:,
|
107
|
+
raise_errors:,
|
108
|
+
instrumenter: config[:instrumenter],
|
109
|
+
&block
|
110
|
+
)
|
111
|
+
end
|
112
|
+
|
113
|
+
# @note See #lock method signature.
|
114
|
+
#
|
115
|
+
# @api public
|
116
|
+
# @since 0.1.0
|
117
|
+
def lock!(
|
118
|
+
lock_name,
|
119
|
+
process_id: RedisQueuedLocks::Resource.get_process_id,
|
120
|
+
thread_id: RedisQueuedLocks::Resource.get_thread_id,
|
121
|
+
ttl: config[:default_lock_ttl],
|
122
|
+
queue_ttl: config[:default_queue_ttl],
|
123
|
+
timeout: config[:default_timeout],
|
124
|
+
retry_count: config[:retry_count],
|
125
|
+
retry_delay: config[:retry_delay],
|
126
|
+
retry_jitter: config[:retry_jitter],
|
127
|
+
&block
|
128
|
+
)
|
129
|
+
lock(
|
130
|
+
lock_name,
|
131
|
+
process_id:,
|
132
|
+
thread_id:,
|
133
|
+
ttl:,
|
134
|
+
queue_ttl:,
|
135
|
+
timeout:,
|
136
|
+
retry_count:,
|
137
|
+
retry_delay:,
|
138
|
+
retry_jitter:,
|
139
|
+
raise_errors: true,
|
100
140
|
&block
|
101
141
|
)
|
102
142
|
end
|
103
143
|
|
104
144
|
# @param lock_name [String] The lock name that should be released.
|
105
|
-
# @return [
|
145
|
+
# @return [Hash<Symbol,Any>] Format: { ok: true/false, result: Symbol/Hash }.
|
106
146
|
#
|
107
147
|
# @api public
|
108
148
|
# @since 0.1.0
|
@@ -110,7 +150,7 @@ class RedisQueuedLocks::Client
|
|
110
150
|
RedisQueuedLocks::Acquier.release_lock!(redis_client, lock_name)
|
111
151
|
end
|
112
152
|
|
113
|
-
# @return [
|
153
|
+
# @return [Hash<Symbol,Any>] Format: { ok: true/false, result: Symbol/Hash }.
|
114
154
|
#
|
115
155
|
# @api public
|
116
156
|
# @since 0.1.0
|
@@ -10,7 +10,7 @@ module RedisQueuedLocks::Debugger
|
|
10
10
|
# @api private
|
11
11
|
# @since 0.1.0
|
12
12
|
DEBUG_ENABLED_METHOD = <<~METHOD_DECLARATION.strip.freeze
|
13
|
-
def debug(message) = STDOUT.
|
13
|
+
def debug(message) = STDOUT.write("#\{message}\n")
|
14
14
|
METHOD_DECLARATION
|
15
15
|
|
16
16
|
# @return [String]
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api public
|
4
|
+
# @since 0.1.0
|
5
|
+
module RedisQueuedLocks::Instrument::ActiveSupport
|
6
|
+
class << self
|
7
|
+
# @param event [String]
|
8
|
+
# @param payload [Hash<String|Symbol,Any>]
|
9
|
+
# @return [void]
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
# @since 0.1.0
|
13
|
+
def notify(event, payload = {})
|
14
|
+
::ActiveSupport::Notifications.instrument(event, payload)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api public
|
4
|
+
# @since 0.1.0
|
5
|
+
module RedisQueuedLocks::Instrument::VoidNotifier
|
6
|
+
class << self
|
7
|
+
# @param event [String]
|
8
|
+
# @param payload [Hash<String|Symbol,Any>]
|
9
|
+
# @return [void]
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
# @since 0.1.0
|
13
|
+
def notify(event, payload = {}); end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api public
|
4
|
+
# @since 0.1.0
|
5
|
+
module RedisQueuedLocks::Instrument
|
6
|
+
require_relative 'instrument/void_notifier'
|
7
|
+
require_relative 'instrument/active_support'
|
8
|
+
|
9
|
+
class << self
|
10
|
+
# @param instrumenter [Class,Module,Object]
|
11
|
+
# @return [Boolean]
|
12
|
+
#
|
13
|
+
# @api public
|
14
|
+
# @since 0.1.0
|
15
|
+
def valid_interface?(instrumenter)
|
16
|
+
if instrumenter == RedisQueuedLocks::Instrument::ActiveSupport
|
17
|
+
# NOTE: active_support should be required in your app
|
18
|
+
defined?(::ActiveSupport::Notifications)
|
19
|
+
elsif instrumenter.respond_to?(:notify)
|
20
|
+
# NOTE: the method signature should be (event, payload). Supported variants:
|
21
|
+
# => [[:req, :event], [:req, :payload]]
|
22
|
+
# => [[:req, :event], [:opt, :payload]]
|
23
|
+
# => [[:opt, :event], [:opt, :payload]]
|
24
|
+
|
25
|
+
m_obj = instrumenter.method(:notify)
|
26
|
+
m_sig = m_obj.parameters
|
27
|
+
|
28
|
+
f_prm = m_sig[0][0]
|
29
|
+
s_prm = m_sig[1][0]
|
30
|
+
|
31
|
+
if m_sig.size == 2
|
32
|
+
# rubocop:disable Layout/MultilineOperationIndentation
|
33
|
+
# NOTE: check the signature vairants
|
34
|
+
f_prm == :req && s_prm == :req ||
|
35
|
+
f_prm == :req && s_prm == :opt ||
|
36
|
+
f_prm == :opt && s_prm == :opt
|
37
|
+
# rubocop:enable Layout/MultilineOperationIndentation
|
38
|
+
else
|
39
|
+
# NOTE: incompatible signature
|
40
|
+
false
|
41
|
+
end
|
42
|
+
else
|
43
|
+
# NOTE: no required method :notify
|
44
|
+
false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/redis_queued_locks.rb
CHANGED
@@ -12,7 +12,7 @@ module RedisQueuedLocks
|
|
12
12
|
require_relative 'redis_queued_locks/debugger'
|
13
13
|
require_relative 'redis_queued_locks/resource'
|
14
14
|
require_relative 'redis_queued_locks/acquier'
|
15
|
-
require_relative 'redis_queued_locks/
|
15
|
+
require_relative 'redis_queued_locks/instrument'
|
16
16
|
require_relative 'redis_queued_locks/client'
|
17
17
|
|
18
18
|
# @since 0.1.0
|
data/redis_queued_locks.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis_queued_locks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rustam Ibragimov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-02-
|
11
|
+
date: 2024-02-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis-client
|
@@ -64,7 +64,9 @@ files:
|
|
64
64
|
- lib/redis_queued_locks/debugger.rb
|
65
65
|
- lib/redis_queued_locks/debugger/interface.rb
|
66
66
|
- lib/redis_queued_locks/errors.rb
|
67
|
-
- lib/redis_queued_locks/
|
67
|
+
- lib/redis_queued_locks/instrument.rb
|
68
|
+
- lib/redis_queued_locks/instrument/active_support.rb
|
69
|
+
- lib/redis_queued_locks/instrument/void_notifier.rb
|
68
70
|
- lib/redis_queued_locks/resource.rb
|
69
71
|
- lib/redis_queued_locks/version.rb
|
70
72
|
- redis_queued_locks.gemspec
|
@@ -83,14 +85,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
83
85
|
requirements:
|
84
86
|
- - ">="
|
85
87
|
- !ruby/object:Gem::Version
|
86
|
-
version: 3.
|
88
|
+
version: '3.1'
|
87
89
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
90
|
requirements:
|
89
91
|
- - ">="
|
90
92
|
- !ruby/object:Gem::Version
|
91
93
|
version: '0'
|
92
94
|
requirements: []
|
93
|
-
rubygems_version: 3.5.
|
95
|
+
rubygems_version: 3.5.1
|
94
96
|
signing_key:
|
95
97
|
specification_version: 4
|
96
98
|
summary: Queued distributed locks based on Redis.
|