redis_queued_locks 1.12.0 → 1.13.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.
Files changed (121) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -1
  3. data/.ruby-version +1 -1
  4. data/CHANGELOG.md +42 -5
  5. data/LICENSE.txt +1 -1
  6. data/README.md +231 -203
  7. data/Rakefile +12 -4
  8. data/Steepfile +16 -0
  9. data/github_ci/ruby3.3.gemfile +17 -0
  10. data/github_ci/ruby3.3.gemfile.lock +217 -0
  11. data/lib/redis_queued_locks/{acquier → acquirer}/acquire_lock/delay_execution.rb +4 -4
  12. data/lib/redis_queued_locks/acquirer/acquire_lock/dequeue_from_lock_queue/log_visitor.rb +40 -0
  13. data/lib/redis_queued_locks/{acquier → acquirer}/acquire_lock/dequeue_from_lock_queue.rb +17 -8
  14. data/lib/redis_queued_locks/acquirer/acquire_lock/instr_visitor.rb +166 -0
  15. data/lib/redis_queued_locks/acquirer/acquire_lock/log_visitor.rb +218 -0
  16. data/lib/redis_queued_locks/acquirer/acquire_lock/try_to_lock/log_visitor.rb +543 -0
  17. data/lib/redis_queued_locks/{acquier → acquirer}/acquire_lock/try_to_lock.rb +126 -92
  18. data/lib/redis_queued_locks/{acquier → acquirer}/acquire_lock/with_acq_timeout.rb +14 -13
  19. data/lib/redis_queued_locks/acquirer/acquire_lock/yield_expire/log_visitor.rb +76 -0
  20. data/lib/redis_queued_locks/{acquier → acquirer}/acquire_lock/yield_expire.rb +43 -20
  21. data/lib/redis_queued_locks/{acquier → acquirer}/acquire_lock.rb +69 -42
  22. data/lib/redis_queued_locks/{acquier → acquirer}/clear_dead_requests.rb +5 -3
  23. data/lib/redis_queued_locks/{acquier → acquirer}/extend_lock_ttl.rb +4 -3
  24. data/lib/redis_queued_locks/{acquier → acquirer}/is_locked.rb +1 -1
  25. data/lib/redis_queued_locks/{acquier → acquirer}/is_queued.rb +1 -1
  26. data/lib/redis_queued_locks/{acquier → acquirer}/keys.rb +5 -5
  27. data/lib/redis_queued_locks/{acquier → acquirer}/lock_info.rb +9 -5
  28. data/lib/redis_queued_locks/{acquier → acquirer}/locks.rb +16 -3
  29. data/lib/redis_queued_locks/{acquier → acquirer}/queue_info.rb +8 -6
  30. data/lib/redis_queued_locks/{acquier → acquirer}/queues.rb +9 -2
  31. data/lib/redis_queued_locks/{acquier → acquirer}/release_all_locks.rb +23 -18
  32. data/lib/redis_queued_locks/{acquier → acquirer}/release_lock.rb +25 -19
  33. data/lib/redis_queued_locks/acquirer.rb +18 -0
  34. data/lib/redis_queued_locks/client.rb +164 -254
  35. data/lib/redis_queued_locks/config/dsl.rb +94 -0
  36. data/lib/redis_queued_locks/config.rb +231 -0
  37. data/lib/redis_queued_locks/data.rb +2 -0
  38. data/lib/redis_queued_locks/errors.rb +27 -11
  39. data/lib/redis_queued_locks/instrument.rb +11 -4
  40. data/lib/redis_queued_locks/logging/void_logger.rb +38 -1
  41. data/lib/redis_queued_locks/logging.rb +20 -5
  42. data/lib/redis_queued_locks/resource.rb +49 -11
  43. data/lib/redis_queued_locks/swarm/acquirers.rb +17 -16
  44. data/lib/redis_queued_locks/swarm/flush_zombies.rb +26 -25
  45. data/lib/redis_queued_locks/swarm/probe_hosts.rb +20 -19
  46. data/lib/redis_queued_locks/swarm/redis_client_builder.rb +3 -3
  47. data/lib/redis_queued_locks/swarm/supervisor.rb +19 -6
  48. data/lib/redis_queued_locks/swarm/swarm_element/isolated.rb +20 -18
  49. data/lib/redis_queued_locks/swarm/swarm_element/threaded.rb +35 -27
  50. data/lib/redis_queued_locks/swarm/zombie_info.rb +9 -9
  51. data/lib/redis_queued_locks/swarm.rb +20 -41
  52. data/lib/redis_queued_locks/utilities/lock.rb +4 -2
  53. data/lib/redis_queued_locks/utilities.rb +2 -2
  54. data/lib/redis_queued_locks/version.rb +2 -2
  55. data/lib/redis_queued_locks.rb +2 -2
  56. data/rbs_collection.lock.yaml +40 -0
  57. data/rbs_collection.yaml +16 -0
  58. data/redis_queued_locks.gemspec +22 -23
  59. data/sig/manifest.yml +7 -0
  60. data/sig/redis_queued_locks/acquier.rbs +4 -0
  61. data/sig/redis_queued_locks/acquirer/acquire_lock/delay_execution.rbs +9 -0
  62. data/sig/redis_queued_locks/acquirer/acquire_lock/dequeue_from_lock_queue/log_visitor.rbs +21 -0
  63. data/sig/redis_queued_locks/acquirer/acquire_lock/dequeue_from_lock_queue.rbs +26 -0
  64. data/sig/redis_queued_locks/acquirer/acquire_lock/instr_visitor.rbs +71 -0
  65. data/sig/redis_queued_locks/acquirer/acquire_lock/log_visitor.rbs +72 -0
  66. data/sig/redis_queued_locks/acquirer/acquire_lock/try_to_lock/log_visitor.rbs +179 -0
  67. data/sig/redis_queued_locks/acquirer/acquire_lock/try_to_lock.rbs +48 -0
  68. data/sig/redis_queued_locks/acquirer/acquire_lock/with_acq_timeout.rbs +19 -0
  69. data/sig/redis_queued_locks/acquirer/acquire_lock/yield_expire.rbs +41 -0
  70. data/sig/redis_queued_locks/acquirer/acquire_lock/yield_with_expire/log_visitor.rbs +32 -0
  71. data/sig/redis_queued_locks/acquirer/acquire_lock.rbs +51 -0
  72. data/sig/redis_queued_locks/acquirer/clear_dead_requests.rbs +28 -0
  73. data/sig/redis_queued_locks/acquirer/extend_lock_ttl.rbs +28 -0
  74. data/sig/redis_queued_locks/acquirer/is_locked.rbs +9 -0
  75. data/sig/redis_queued_locks/acquirer/is_queued.rbs +9 -0
  76. data/sig/redis_queued_locks/acquirer/keys.rbs +10 -0
  77. data/sig/redis_queued_locks/acquirer/lock_info.rbs +10 -0
  78. data/sig/redis_queued_locks/acquirer/locks.rbs +16 -0
  79. data/sig/redis_queued_locks/acquirer/queue_info.rbs +13 -0
  80. data/sig/redis_queued_locks/acquirer/queues.rbs +16 -0
  81. data/sig/redis_queued_locks/acquirer/release_all_locks.rbs +30 -0
  82. data/sig/redis_queued_locks/acquirer/release_lock.rbs +38 -0
  83. data/sig/redis_queued_locks/client.rbs +195 -0
  84. data/sig/redis_queued_locks/config/dsl.rbs +26 -0
  85. data/sig/redis_queued_locks/config.rbs +23 -0
  86. data/sig/redis_queued_locks/data.rbs +4 -0
  87. data/sig/redis_queued_locks/debugger/interface.rbs +9 -0
  88. data/sig/redis_queued_locks/debugger.rbs +13 -0
  89. data/sig/redis_queued_locks/errors.rbs +43 -0
  90. data/sig/redis_queued_locks/instrument/active_support.rbs +7 -0
  91. data/sig/redis_queued_locks/instrument/sampler.rbs +9 -0
  92. data/sig/redis_queued_locks/instrument/void_notifier.rbs +7 -0
  93. data/sig/redis_queued_locks/instrument.rbs +15 -0
  94. data/sig/redis_queued_locks/logging/sampler.rbs +9 -0
  95. data/sig/redis_queued_locks/logging/void_logger.rbs +15 -0
  96. data/sig/redis_queued_locks/logging.rbs +15 -0
  97. data/sig/redis_queued_locks/resource.rbs +42 -0
  98. data/sig/redis_queued_locks/swarm/acquirers.rbs +10 -0
  99. data/sig/redis_queued_locks/swarm/flush_zombies.rbs +13 -0
  100. data/sig/redis_queued_locks/swarm/probe_hosts.rbs +13 -0
  101. data/sig/redis_queued_locks/swarm/redis_client_builder.rbs +19 -0
  102. data/sig/redis_queued_locks/swarm/supervisor.rbs +26 -0
  103. data/sig/redis_queued_locks/swarm/swarm_element/isolated.rbs +52 -0
  104. data/sig/redis_queued_locks/swarm/swarm_element/threaded.rbs +61 -0
  105. data/sig/redis_queued_locks/swarm/swarm_element.rbs +8 -0
  106. data/sig/redis_queued_locks/swarm/zombie_info.rbs +24 -0
  107. data/sig/redis_queued_locks/swarm.rbs +41 -0
  108. data/sig/redis_queued_locks/utilities/lock.rbs +10 -0
  109. data/sig/redis_queued_locks/utilities.rbs +11 -0
  110. data/sig/redis_queued_locks/version.rbs +3 -0
  111. data/sig/redis_queued_locks.rbs +14 -0
  112. data/sig/vendor/active_support.rbs +9 -0
  113. data/sig/vendor/redis_client.rbs +39 -0
  114. data/sig/vendor/semantic_logger.rbs +4 -0
  115. metadata +96 -54
  116. data/lib/redis_queued_locks/acquier/acquire_lock/dequeue_from_lock_queue/log_visitor.rb +0 -40
  117. data/lib/redis_queued_locks/acquier/acquire_lock/instr_visitor.rb +0 -166
  118. data/lib/redis_queued_locks/acquier/acquire_lock/log_visitor.rb +0 -216
  119. data/lib/redis_queued_locks/acquier/acquire_lock/try_to_lock/log_visitor.rb +0 -541
  120. data/lib/redis_queued_locks/acquier/acquire_lock/yield_expire/log_visitor.rb +0 -76
  121. data/lib/redis_queued_locks/acquier.rb +0 -18
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since [1.13.0]
5
+ module RedisQueuedLocks::Config::DSL
6
+ # @api private
7
+ # @since [1.13.0]
8
+ module ClassMethods
9
+ # NOTE:
10
+ # 1. Style/DefWithParentheses rubocop's cop incorrectly drops `()` from method definition
11
+ # and breaks ruby code syntax. So this cop is disabled here;
12
+ # 2. attr_reader is not used cuz `steep` can't understand it form inside the class where
13
+ # the current module is mixed;
14
+ #
15
+ # @return [Hash<String,Block>]
16
+ #
17
+ # @api private
18
+ # @since [1.13.0]
19
+ def config_setters()= @config_setters # rubocop:disable Style/DefWithParentheses
20
+
21
+ # NOTE:
22
+ # 1. Style/DefWithParentheses rubocop's cop incorrectly drops `()` from method definition
23
+ # and breaks ruby code syntax. So this cop is disabled here;
24
+ # 2. attr_reader is not used cuz `steep` can't understand it form inside the class where
25
+ # the current module is mixed;
26
+ #
27
+ # @return [Hash<String,Block>]
28
+ #
29
+ # @api private
30
+ # @since [1.13.0]
31
+ def config_validators()= @config_validators # rubocop:disable Style/DefWithParentheses
32
+
33
+ # @param config_key [String]
34
+ # @param validator [Block]
35
+ # @return [Bool]
36
+ #
37
+ # @api private
38
+ # @since [1.13.0]
39
+ def validate(config_key, &validator)
40
+ config_validators[config_key] = validator
41
+ end
42
+
43
+ # @param config_key [String]
44
+ # @param config_value [Any]
45
+ # @return [void]
46
+ #
47
+ # @api private
48
+ # @since [1.13.0]
49
+ def setting(config_key, config_value)
50
+ config_setters[config_key] = proc do |config|
51
+ config[config_key] = config_value
52
+ end
53
+ end
54
+ end
55
+
56
+ module InstanceMethods
57
+ # @return [Hash<String,Blcok>]
58
+ #
59
+ # @api private
60
+ # @since [1.13.0]
61
+ def config_setters
62
+ self.class.config_setters # steep:ignore
63
+ end
64
+
65
+ # @return [Hash<String,Blcok>]
66
+ #
67
+ # @api private
68
+ # @since [1.13.0]
69
+ def config_validators
70
+ self.class.config_validators # steep:ignore
71
+ end
72
+ end
73
+
74
+ class << self
75
+ # @param child_klass [Class]
76
+ # @return [void]
77
+ #
78
+ # @api private
79
+ # @since [1.13.0]
80
+ def included(child_klass)
81
+ child_klass.instance_variable_set(
82
+ :@config_setters,
83
+ {} #: RedisQueuedLocks::Config::DSL::configSetters
84
+ )
85
+ child_klass.instance_variable_set(
86
+ :@config_validators,
87
+ {} #: RedisQueuedLocks::Config::DSL::configValidators
88
+ )
89
+ child_klass.extend(ClassMethods)
90
+ child_klass.include(InstanceMethods)
91
+ super
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,231 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since [1.13.0]
5
+ # rubocop:disable Metrics/ClassLength
6
+ class RedisQueuedLocks::Config
7
+ require_relative 'config/dsl'
8
+
9
+ # @api private
10
+ # @since [1.13.0]
11
+ include DSL
12
+
13
+ setting('retry_count', 3)
14
+ setting('retry_delay', 200) # NOTE: in milliseconds)
15
+ setting('retry_jitter', 25) # NOTE: in milliseconds)
16
+ setting('try_to_lock_timeout', 10) # NOTE: in seconds)
17
+ setting('default_lock_ttl', 5_000) # NOTE: in milliseconds)
18
+ setting('default_queue_ttl', 15) # NOTE: in seconds)
19
+ setting('detailed_acq_timeout_error', false)
20
+ setting('lock_release_batch_size', 100)
21
+ setting('key_extraction_batch_size', 500)
22
+ setting('instrumenter', RedisQueuedLocks::Instrument::VoidNotifier)
23
+ setting('uniq_identifier', -> { RedisQueuedLocks::Resource.calc_uniq_identity })
24
+ setting('logger', RedisQueuedLocks::Logging::VoidLogger)
25
+ setting('log_lock_try', false)
26
+ setting('dead_request_ttl', 1 * 24 * 60 * 60 * 1000) # NOTE: 1 day in milliseconds)
27
+ setting('is_timed_by_default', false)
28
+ setting('default_conflict_strategy', :wait_for_lock)
29
+ setting('default_access_strategy', :queued)
30
+ setting('log_sampling_enabled', false)
31
+ setting('log_sampling_percent', 15)
32
+ setting('log_sampler', RedisQueuedLocks::Logging::Sampler)
33
+ setting('instr_sampling_enabled', false)
34
+ setting('instr_sampling_percent', 15)
35
+ setting('instr_sampler', RedisQueuedLocks::Instrument::Sampler)
36
+ setting('swarm.auto_swarm', false)
37
+ setting('swarm.supervisor.liveness_probing_period', 2) # NOTE: in seconds)
38
+ setting('swarm.probe_hosts.enabled_for_swarm', true)
39
+ setting('swarm.probe_hosts.probe_period', 2) # NOTE: in seconds)
40
+ setting('swarm.probe_hosts.redis_config.sentinel', false)
41
+ setting('swarm.probe_hosts.redis_config.pooled', false)
42
+ setting('swarm.probe_hosts.redis_config.config', {})
43
+ setting('swarm.probe_hosts.redis_config.pool_config', {})
44
+ setting('swarm.flush_zombies.enabled_for_swarm', true)
45
+ setting('swarm.flush_zombies.zombie_ttl', 15_000) # NOTE: in milliseconds)
46
+ setting('swarm.flush_zombies.zombie_lock_scan_size', 500)
47
+ setting('swarm.flush_zombies.zombie_queue_scan_size', 500)
48
+ setting('swarm.flush_zombies.zombie_flush_period', 10)
49
+ setting('swarm.flush_zombies.redis_config.sentinel', false)
50
+ setting('swarm.flush_zombies.redis_config.pooled', false)
51
+ setting('swarm.flush_zombies.redis_config.config', {})
52
+ setting('swarm.flush_zombies.redis_config.pool_config', {})
53
+
54
+ validate('swarm.auto_swarm') { |val| val == true || val == false }
55
+ validate('swarm.supervisor.liveness_probing_period') { |val| val.is_a?(Integer) }
56
+
57
+ validate('swarm.probe_hosts.enabled_for_swarm') { |val| val == true || val == false }
58
+ validate('swarm.probe_hosts.redis_config.sentinel') { |val| val == true || val == false }
59
+ validate('swarm.probe_hosts.redis_config.pooled') { |val| val == true || val == false }
60
+ validate('swarm.probe_hosts.redis_config.config') { |val| val.is_a?(Hash) }
61
+ validate('swarm.probe_hosts.redis_config.pool_config') { |val| val.is_a?(Hash) }
62
+ validate('swarm.probe_hosts.probe_period') { |val| val.is_a?(Integer) }
63
+
64
+ validate('swarm.flush_zombies.enabled_for_swarm') { |val| val == true || val == false }
65
+ validate('swarm.flush_zombies.redis_config.sentinel') { |val| val == true || val == false }
66
+ validate('swarm.flush_zombies.redis_config.pooled') { |val| val == true || val == false }
67
+ validate('swarm.flush_zombies.redis_config.config') { |val| val.is_a?(Hash) }
68
+ validate('swarm.flush_zombies.redis_config.pool_config') { |val| val.is_a?(Hash) }
69
+ validate('swarm.flush_zombies.zombie_ttl') { |val| val.is_a?(Integer) }
70
+ validate('swarm.flush_zombies.zombie_lock_scan_size') { |val| val.is_a?(Integer) }
71
+ validate('swarm.flush_zombies.zombie_queue_scan_size') { |val| val.is_a?(Integer) }
72
+ validate('swarm.flush_zombies.zombie_flush_period') { |val| val.is_a?(Integer) }
73
+
74
+ validate('retry_count') { |val| val == nil || (val.is_a?(Integer) && val >= 0) }
75
+ validate('retry_delay') { |val| val.is_a?(Integer) && val >= 0 }
76
+ validate('retry_jitter') { |val| val.is_a?(Integer) && val >= 0 }
77
+ validate('try_to_lock_timeout') { |val| val == nil || (val.is_a?(Integer) && val >= 0) }
78
+ validate('default_lock_tt') { |val| val.is_a?(Integer) }
79
+ validate('default_queue_ttl') { |val| val.is_a?(Integer) }
80
+ validate('detailed_acq_timeout_error') { |val| val == true || val == false }
81
+ validate('lock_release_batch_size') { |val| val.is_a?(Integer) }
82
+ validate('instrumenter') { |val| RedisQueuedLocks::Instrument.valid_interface?(val) }
83
+ validate('uniq_identifier') { |val| val.is_a?(Proc) }
84
+ validate('logger') { |val| RedisQueuedLocks::Logging.valid_interface?(val) }
85
+ validate('log_lock_try') { |val| val == true || val == false }
86
+ validate('dead_request_ttl') { |val| val.is_a?(Integer) && val > 0 }
87
+ validate('is_timed_by_default') { |val| val == true || val == false }
88
+ validate('log_sampler') { |val| RedisQueuedLocks::Logging.valid_sampler?(val) }
89
+ validate('log_sampling_enabled') { |val| val == true || val == false }
90
+ validate('log_sampling_percent') { |val| val.is_a?(Integer) && val >= 0 && val <= 100 }
91
+ validate('instr_sampling_enabled') { |val| val == true || val == false }
92
+ validate('instr_sampling_percent') { |val| val.is_a?(Integer) && val >= 0 && val <= 100 }
93
+ validate('instr_sampler') { |val| RedisQueuedLocks::Instrument.valid_sampler?(val) }
94
+ validate('default_conflict_strategy') do |val|
95
+ # rubocop:disable Layout/MultilineOperationIndentation
96
+ val == :work_through ||
97
+ val == :extendable_work_through ||
98
+ val == :wait_for_lock ||
99
+ val == :dead_locking
100
+ # rubocop:enable Layout/MultilineOperationIndentation
101
+ end
102
+ validate('default_access_strategy') do |val|
103
+ # rubocop:disable Layout/MultilineOperationIndentation
104
+ val == :queued ||
105
+ val == :random
106
+ # rubocop:enable Layout/MultilineOperationIndentation
107
+ end
108
+
109
+ # @return [Hash<Symbol,Any>]
110
+ #
111
+ # @api private
112
+ # @since [1.13.0]
113
+ attr_reader :config_state
114
+
115
+ # @return [void]
116
+ #
117
+ # @api private
118
+ # @since [1.13.0]
119
+ def initialize(&configuration)
120
+ @config_state = {}
121
+ config_setters.each_value { |setter| setter.call(@config_state) }
122
+ configure(&configuration)
123
+ end
124
+
125
+ # @param configuration [Block]
126
+ # @yield [?]
127
+ # @yieldparam [?]
128
+ # @return [void]
129
+ #
130
+ # @api private
131
+ # @since [1.13.0]
132
+ def configure(&configuration)
133
+ yield(self) if block_given?
134
+ end
135
+
136
+ # @param config_key [String]
137
+ # @return [Any]
138
+ #
139
+ # @raise [RedisQueuedLocks::ConfigNotFoundError]
140
+ #
141
+ # @api public
142
+ # @since [1.13.0]
143
+ def [](config_key)
144
+ prevent_key__non_existent(config_key)
145
+ config_state[config_key]
146
+ end
147
+
148
+ # @param config_key [String]
149
+ # @param config_value [Any]
150
+ # @return [void]
151
+ #
152
+ # @raise [RedisQueuedLocks::ConfigNotFoundError]
153
+ # @raise [RedisQueuedLocks::ConfigValidationError]
154
+ #
155
+ # @api public
156
+ # @since [1.13.0]
157
+ def []=(config_key, config_value)
158
+ prevent_key__non_existent(config_key)
159
+ prevent_key__invalid_type(config_key, config_value)
160
+ config_state[config_key] = config_value
161
+ end
162
+
163
+ # Returns the slice of the config values as a `hash` match the received pattern.
164
+ # Matched configs will be sliced as a nested config (as a hash object). And config valuess
165
+ # will be duplicated via `Object#dup`. How it works:
166
+ # initial config sate: => {
167
+ # 'swarm.flush_zombies.redis_config.pooled' => true,
168
+ # 'swarm.flush_zombies.redis_config.sentinel' => true,
169
+ # 'swarm.aut_swarm' => false,
170
+ # 'logger' => Logger.new
171
+ # }
172
+ # slice with "swarm.flush_zombies.redis_config" pattern: => {
173
+ # 'pooled' => true,
174
+ # 'sentinel' => true
175
+ # }
176
+ #
177
+ # @param config_key_pattern [String]
178
+ # @return [Hash<String,Any>]
179
+ #
180
+ # @api public
181
+ # @since [1.13.0]
182
+ def slice(config_key_pattern)
183
+ key_selector = "#{config_key_pattern}."
184
+ key_splitter = key_selector.size
185
+ sliced_config = {} #: Hash[String,untyped]
186
+
187
+ config_state.each_pair do |config_key, config_value|
188
+ next unless config_key.start_with?(key_selector)
189
+ sliced_config_key = config_key[key_splitter..] #: String
190
+ sliced_config[sliced_config_key] = config_value.dup
191
+ end
192
+
193
+ sliced_config
194
+ end
195
+
196
+ private
197
+
198
+ # @param config_key [String]
199
+ # @return [void]
200
+ #
201
+ # @raise [RedisQueuedLocks::ConfigNotFoundError]
202
+ #
203
+ # @api private
204
+ # @since [1.13.0]
205
+ def prevent_key__non_existent(config_key)
206
+ unless config_state.key?(config_key)
207
+ raise(
208
+ RedisQueuedLocks::ConfigNotFoundError,
209
+ "Config with '#{config_key}' key does not exist."
210
+ )
211
+ end
212
+ end
213
+
214
+ # @param config_key [String]
215
+ # @param config_value [Any]
216
+ # @return [void]
217
+ #
218
+ # @raise [RedisQueuedLocks::ConfigValidationError]
219
+ #
220
+ # @api private
221
+ # @sicne [1.13.0]
222
+ def prevent_key__invalid_type(config_key, config_value)
223
+ unless config_validators[config_key].call(config_value)
224
+ raise(
225
+ RedisQueuedLocks::ConfigValidationError,
226
+ "Trying to assing an invalid value to the '#{config_key}' config key."
227
+ )
228
+ end
229
+ end
230
+ end
231
+ # rubocop:enable Metrics/ClassLength
@@ -1,4 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # @api private
4
+ # @since 0.0.18
3
5
  class RedisQueuedLocks::Data < Hash
4
6
  end
@@ -1,47 +1,63 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # NOTE:
4
+ # the one-line definition style (like "Error = Class.new(::StandardError)")
5
+ # is not used cuz that style can not be correctly defined via RBS types: we can not
6
+ # identify the superclass of our class for a constant;
3
7
  module RedisQueuedLocks
4
8
  # @api public
5
9
  # @since 1.0.0
6
- Error = Class.new(::StandardError)
10
+ class Error < ::StandardError; end
7
11
 
8
12
  # @api public
9
13
  # @since 1.0.0
10
- ArgumentError = Class.new(::ArgumentError)
14
+ class ArgumentError < ::ArgumentError; end
11
15
 
12
16
  # @api public
13
17
  # @since 1.0.0
14
- LockAlreadyObtainedError = Class.new(Error)
18
+ class LockAlreadyObtainedError < Error; end
15
19
 
16
20
  # @api private
17
21
  # @since 1.11.0
18
- LockAcquiermentIntermediateTimeoutError = Class.new(::Timeout::Error)
22
+ class LockAcquirementIntermediateTimeoutError < ::Timeout::Error; end
19
23
 
20
24
  # @api public
21
25
  # @since 1.0.0
22
- LockAcquiermentTimeoutError = Class.new(Error)
26
+ class LockAcquirementTimeoutError < Error; end
23
27
 
24
28
  # @api public
25
29
  # @since 1.0.0
26
- LockAcquiermentRetryLimitError = Class.new(Error)
30
+ class LockAcquirementRetryLimitError < Error; end
27
31
 
28
32
  # @api private
29
33
  # @since 1.12.0
30
- TimedLockIntermediateTimeoutError = Class.new(::Timeout::Error)
34
+ class TimedLockIntermediateTimeoutError < ::Timeout::Error; end
31
35
 
32
36
  # @api pulic
33
37
  # @since 1.0.0
34
- TimedLockTimeoutError = Class.new(Error)
38
+ class TimedLockTimeoutError < Error; end
35
39
 
36
40
  # @api public
37
41
  # @since 1.3.0
38
- ConflictLockObtainError = Class.new(Error)
42
+ class ConflictLockObtainError < Error; end
39
43
 
40
44
  # @api public
41
45
  # @since 1.9.0
42
- SwarmError = Class.new(Error)
46
+ class SwarmError < Error; end
43
47
 
44
48
  # @api public
45
49
  # @since 1.9.0
46
- SwarmArgumentError = Class.new(ArgumentError)
50
+ class SwarmArgumentError < ArgumentError; end
51
+
52
+ # @api public
53
+ # @since [1.13.0]
54
+ class ConfigError < Error; end
55
+
56
+ # @api public
57
+ # @since [1.13.0]
58
+ class ConfigNotFoundError < ConfigError; end
59
+
60
+ # @api pub;ic
61
+ # @since [1.13.0]
62
+ class ConfigValidationError < ConfigError; end
47
63
  end
@@ -36,6 +36,7 @@ module RedisQueuedLocks::Instrument
36
36
  def valid_sampler?(sampler)
37
37
  return false unless sampler.respond_to?(:sampling_happened?)
38
38
 
39
+ # @type var m_obj: Method
39
40
  m_obj = sampler.method(:sampling_happened?)
40
41
  m_sig = m_obj.parameters
41
42
 
@@ -45,12 +46,17 @@ module RedisQueuedLocks::Instrument
45
46
  # => [[:opt, :sampling_percent]]
46
47
  # => [[:req, :sampling_percent], [:block, :block]]
47
48
  # => [[:opt, :sampling_percent], [:block, :block]]
48
- if m_sig.size == 1
49
+ case m_sig.size
50
+ when 1
51
+ # => [[:req, :sampling_percent]]
52
+ # => [[:opt, :sampling_percent]]
49
53
  prm = m_sig[0][0]
50
54
  prm == :req || prm == :opt
51
- elsif m_sig.size == 2
55
+ when 2
56
+ # => [[:req, :sampling_percent], [:block, :block]]
57
+ # => [[:opt, :sampling_percent], [:block, :block]]
52
58
  f_prm = m_sig[0][0]
53
- s_prm = m_sign[1][0]
59
+ s_prm = m_sig[1][0]
54
60
 
55
61
  # rubocop:disable Layout/MultilineOperationIndentation
56
62
  f_prm == :req && s_prm == :block ||
@@ -69,13 +75,14 @@ module RedisQueuedLocks::Instrument
69
75
  def valid_interface?(instrumenter)
70
76
  if instrumenter == RedisQueuedLocks::Instrument::ActiveSupport
71
77
  # NOTE: active_support should be required in your app
72
- defined?(::ActiveSupport::Notifications)
78
+ !!defined?(::ActiveSupport::Notifications)
73
79
  elsif instrumenter.respond_to?(:notify)
74
80
  # NOTE: the method signature should be (event, payload). Supported variants:
75
81
  # => [[:req, :event], [:req, :payload]]
76
82
  # => [[:req, :event], [:opt, :payload]]
77
83
  # => [[:opt, :event], [:opt, :payload]]
78
84
 
85
+ # @type var m_obj: Method
79
86
  m_obj = instrumenter.method(:notify)
80
87
  m_sig = m_obj.parameters
81
88
 
@@ -4,38 +4,75 @@
4
4
  # @since 1.0.0
5
5
  module RedisQueuedLocks::Logging::VoidLogger
6
6
  class << self
7
+ # @param progname [Any]
8
+ # @parma block [Block]
9
+ # @return [void]
10
+ #
7
11
  # @api public
8
12
  # @since 1.0.0
9
13
  def warn(progname = nil, &block); end
10
14
 
15
+ # @param progname [Any]
16
+ # @parma block [Block]
17
+ # @return [void]
18
+ #
11
19
  # @api public
12
20
  # @since 1.0.0
13
21
  def unknown(progname = nil, &block); end
14
22
 
23
+ # @param progname [Any]
24
+ # @parma block [Block]
25
+ # @return [void]
26
+ #
15
27
  # @api public
16
28
  # @since 1.0.0
17
29
  def log(progname = nil, &block); end
18
30
 
31
+ # @param progname [Any]
32
+ # @parma block [Block]
33
+ # @return [void]
34
+ #
19
35
  # @api public
20
36
  # @since 1.0.0
21
37
  def info(progname = nil, &block); end
22
38
 
39
+ # @param progname [Any]
40
+ # @parma block [Block]
41
+ # @return [void]
42
+ #
23
43
  # @api public
24
44
  # @since 1.0.0
25
45
  def error(progname = nil, &block); end
26
46
 
47
+ # @param progname [Any]
48
+ # @parma block [Block]
49
+ # @return [void]
50
+ #
27
51
  # @api public
28
52
  # @since 1.0.0
29
53
  def fatal(progname = nil, &block); end
30
54
 
55
+ # @param progname [Any]
56
+ # @parma block [Block]
57
+ # @return [void]
58
+ #
31
59
  # @api public
32
60
  # @since 1.0.0
33
61
  def debug(progname = nil, &block); end
34
62
 
63
+ # @param severity [Any]
64
+ # @param message [Any]
65
+ # @param progname [Any]
66
+ # @param block [Block]
67
+ # @return [void]
68
+ #
35
69
  # @api public
36
70
  # @since 1.0.0
37
- def add(*, &block); end
71
+ def add(severity = nil, message = nil, progname = nil, &block); end
38
72
 
73
+ # @param message [Any]
74
+ # @retorun [void]
75
+ #
39
76
  # @api public
40
77
  # @since 1.0.0
41
78
  def <<(message); end
@@ -49,7 +49,7 @@ module RedisQueuedLocks::Logging
49
49
  prm == :req || prm == :opt
50
50
  elsif m_sig.size == 2
51
51
  f_prm = m_sig[0][0]
52
- s_prm = m_sign[1][0]
52
+ s_prm = m_sig[1][0]
53
53
 
54
54
  # rubocop:disable Layout/MultilineOperationIndentation
55
55
  f_prm == :req && s_prm == :block ||
@@ -71,9 +71,14 @@ module RedisQueuedLocks::Logging
71
71
 
72
72
  # NOTE:
73
73
  # - convinient/conventional way to support the popular `semantic_logger` library
74
- # - see https://logger.rocketjob.io/
75
- # - see https://github.com/reidmorrison/semantic_logger
74
+ # - see https://logger.rocketjob.io/
75
+ # - see https://github.com/reidmorrison/semantic_logger
76
+ # - convinient/conventional way to support the popular `broadcast` RubyOnRails's logger;
77
+ # - see https://api.rubyonrails.org/classes/ActiveSupport/BroadcastLogger.html
78
+ # rubocop:disable Layout/LineLength
76
79
  return true if defined?(::SemanticLogger::Logger) && logger.is_a?(::SemanticLogger::Logger)
80
+ return true if defined?(::ActiveSupport::BroadcastLogger) && logger.is_a?(::ActiveSupport::BroadcastLogger)
81
+ # rubocop:enable Layout/LineLength
77
82
 
78
83
  # NOTE: should provide `#debug` method.
79
84
  return false unless logger.respond_to?(:debug)
@@ -87,11 +92,14 @@ module RedisQueuedLocks::Logging
87
92
  # => [[:req, :progname]]
88
93
  # => [[:rest], [:block, :block]]
89
94
  # => [[:rest]]
95
+ # => ((...) method signature): [[:rest, :*], [:keyrest, :**], [:block, :&]]
90
96
 
97
+ # @type var m_obj: Method
91
98
  m_obj = logger.method(:debug)
92
99
  m_sig = m_obj.parameters
93
100
 
94
- if m_sig.size == 2
101
+ case m_sig.size
102
+ when 2
95
103
  # => [[:opt, :progname], [:block, :block]]
96
104
  # => [[:req, :progname], [:block, :block]]
97
105
  # => [[:rest], [:block, :block]]
@@ -103,13 +111,20 @@ module RedisQueuedLocks::Logging
103
111
  f_prm == :req && s_prm == :block ||
104
112
  f_prm == :rest && s_prm == :block
105
113
  # rubocop:enable Layout/MultilineOperationIndentation
106
- elsif m_sig.size == 1
114
+ when 1
107
115
  # => [[:opt, :progname]]
108
116
  # => [[:req, :progname]]
109
117
  # => [[:rest]]
110
118
  prm = m_sig[0][0]
111
119
 
112
120
  prm == :opt || prm == :req || prm == :rest
121
+ when 3
122
+ # => [[:rest, :*], [:keyrest, :**], [:block, :&]]
123
+ f_prm = m_sig[0][0]
124
+ s_prm = m_sig[1][0]
125
+ t_prm = m_sig[2][0]
126
+
127
+ f_prm == :rest && s_prm == :keyrest && t_prm == :block
113
128
  else
114
129
  false
115
130
  end