redis_queued_locks 1.12.1 → 1.14.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 (122) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -1
  3. data/.ruby-version +1 -1
  4. data/CHANGELOG.md +45 -5
  5. data/LICENSE.txt +1 -1
  6. data/README.md +574 -296
  7. data/Rakefile +12 -4
  8. data/Steepfile +15 -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 -9
  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 +42 -19
  21. data/lib/redis_queued_locks/{acquier → acquirer}/acquire_lock.rb +74 -47
  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 +26 -21
  32. data/lib/redis_queued_locks/{acquier → acquirer}/release_lock.rb +28 -22
  33. data/lib/redis_queued_locks/acquirer/release_locks_of.rb +211 -0
  34. data/lib/redis_queued_locks/acquirer.rb +19 -0
  35. data/lib/redis_queued_locks/client.rb +317 -254
  36. data/lib/redis_queued_locks/config/dsl.rb +94 -0
  37. data/lib/redis_queued_locks/config.rb +236 -0
  38. data/lib/redis_queued_locks/data.rb +2 -0
  39. data/lib/redis_queued_locks/errors.rb +27 -11
  40. data/lib/redis_queued_locks/instrument.rb +11 -4
  41. data/lib/redis_queued_locks/logging/void_logger.rb +38 -1
  42. data/lib/redis_queued_locks/logging.rb +20 -5
  43. data/lib/redis_queued_locks/resource.rb +49 -11
  44. data/lib/redis_queued_locks/swarm/acquirers.rb +17 -16
  45. data/lib/redis_queued_locks/swarm/flush_zombies.rb +26 -25
  46. data/lib/redis_queued_locks/swarm/probe_hosts.rb +20 -19
  47. data/lib/redis_queued_locks/swarm/redis_client_builder.rb +3 -3
  48. data/lib/redis_queued_locks/swarm/supervisor.rb +19 -6
  49. data/lib/redis_queued_locks/swarm/swarm_element/isolated.rb +20 -18
  50. data/lib/redis_queued_locks/swarm/swarm_element/threaded.rb +35 -27
  51. data/lib/redis_queued_locks/swarm/zombie_info.rb +9 -9
  52. data/lib/redis_queued_locks/swarm.rb +20 -41
  53. data/lib/redis_queued_locks/utilities.rb +11 -2
  54. data/lib/redis_queued_locks/version.rb +2 -2
  55. data/lib/redis_queued_locks.rb +2 -3
  56. data/rbs_collection.lock.yaml +28 -0
  57. data/rbs_collection.yaml +17 -0
  58. data/redis_queued_locks.gemspec +22 -23
  59. data/sig/manifest.yml +6 -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 +52 -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/acquirer/release_locks_of.rbs +46 -0
  84. data/sig/redis_queued_locks/client.rbs +235 -0
  85. data/sig/redis_queued_locks/config/dsl.rbs +26 -0
  86. data/sig/redis_queued_locks/config.rbs +23 -0
  87. data/sig/redis_queued_locks/data.rbs +4 -0
  88. data/sig/redis_queued_locks/debugger/interface.rbs +9 -0
  89. data/sig/redis_queued_locks/debugger.rbs +13 -0
  90. data/sig/redis_queued_locks/errors.rbs +43 -0
  91. data/sig/redis_queued_locks/instrument/active_support.rbs +7 -0
  92. data/sig/redis_queued_locks/instrument/sampler.rbs +9 -0
  93. data/sig/redis_queued_locks/instrument/void_notifier.rbs +7 -0
  94. data/sig/redis_queued_locks/instrument.rbs +15 -0
  95. data/sig/redis_queued_locks/logging/sampler.rbs +9 -0
  96. data/sig/redis_queued_locks/logging/void_logger.rbs +15 -0
  97. data/sig/redis_queued_locks/logging.rbs +15 -0
  98. data/sig/redis_queued_locks/resource.rbs +42 -0
  99. data/sig/redis_queued_locks/swarm/acquirers.rbs +10 -0
  100. data/sig/redis_queued_locks/swarm/flush_zombies.rbs +13 -0
  101. data/sig/redis_queued_locks/swarm/probe_hosts.rbs +13 -0
  102. data/sig/redis_queued_locks/swarm/redis_client_builder.rbs +19 -0
  103. data/sig/redis_queued_locks/swarm/supervisor.rbs +26 -0
  104. data/sig/redis_queued_locks/swarm/swarm_element/isolated.rbs +52 -0
  105. data/sig/redis_queued_locks/swarm/swarm_element/threaded.rbs +61 -0
  106. data/sig/redis_queued_locks/swarm/swarm_element.rbs +8 -0
  107. data/sig/redis_queued_locks/swarm/zombie_info.rbs +24 -0
  108. data/sig/redis_queued_locks/swarm.rbs +41 -0
  109. data/sig/redis_queued_locks/utilities/lock.rbs +10 -0
  110. data/sig/redis_queued_locks/utilities.rbs +12 -0
  111. data/sig/redis_queued_locks/version.rbs +3 -0
  112. data/sig/redis_queued_locks.rbs +14 -0
  113. data/sig/vendor/active_support.rbs +9 -0
  114. data/sig/vendor/redis_client.rbs +39 -0
  115. data/sig/vendor/semantic_logger.rbs +4 -0
  116. metadata +98 -54
  117. data/lib/redis_queued_locks/acquier/acquire_lock/dequeue_from_lock_queue/log_visitor.rb +0 -40
  118. data/lib/redis_queued_locks/acquier/acquire_lock/instr_visitor.rb +0 -166
  119. data/lib/redis_queued_locks/acquier/acquire_lock/log_visitor.rb +0 -216
  120. data/lib/redis_queued_locks/acquier/acquire_lock/try_to_lock/log_visitor.rb +0 -541
  121. data/lib/redis_queued_locks/acquier/acquire_lock/yield_expire/log_visitor.rb +0 -76
  122. 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,236 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 1.13.0
5
+ # @version 1.14.0
6
+ # rubocop:disable Metrics/ClassLength
7
+ class RedisQueuedLocks::Config
8
+ require_relative 'config/dsl'
9
+
10
+ # @api private
11
+ # @since 1.13.0
12
+ include DSL
13
+
14
+ setting('retry_count', 3)
15
+ setting('retry_delay', 200) # NOTE: in milliseconds)
16
+ setting('retry_jitter', 25) # NOTE: in milliseconds)
17
+ setting('try_to_lock_timeout', 10) # NOTE: in seconds)
18
+ setting('default_lock_ttl', 5_000) # NOTE: in milliseconds)
19
+ setting('default_queue_ttl', 15) # NOTE: in seconds)
20
+ setting('detailed_acq_timeout_error', false)
21
+ setting('lock_release_batch_size', 100)
22
+ setting('clear_locks_of__lock_scan_size', 300)
23
+ setting('clear_locks_of__queue_scan_size', 300)
24
+ setting('key_extraction_batch_size', 500)
25
+ setting('instrumenter', RedisQueuedLocks::Instrument::VoidNotifier)
26
+ setting('uniq_identifier', -> { RedisQueuedLocks::Resource.calc_uniq_identity })
27
+ setting('logger', RedisQueuedLocks::Logging::VoidLogger)
28
+ setting('log_lock_try', false)
29
+ setting('dead_request_ttl', 1 * 24 * 60 * 60 * 1000) # NOTE: 1 day in milliseconds)
30
+ setting('is_timed_by_default', false)
31
+ setting('default_conflict_strategy', :wait_for_lock)
32
+ setting('default_access_strategy', :queued)
33
+ setting('log_sampling_enabled', false)
34
+ setting('log_sampling_percent', 15)
35
+ setting('log_sampler', RedisQueuedLocks::Logging::Sampler)
36
+ setting('instr_sampling_enabled', false)
37
+ setting('instr_sampling_percent', 15)
38
+ setting('instr_sampler', RedisQueuedLocks::Instrument::Sampler)
39
+ setting('swarm.auto_swarm', false)
40
+ setting('swarm.supervisor.liveness_probing_period', 2) # NOTE: in seconds)
41
+ setting('swarm.probe_hosts.enabled_for_swarm', true)
42
+ setting('swarm.probe_hosts.probe_period', 2) # NOTE: in seconds)
43
+ setting('swarm.probe_hosts.redis_config.sentinel', false)
44
+ setting('swarm.probe_hosts.redis_config.pooled', false)
45
+ setting('swarm.probe_hosts.redis_config.config', {})
46
+ setting('swarm.probe_hosts.redis_config.pool_config', {})
47
+ setting('swarm.flush_zombies.enabled_for_swarm', true)
48
+ setting('swarm.flush_zombies.zombie_ttl', 15_000) # NOTE: in milliseconds)
49
+ setting('swarm.flush_zombies.zombie_lock_scan_size', 500)
50
+ setting('swarm.flush_zombies.zombie_queue_scan_size', 500)
51
+ setting('swarm.flush_zombies.zombie_flush_period', 10)
52
+ setting('swarm.flush_zombies.redis_config.sentinel', false)
53
+ setting('swarm.flush_zombies.redis_config.pooled', false)
54
+ setting('swarm.flush_zombies.redis_config.config', {})
55
+ setting('swarm.flush_zombies.redis_config.pool_config', {})
56
+
57
+ validate('swarm.auto_swarm') { |val| val == true || val == false }
58
+ validate('swarm.supervisor.liveness_probing_period') { |val| val.is_a?(Integer) }
59
+
60
+ validate('swarm.probe_hosts.enabled_for_swarm') { |val| val == true || val == false }
61
+ validate('swarm.probe_hosts.redis_config.sentinel') { |val| val == true || val == false }
62
+ validate('swarm.probe_hosts.redis_config.pooled') { |val| val == true || val == false }
63
+ validate('swarm.probe_hosts.redis_config.config') { |val| val.is_a?(Hash) }
64
+ validate('swarm.probe_hosts.redis_config.pool_config') { |val| val.is_a?(Hash) }
65
+ validate('swarm.probe_hosts.probe_period') { |val| val.is_a?(Integer) }
66
+
67
+ validate('swarm.flush_zombies.enabled_for_swarm') { |val| val == true || val == false }
68
+ validate('swarm.flush_zombies.redis_config.sentinel') { |val| val == true || val == false }
69
+ validate('swarm.flush_zombies.redis_config.pooled') { |val| val == true || val == false }
70
+ validate('swarm.flush_zombies.redis_config.config') { |val| val.is_a?(Hash) }
71
+ validate('swarm.flush_zombies.redis_config.pool_config') { |val| val.is_a?(Hash) }
72
+ validate('swarm.flush_zombies.zombie_ttl') { |val| val.is_a?(Integer) }
73
+ validate('swarm.flush_zombies.zombie_lock_scan_size') { |val| val.is_a?(Integer) }
74
+ validate('swarm.flush_zombies.zombie_queue_scan_size') { |val| val.is_a?(Integer) }
75
+ validate('swarm.flush_zombies.zombie_flush_period') { |val| val.is_a?(Integer) }
76
+
77
+ validate('retry_count') { |val| val == nil || (val.is_a?(Integer) && val >= 0) }
78
+ validate('retry_delay') { |val| val.is_a?(Integer) && val >= 0 }
79
+ validate('retry_jitter') { |val| val.is_a?(Integer) && val >= 0 }
80
+ validate('try_to_lock_timeout') { |val| val == nil || (val.is_a?(Integer) && val >= 0) }
81
+ validate('default_lock_tt') { |val| val.is_a?(Integer) }
82
+ validate('default_queue_ttl') { |val| val.is_a?(Integer) }
83
+ validate('detailed_acq_timeout_error') { |val| val == true || val == false }
84
+ validate('lock_release_batch_size') { |val| val.is_a?(Integer) }
85
+ validate('clear_locks_of__lock_scan_size') { |val| val.is_a?(Integer) }
86
+ validate('clear_locks_of__queue_scan_size') { |val| val.is_a?(Integer) }
87
+ validate('instrumenter') { |val| RedisQueuedLocks::Instrument.valid_interface?(val) }
88
+ validate('uniq_identifier') { |val| val.is_a?(Proc) }
89
+ validate('logger') { |val| RedisQueuedLocks::Logging.valid_interface?(val) }
90
+ validate('log_lock_try') { |val| val == true || val == false }
91
+ validate('dead_request_ttl') { |val| val.is_a?(Integer) && val > 0 }
92
+ validate('is_timed_by_default') { |val| val == true || val == false }
93
+ validate('log_sampler') { |val| RedisQueuedLocks::Logging.valid_sampler?(val) }
94
+ validate('log_sampling_enabled') { |val| val == true || val == false }
95
+ validate('log_sampling_percent') { |val| val.is_a?(Integer) && val >= 0 && val <= 100 }
96
+ validate('instr_sampling_enabled') { |val| val == true || val == false }
97
+ validate('instr_sampling_percent') { |val| val.is_a?(Integer) && val >= 0 && val <= 100 }
98
+ validate('instr_sampler') { |val| RedisQueuedLocks::Instrument.valid_sampler?(val) }
99
+ validate('default_conflict_strategy') do |val|
100
+ # rubocop:disable Layout/MultilineOperationIndentation
101
+ val == :work_through ||
102
+ val == :extendable_work_through ||
103
+ val == :wait_for_lock ||
104
+ val == :dead_locking
105
+ # rubocop:enable Layout/MultilineOperationIndentation
106
+ end
107
+ validate('default_access_strategy') do |val|
108
+ # rubocop:disable Layout/MultilineOperationIndentation
109
+ val == :queued ||
110
+ val == :random
111
+ # rubocop:enable Layout/MultilineOperationIndentation
112
+ end
113
+
114
+ # @return [Hash<Symbol,Any>]
115
+ #
116
+ # @api private
117
+ # @since 1.13.0
118
+ attr_reader :config_state
119
+
120
+ # @return [void]
121
+ #
122
+ # @api private
123
+ # @since 1.13.0
124
+ def initialize(&configuration)
125
+ @config_state = {}
126
+ config_setters.each_value { |setter| setter.call(@config_state) }
127
+ configure(&configuration)
128
+ end
129
+
130
+ # @param configuration [Block]
131
+ # @yield [?]
132
+ # @yieldparam [?]
133
+ # @return [void]
134
+ #
135
+ # @api private
136
+ # @since 1.13.0
137
+ def configure(&configuration)
138
+ yield(self) if block_given?
139
+ end
140
+
141
+ # @param config_key [String]
142
+ # @return [Any]
143
+ #
144
+ # @raise [RedisQueuedLocks::ConfigNotFoundError]
145
+ #
146
+ # @api public
147
+ # @since 1.13.0
148
+ def [](config_key)
149
+ prevent_key__non_existent(config_key)
150
+ config_state[config_key]
151
+ end
152
+
153
+ # @param config_key [String]
154
+ # @param config_value [Any]
155
+ # @return [void]
156
+ #
157
+ # @raise [RedisQueuedLocks::ConfigNotFoundError]
158
+ # @raise [RedisQueuedLocks::ConfigValidationError]
159
+ #
160
+ # @api public
161
+ # @since 1.13.0
162
+ def []=(config_key, config_value)
163
+ prevent_key__non_existent(config_key)
164
+ prevent_key__invalid_type(config_key, config_value)
165
+ config_state[config_key] = config_value
166
+ end
167
+
168
+ # Returns the slice of the config values as a `hash` match the received pattern.
169
+ # Matched configs will be sliced as a nested config (as a hash object). And config valuess
170
+ # will be duplicated via `Object#dup`. How it works:
171
+ # initial config sate: => {
172
+ # 'swarm.flush_zombies.redis_config.pooled' => true,
173
+ # 'swarm.flush_zombies.redis_config.sentinel' => true,
174
+ # 'swarm.aut_swarm' => false,
175
+ # 'logger' => Logger.new
176
+ # }
177
+ # slice with "swarm.flush_zombies.redis_config" pattern: => {
178
+ # 'pooled' => true,
179
+ # 'sentinel' => true
180
+ # }
181
+ #
182
+ # @param config_key_pattern [String]
183
+ # @return [Hash<String,Any>]
184
+ #
185
+ # @api public
186
+ # @since 1.13.0
187
+ def slice(config_key_pattern)
188
+ key_selector = "#{config_key_pattern}."
189
+ key_splitter = key_selector.size
190
+ sliced_config = {} #: Hash[String,untyped]
191
+
192
+ config_state.each_pair do |config_key, config_value|
193
+ next unless config_key.start_with?(key_selector)
194
+ sliced_config_key = config_key[key_splitter..] #: String
195
+ sliced_config[sliced_config_key] = config_value.dup
196
+ end
197
+
198
+ sliced_config
199
+ end
200
+
201
+ private
202
+
203
+ # @param config_key [String]
204
+ # @return [void]
205
+ #
206
+ # @raise [RedisQueuedLocks::ConfigNotFoundError]
207
+ #
208
+ # @api private
209
+ # @since 1.13.0
210
+ def prevent_key__non_existent(config_key)
211
+ unless config_state.key?(config_key)
212
+ raise(
213
+ RedisQueuedLocks::ConfigNotFoundError,
214
+ "Config with '#{config_key}' key does not exist."
215
+ )
216
+ end
217
+ end
218
+
219
+ # @param config_key [String]
220
+ # @param config_value [Any]
221
+ # @return [void]
222
+ #
223
+ # @raise [RedisQueuedLocks::ConfigValidationError]
224
+ #
225
+ # @api private
226
+ # @since 1.13.0
227
+ def prevent_key__invalid_type(config_key, config_value)
228
+ unless config_validators[config_key].call(config_value)
229
+ raise(
230
+ RedisQueuedLocks::ConfigValidationError,
231
+ "Trying to assing an invalid value to the '#{config_key}' config key."
232
+ )
233
+ end
234
+ end
235
+ end
236
+ # 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