redis_queued_locks 1.13.0 → 1.15.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.
@@ -1,13 +1,13 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- redis_queued_locks (1.13.0)
4
+ redis_queued_locks (1.15.0)
5
5
  redis-client (~> 0.20)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- activesupport (8.0.2)
10
+ activesupport (8.0.3)
11
11
  base64
12
12
  benchmark (>= 0.3)
13
13
  bigdecimal
@@ -34,10 +34,10 @@ GEM
34
34
  ast (2.4.3)
35
35
  base64 (0.3.0)
36
36
  benchmark (0.4.1)
37
- bigdecimal (3.2.1)
37
+ bigdecimal (3.3.1)
38
38
  coderay (1.1.3)
39
39
  concurrent-ruby (1.3.5)
40
- connection_pool (2.5.3)
40
+ connection_pool (2.5.4)
41
41
  csv (3.3.5)
42
42
  diff-lcs (1.6.2)
43
43
  docile (1.4.1)
@@ -56,7 +56,7 @@ GEM
56
56
  fileutils (1.7.3)
57
57
  i18n (1.14.7)
58
58
  concurrent-ruby (~> 1.0)
59
- json (2.12.2)
59
+ json (2.15.1)
60
60
  language_server-protocol (3.17.0.5)
61
61
  lint_roller (1.1.0)
62
62
  listen (3.9.0)
@@ -64,43 +64,43 @@ GEM
64
64
  rb-inotify (~> 0.9, >= 0.9.10)
65
65
  logger (1.7.0)
66
66
  method_source (1.1.0)
67
- minitest (5.25.5)
67
+ minitest (5.26.0)
68
68
  mutex_m (0.3.0)
69
69
  parallel (1.27.0)
70
- parser (3.3.8.0)
70
+ parser (3.3.9.0)
71
71
  ast (~> 2.4.1)
72
72
  racc
73
- prism (1.4.0)
73
+ prism (1.6.0)
74
74
  pry (0.15.2)
75
75
  coderay (~> 1.1)
76
76
  method_source (~> 1.0)
77
77
  racc (1.8.1)
78
- rack (3.1.15)
78
+ rack (3.2.3)
79
79
  rainbow (3.1.1)
80
80
  rake (13.3.0)
81
81
  rb-fsevent (0.11.2)
82
82
  rb-inotify (0.11.1)
83
83
  ffi (~> 1.0)
84
- rbs (3.9.4)
84
+ rbs (3.9.5)
85
85
  logger
86
- redis-client (0.24.0)
86
+ redis-client (0.26.1)
87
87
  connection_pool
88
- regexp_parser (2.10.0)
88
+ regexp_parser (2.11.3)
89
89
  rspec (3.13.1)
90
90
  rspec-core (~> 3.13.0)
91
91
  rspec-expectations (~> 3.13.0)
92
92
  rspec-mocks (~> 3.13.0)
93
- rspec-core (3.13.4)
93
+ rspec-core (3.13.5)
94
94
  rspec-support (~> 3.13.0)
95
95
  rspec-expectations (3.13.5)
96
96
  diff-lcs (>= 1.2.0, < 2.0)
97
97
  rspec-support (~> 3.13.0)
98
- rspec-mocks (3.13.5)
98
+ rspec-mocks (3.13.6)
99
99
  diff-lcs (>= 1.2.0, < 2.0)
100
100
  rspec-support (~> 3.13.0)
101
101
  rspec-retry (0.6.2)
102
102
  rspec-core (> 3.3)
103
- rspec-support (3.13.4)
103
+ rspec-support (3.13.6)
104
104
  rubocop (1.75.7)
105
105
  json (~> 2.3)
106
106
  language_server-protocol (~> 3.17.0.2)
@@ -112,7 +112,7 @@ GEM
112
112
  rubocop-ast (>= 1.44.0, < 2.0)
113
113
  ruby-progressbar (~> 1.7)
114
114
  unicode-display_width (>= 2.4.0, < 4.0)
115
- rubocop-ast (1.44.1)
115
+ rubocop-ast (1.47.1)
116
116
  parser (>= 3.3.7.2)
117
117
  prism (~> 1.4)
118
118
  rubocop-capybara (2.22.1)
@@ -155,8 +155,8 @@ GEM
155
155
  docile (~> 1.1)
156
156
  simplecov-html (~> 0.11)
157
157
  simplecov_json_formatter (~> 0.1)
158
- simplecov-html (0.13.1)
159
- simplecov-lcov (0.8.0)
158
+ simplecov-html (0.13.2)
159
+ simplecov-lcov (0.9.0)
160
160
  simplecov_json_formatter (0.1.4)
161
161
  steep (1.10.0)
162
162
  activesupport (>= 5.1)
@@ -180,10 +180,10 @@ GEM
180
180
  unicode-display_width (>= 1.1.1, < 4)
181
181
  tzinfo (2.0.6)
182
182
  concurrent-ruby (~> 1.0)
183
- unicode-display_width (3.1.4)
184
- unicode-emoji (~> 4.0, >= 4.0.4)
185
- unicode-emoji (4.0.4)
186
- uri (1.0.3)
183
+ unicode-display_width (3.2.0)
184
+ unicode-emoji (~> 4.1)
185
+ unicode-emoji (4.1.0)
186
+ uri (1.0.4)
187
187
  zlib (3.2.1)
188
188
 
189
189
  PLATFORMS
@@ -214,4 +214,4 @@ DEPENDENCIES
214
214
  steep
215
215
 
216
216
  BUNDLED WITH
217
- 2.6.9
217
+ 2.7.2
@@ -17,6 +17,8 @@ module RedisQueuedLocks::Acquirer::AcquireLock
17
17
  require_relative 'acquire_lock/try_to_lock'
18
18
  require_relative 'acquire_lock/dequeue_from_lock_queue'
19
19
 
20
+ # @since 1.14.0
21
+ extend RedisQueuedLocks::Utilities
20
22
  # @since 1.0.0
21
23
  extend TryToLock
22
24
  # @since 1.0.0
@@ -157,7 +159,7 @@ module RedisQueuedLocks::Acquirer::AcquireLock
157
159
  #
158
160
  # @api private
159
161
  # @since 1.0.0
160
- # @version 1.13.0
162
+ # @version 1.14.0
161
163
  def acquire_lock(
162
164
  redis,
163
165
  lock_name,
@@ -309,7 +311,7 @@ module RedisQueuedLocks::Acquirer::AcquireLock
309
311
  detailed_acq_timeout_error,
310
312
  on_timeout: acq_dequeue
311
313
  ) do
312
- acq_start_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC, :microsecond)
314
+ acq_start_time = clock_gettime
313
315
 
314
316
  # Step 2.1: cyclically try to obtain the lock
315
317
  while acq_process[:should_try]
@@ -358,7 +360,7 @@ module RedisQueuedLocks::Acquirer::AcquireLock
358
360
  # @type var ok: bool
359
361
  # @type var result: Symbol|Hash[Symbol,untyped]
360
362
 
361
- acq_end_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC, :microsecond)
363
+ acq_end_time = clock_gettime
362
364
  acq_time = ((acq_end_time - acq_start_time) / 1_000.0).ceil(2)
363
365
 
364
366
  # Step X: save the intermediate results to the result observer
@@ -491,7 +493,7 @@ module RedisQueuedLocks::Acquirer::AcquireLock
491
493
  # Step 3.a: acquired successfully => run logic or return the result of acquirement
492
494
  if block_given?
493
495
  begin
494
- yield_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC, :microsecond)
496
+ yield_time = clock_gettime
495
497
 
496
498
  ttl_shift = (
497
499
  (yield_time - acq_process[:acq_end_time]) / 1_000.0 -
@@ -524,9 +526,7 @@ module RedisQueuedLocks::Acquirer::AcquireLock
524
526
  &block
525
527
  )
526
528
  ensure
527
- acq_process[:rel_time] = ::Process.clock_gettime(
528
- ::Process::CLOCK_MONOTONIC, :microsecond
529
- )
529
+ acq_process[:rel_time] = clock_gettime
530
530
  acq_process[:hold_time] = (
531
531
  (acq_process[:rel_time] - acq_process[:acq_end_time]) / 1_000.0
532
532
  ).ceil(2)
@@ -71,7 +71,7 @@ module RedisQueuedLocks::Acquirer::ReleaseAllLocks
71
71
  #
72
72
  # @api private
73
73
  # @since 1.0.0
74
- # @version 1.6.0
74
+ # @version 1.14.0
75
75
  def release_all_locks(
76
76
  redis,
77
77
  batch_size,
@@ -87,14 +87,14 @@ module RedisQueuedLocks::Acquirer::ReleaseAllLocks
87
87
  instr_sampler,
88
88
  instr_sample_this
89
89
  )
90
- rel_start_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC, :microsecond)
90
+ rel_start_time = clock_gettime
91
91
  fully_release_all_locks(redis, batch_size) => { ok:, result: } # steep:ignore
92
92
 
93
93
  # @type var ok: bool
94
94
  # @type var result: Hash[Symbol,Integer]
95
95
 
96
96
  time_at = Time.now.to_f
97
- rel_end_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC, :microsecond)
97
+ rel_end_time = clock_gettime
98
98
  rel_time = ((rel_end_time - rel_start_time) / 1_000.0).ceil(2)
99
99
 
100
100
  instr_sampled = RedisQueuedLocks::Instrument.should_instrument?(
@@ -71,7 +71,7 @@ module RedisQueuedLocks::Acquirer::ReleaseLock
71
71
  #
72
72
  # @api private
73
73
  # @since 1.0.0
74
- # @version 1.6.0
74
+ # @version 1.14.0
75
75
  # rubocop:disable Metrics/MethodLength
76
76
  def release_lock(
77
77
  redis,
@@ -90,14 +90,14 @@ module RedisQueuedLocks::Acquirer::ReleaseLock
90
90
  lock_key = RedisQueuedLocks::Resource.prepare_lock_key(lock_name)
91
91
  lock_key_queue = RedisQueuedLocks::Resource.prepare_lock_queue(lock_name)
92
92
 
93
- rel_start_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC, :microsecond)
93
+ rel_start_time = clock_gettime
94
94
  fully_release_lock(redis, lock_key, lock_key_queue) => { ok:, result: } # steep:ignore
95
95
 
96
96
  # @type var ok: bool
97
97
  # @type var result: Hash[Symbol,Symbol]
98
98
 
99
99
  time_at = Time.now.to_f
100
- rel_end_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC, :microsecond)
100
+ rel_end_time = clock_gettime
101
101
  rel_time = ((rel_end_time - rel_start_time) / 1_000.0).ceil(2)
102
102
 
103
103
  instr_sampled = RedisQueuedLocks::Instrument.should_instrument?(
@@ -0,0 +1,221 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 1.14.0
5
+ module RedisQueuedLocks::Acquirer::ReleaseLocksOf
6
+ # @since 1.14.0
7
+ extend RedisQueuedLocks::Utilities
8
+
9
+ class << self
10
+ # Release all queues and locks that belong to the given host and its associated acquirer.
11
+ #
12
+ # @param refused_host_id [String]
13
+ # A host whose locks and queues should be released.
14
+ # @param refused_acquirer_id [String]
15
+ # An acquirer (of the passed host) whose locks and queues should be released.
16
+ # @param redis [RedisClient]
17
+ # Redis connection client.
18
+ # @param lock_scan_size [Integer]
19
+ # The number of lock keys that should be released in a time.
20
+ # Affects the RubyVM memmory (cuz each found lock will be temporary stored in memory for
21
+ # subsequent removal from redis in one query at a time).
22
+ # @param queue_scan_size [Integer]
23
+ # The number of lock queues that should be scanned removing an acquirer from them (at a time).
24
+ # @param logger [::Logger,#debug]
25
+ # - Logger object used from `configuration` layer (see config['logger']);
26
+ # - See RedisQueuedLocks::Logging::VoidLogger for example;
27
+ # @param isntrumenter [#notify]
28
+ # See RedisQueuedLocks::Instrument::ActiveSupport for example.
29
+ # @param instrument [NilClass,Any]
30
+ # - Custom instrumentation data wich will be passed to the instrumenter's payload
31
+ # with :instrument key;
32
+ # @param log_sampling_enabled [Boolean]
33
+ # - enables <log sampling>: only the configured percent of RQL cases will be logged;
34
+ # - disabled by default;
35
+ # - works in tandem with <config['log_sampling_percent']> and <config['log_sampler']>;
36
+ # @param log_sampling_percent [Integer]
37
+ # - the percent of cases that should be logged;
38
+ # - take an effect when <config['log_sampling_enalbed']> is true;
39
+ # - works in tandem with <config['log_sampling_enabled']> and <config['log_sampler']> configs;
40
+ # @param log_sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
41
+ # - percent-based log sampler that decides should be RQL case logged or not;
42
+ # - works in tandem with <config['log_sampling_enabled']> and
43
+ # <config['log_sampling_percent']> configs;
44
+ # - based on the ultra simple percent-based (weight-based) algorithm that uses
45
+ # SecureRandom.rand method so the algorithm error is ~(0%..13%);
46
+ # - you can provide your own log sampler with bettter algorithm that should realize
47
+ # `sampling_happened?(percent) => boolean` interface
48
+ # (see `RedisQueuedLocks::Logging::Sampler` for example);
49
+ # @param log_sample_this [Boolean]
50
+ # - marks the method that everything should be logged despite the enabled log sampling;
51
+ # - makes sense when log sampling is enabled;
52
+ # @param instr_sampling_enabled [Boolean]
53
+ # - enables <instrumentaion sampling>: only the configured percent
54
+ # of RQL cases will be instrumented;
55
+ # - disabled by default;
56
+ # - works in tandem with <config['instr_sampling_percent']> and <config['instr_sampler']>;
57
+ # @param instr_sampling_percent [Integer]
58
+ # - the percent of cases that should be instrumented;
59
+ # - take an effect when <config['instr_sampling_enalbed']> is true;
60
+ # - works in tandem with <config['instr_sampling_enabled']>
61
+ # and <config['instr_sampler']> configs;
62
+ # @param instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
63
+ # - percent-based log sampler that decides should be RQL case instrumented or not;
64
+ # - works in tandem with <config['instr_sampling_enabled']> and
65
+ # <config['instr_sampling_percent']> configs;
66
+ # - based on the ultra simple percent-based (weight-based) algorithm that uses
67
+ # SecureRandom.rand method so the algorithm error is ~(0%..13%);
68
+ # - you can provide your own log sampler with bettter algorithm that should realize
69
+ # `sampling_happened?(percent) => boolean` interface
70
+ # (see `RedisQueuedLocks::Instrument::Sampler` for example);
71
+ # @param instr_sample_this [Boolean]
72
+ # - marks the method that everything should be instrumneted
73
+ # despite the enabled instrumentation sampling;
74
+ # - makes sense when instrumentation sampling is enabled;
75
+ # @return [Hash<Symbol,Any>]
76
+ # Format: {
77
+ # ok: true,
78
+ # result: {
79
+ # rel_key_cnt: Integer,
80
+ # tch_queue_cnt: Integer,
81
+ # rel_time: Numeric
82
+ # }
83
+ # }
84
+ #
85
+ # @api private
86
+ # @since 1.14.0
87
+ # @version 1.15.0
88
+ # rubocop:disable Metrics/MethodLength
89
+ def release_locks_of(
90
+ refused_host_id,
91
+ refused_acquirer_id,
92
+ redis,
93
+ lock_scan_size,
94
+ queue_scan_size,
95
+ logger,
96
+ instrumenter,
97
+ instrument,
98
+ log_sampling_enabled,
99
+ log_sampling_percent,
100
+ log_sampler,
101
+ log_sample_this,
102
+ instr_sampling_enabled,
103
+ instr_sampling_percent,
104
+ instr_sampler,
105
+ instr_sample_this
106
+ ) # TODO: move from SCAN to indexes :thinking:
107
+ rel_start_time = clock_gettime
108
+
109
+ # steep:ignore:start
110
+ fully_release_locks_of(
111
+ refused_host_id,
112
+ refused_acquirer_id,
113
+ redis,
114
+ lock_scan_size,
115
+ queue_scan_size
116
+ ) => { ok:, result: }
117
+ # steep:ignore:end
118
+
119
+ # @type var ok: bool
120
+ # @type var result: Hash[Symbol,Integer]
121
+
122
+ time_at = Time.now.to_f
123
+ rel_end_time = clock_gettime
124
+ rel_time = ((rel_end_time - rel_start_time) / 1_000.0).ceil(2)
125
+
126
+ instr_sampled = RedisQueuedLocks::Instrument.should_instrument?(
127
+ instr_sampling_enabled,
128
+ instr_sample_this,
129
+ instr_sampling_percent,
130
+ instr_sampler
131
+ )
132
+
133
+ run_non_critical do
134
+ instrumenter.notify('redis_queued_locks.release_locks_of', {
135
+ at: time_at,
136
+ hst_id: refused_host_id,
137
+ acq_id: refused_acquirer_id,
138
+ rel_time: rel_time,
139
+ rel_key_cnt: result[:rel_key_cnt],
140
+ tch_queue_cnt: result[:tch_queue_cnt]
141
+ })
142
+ end if instr_sampled
143
+
144
+ {
145
+ ok: true,
146
+ result: {
147
+ rel_key_cnt: result[:rel_key_cnt],
148
+ tch_queue_cnt: result[:tch_queue_cnt],
149
+ rel_time: rel_time
150
+ }
151
+ }
152
+ end
153
+ # rubocop:enable Metrics/MethodLength
154
+
155
+ private
156
+
157
+ # @param refused_host_id [String]
158
+ # @param refused_acquirer_id [String]
159
+ # @param redis [RedisClient]
160
+ # @param lock_scan_size [Integer]
161
+ # @param queue_scan_size [Integer]
162
+ # @return [Hash<Symbol,Boolean|Hash<Symbol,Integer>>]
163
+ # - Example: { ok: true, result: { rel_key_cnt: 12345, tch_queue_cnt: 321 } }
164
+ #
165
+ # @api private
166
+ # @since 1.14.0
167
+ # rubocop:disable Metrics/MethodLength
168
+ def fully_release_locks_of(
169
+ refused_host_id,
170
+ refused_acquirer_id,
171
+ redis,
172
+ lock_scan_size,
173
+ queue_scan_size
174
+ )
175
+ # TODO: some indexing approach isntead of <scan>
176
+ rel_key_cnt = 0
177
+ tch_queue_cnt = 0
178
+
179
+ redis.with do |rconn|
180
+ # Step A: drop locks of the passed host/acquirer
181
+ refused_locks = Set.new #: Set[String]
182
+ rconn.scan(
183
+ 'MATCH',
184
+ RedisQueuedLocks::Resource::LOCK_PATTERN,
185
+ count: lock_scan_size
186
+ ) do |lock_key|
187
+ acquirer_id, host_id = rconn.call('HMGET', lock_key, 'acq_id', 'hst_id')
188
+ if refused_host_id == host_id && refused_acquirer_id == acquirer_id
189
+ refused_locks << lock_key
190
+ end
191
+
192
+ if refused_locks.size >= lock_scan_size
193
+ # NOTE: steep can not recognize the `*`-splat operator on Set objects
194
+ rconn.call('DEL', *refused_locks) # steep:ignore
195
+ rel_key_cnt += refused_locks.size
196
+ refused_locks.clear
197
+ end
198
+ end
199
+
200
+ if refused_locks.any?
201
+ # NOTE: steep can not recognize the `*`-splat operator on Set objects
202
+ rconn.call('DEL', *refused_locks) # steep:ignore
203
+ rel_key_cnt += refused_locks.size
204
+ end
205
+
206
+ # Step B: drop passed host/acquirer from lock queues
207
+ rconn.scan(
208
+ 'MATCH',
209
+ RedisQueuedLocks::Resource::LOCK_QUEUE_PATTERN,
210
+ count: queue_scan_size
211
+ ) do |lock_queue|
212
+ res = rconn.call('ZREM', lock_queue, refused_acquirer_id)
213
+ tch_queue_cnt += 1 if res != 0
214
+ end
215
+ end
216
+
217
+ { ok: true, result: { rel_key_cnt:, tch_queue_cnt: } }
218
+ end
219
+ end
220
+ # rubocop:enable Metrics/MethodLength
221
+ end
@@ -6,6 +6,7 @@ module RedisQueuedLocks::Acquirer
6
6
  require_relative 'acquirer/acquire_lock'
7
7
  require_relative 'acquirer/release_lock'
8
8
  require_relative 'acquirer/release_all_locks'
9
+ require_relative 'acquirer/release_locks_of'
9
10
  require_relative 'acquirer/is_locked'
10
11
  require_relative 'acquirer/is_queued'
11
12
  require_relative 'acquirer/lock_info'
@@ -2,6 +2,7 @@
2
2
 
3
3
  # @api public
4
4
  # @since 1.0.0
5
+ # @version 1.14.0
5
6
  # rubocop:disable Metrics/ClassLength
6
7
  class RedisQueuedLocks::Client
7
8
  # @return [RedisClient]
@@ -27,7 +28,7 @@ class RedisQueuedLocks::Client
27
28
  # @return [RedisQueuedLocks::Config]
28
29
  #
29
30
  # @api public
30
- # @since [1.13.0]
31
+ # @since 1.13.0
31
32
  attr_reader :config
32
33
 
33
34
  # @param redis_client [RedisClient]
@@ -52,7 +53,7 @@ class RedisQueuedLocks::Client
52
53
  # @return [void]
53
54
  #
54
55
  # @api public
55
- # @since [1.13.0]
56
+ # @since 1.13.0
56
57
  def configure(&configuration)
57
58
  config.configure(&configuration)
58
59
  end
@@ -577,6 +578,8 @@ class RedisQueuedLocks::Client
577
578
  identity
578
579
  )
579
580
  end
581
+ alias_method :current_acq_id, :current_acquirer_id
582
+ alias_method :acq_id, :current_acquirer_id
580
583
 
581
584
  # Retrun the current host identifier.
582
585
  #
@@ -608,6 +611,8 @@ class RedisQueuedLocks::Client
608
611
  identity
609
612
  )
610
613
  end
614
+ alias_method :current_hst_id, :current_host_id
615
+ alias_method :hst_id, :current_host_id
611
616
 
612
617
  # Return the list of possible host identifiers that can be reached from the current ractor.
613
618
  #
@@ -739,6 +744,154 @@ class RedisQueuedLocks::Client
739
744
  end
740
745
  alias_method :release_locks, :clear_locks
741
746
 
747
+ # Release all locks of the passed acquirer/host and remove this acquirer/host from all queues;
748
+ #
749
+ # This is a cleanup helper intended for operational and debugging scenarios (for example: your
750
+ # current puma request thread is killed by Rack::Timeout and you need to cleanup all zombie RQL
751
+ # locks and lock reuqests obtained during the request processing).
752
+ #
753
+ # Identifiers can be extracted via:
754
+ # - `#current_host_id`
755
+ # - `#current_acquirer_id`
756
+ # - `#possible_host_ids`
757
+ # - lock data (extracted from Redis via #lock_info, #locks_info, #queue_info, #queues_info)
758
+ #
759
+ # @option host_id [String] Host identifier whose locks/queues should be released.
760
+ # @option acquirer_id [String] Acquirer identifier, associated with the `host_id`.
761
+ # @option lock_scan_size [Integer]
762
+ # @option queue_scan_size [Integer]
763
+ # @option logger [::Logger,#debug]
764
+ # @option instrumenter [#notify] See `config['instrumenter']` docs for details.
765
+ # @option instrument [NilClass,Any]
766
+ # @option log_sampling_enabled [Boolean]
767
+ # @option log_sampling_percent [Integer]
768
+ # @option log_sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
769
+ # @option log_sample_this [Boolean]
770
+ # @option instr_sampling_enabled [Boolean]
771
+ # @option instr_sampling_percent [Integer]
772
+ # @option instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
773
+ # @option instr_sample_this [Boolean]
774
+ # @return [Hash<Symbol,Boolean|Hash<Symbol,Numeric>>]
775
+ # Example: { ok: true, result: { rel_key_cnt: 100, tch_queue_cnt: 2, rel_time: 0.01 } }
776
+ #
777
+ # @example Release locks of the current process:
778
+ # client.clear_locks_of(
779
+ # host_id: client.current_host_id,
780
+ # acquirer_id: client.current_acquirer_id
781
+ # )
782
+ #
783
+ # @example Release locks of a different host/acquirer:
784
+ # client.clear_locks_of(
785
+ # host_id: "rql:hst:62681/2016/2032/b30ec5e4bea10512",
786
+ # acquirer_id: "ral:acq:62681/2016/2024/2032/b30ec5e4bea10512"
787
+ # )
788
+ #
789
+ # @see #clear_current_locks
790
+ # @see #current_host_id
791
+ # @see #current_acquirer_id
792
+ # @see #possible_host_ids
793
+ # @see #lock_info
794
+ # @see #locks_info
795
+ # @see #queue_info
796
+ # @see #queues_info
797
+ #
798
+ # @api public
799
+ # @since 1.14.0
800
+ def clear_locks_of(
801
+ host_id:,
802
+ acquirer_id:,
803
+ lock_scan_size: config['clear_locks_of__lock_scan_size'], # steep:ignore
804
+ queue_scan_size: config['clear_locks_of__queue_scan_size'], # steep:ingore
805
+ logger: config['logger'], # steep:ignore
806
+ instrumenter: config['instrumenter'], # steep:ignore
807
+ instrument: nil,
808
+ log_sampling_enabled: config['log_sampling_enabled'], # steep:ignore
809
+ log_sampling_percent: config['log_sampling_percent'], # steep:ignore
810
+ log_sampler: config['log_sampler'], # steep:ignore
811
+ log_sample_this: false,
812
+ instr_sampling_enabled: config['instr_sampling_enabled'], # steep:ignore
813
+ instr_sampling_percent: config['instr_sampling_percent'], # steep:ignore
814
+ instr_sampler: config['instr_sampler'], # steep:ignore
815
+ instr_sample_this: false
816
+ )
817
+ RedisQueuedLocks::Acquirer::ReleaseLocksOf.release_locks_of(
818
+ host_id,
819
+ acquirer_id,
820
+ redis_client,
821
+ lock_scan_size,
822
+ queue_scan_size,
823
+ logger,
824
+ instrumenter,
825
+ instrument,
826
+ log_sampling_enabled,
827
+ log_sampling_percent,
828
+ log_sampler,
829
+ log_sample_this,
830
+ instr_sampling_enabled,
831
+ instr_sampling_percent,
832
+ instr_sampler,
833
+ instr_sample_this
834
+ )
835
+ end
836
+ alias_method :release_locks_of, :clear_locks_of
837
+
838
+ # Release all locks of the current acquirer/host and
839
+ # remove the current acquirer/host from all queues;
840
+ #
841
+ # @option batch_size [Integer]
842
+ # @option logger [::Logger,#debug]
843
+ # @option instrumenter [#notify] See `config['instrumenter']` docs for details.
844
+ # @option instrument [NilClass,Any]
845
+ # @option log_sampling_enabled [Boolean]
846
+ # @option log_sampling_percent [Integer]
847
+ # @option log_sampler [#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]
848
+ # @option log_sample_this [Boolean]
849
+ # @option instr_sampling_enabled [Boolean]
850
+ # @option instr_sampling_percent [Integer]
851
+ # @option instr_sampler [#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]
852
+ # @option instr_sample_this [Boolean]
853
+ # @return [Hash<Symbol,Boolean|Hash<Symbol,Numeric>>]
854
+ # Example: { ok: true, result: { rel_key_cnt: 100, tch_queue_cnt: 2, rel_time: 0.01 } }
855
+ #
856
+ # @see #clear_locks_of
857
+ #
858
+ # @api public
859
+ # @since 1.14.0
860
+ def clear_current_locks(
861
+ lock_scan_size: config['clear_locks_of__lock_scan_size'], # steep:ignore
862
+ queue_scan_size: config['clear_locks_of__queue_scan_size'], # steep:ingore
863
+ logger: config['logger'], # steep:ignore
864
+ instrumenter: config['instrumenter'], # steep:ignore
865
+ instrument: nil,
866
+ log_sampling_enabled: config['log_sampling_enabled'], # steep:ignore
867
+ log_sampling_percent: config['log_sampling_percent'], # steep:ignore
868
+ log_sampler: config['log_sampler'], # steep:ignore
869
+ log_sample_this: false,
870
+ instr_sampling_enabled: config['instr_sampling_enabled'], # steep:ignore
871
+ instr_sampling_percent: config['instr_sampling_percent'], # steep:ignore
872
+ instr_sampler: config['instr_sampler'], # steep:ignore
873
+ instr_sample_this: false
874
+ )
875
+ clear_locks_of(
876
+ host_id: current_host_id,
877
+ acquirer_id: current_acquirer_id,
878
+ lock_scan_size:,
879
+ queue_scan_size:,
880
+ logger:,
881
+ instrumenter:,
882
+ instrument:,
883
+ log_sampling_enabled:,
884
+ log_sampling_percent:,
885
+ log_sampler:,
886
+ log_sample_this:,
887
+ instr_sampling_enabled:,
888
+ instr_sampling_percent:,
889
+ instr_sampler:,
890
+ instr_sample_this:
891
+ )
892
+ end
893
+ alias_method :release_current_locks, :clear_current_locks
894
+
742
895
  # @option scan_size [Integer]
743
896
  # The batch of scanned keys for Redis'es SCAN command.
744
897
  # @option with_info [Boolean]