Class: Kaal::Configuration
- Inherits:
-
Object
- Object
- Kaal::Configuration
- Defined in:
- lib/kaal/config/configuration.rb,
sig/kaal/config/configuration.rbs
Overview
Configuration class for Kaal Holds all settings for the scheduler, tick intervals, locks, and more.
Constant Summary collapse
- DEFAULTS =
Default values for all configuration options
{ tick_interval: 5, window_lookback: 120, window_lookahead: 0, lease_ttl: 125, # Must be >= window_lookback + tick_interval (120 + 5 = 125) namespace: 'kaal', backend: nil, backend_config: {}, logger: nil, time_zone: nil, enable_log_dispatch_registry: false, enable_dispatch_recovery: true, recovery_window: 86_400, # 24 hours in seconds recovery_startup_jitter: 5, # max random delay in seconds scheduler_config_path: 'config/kaal-scheduler.yml', scheduler_conflict_policy: :error, scheduler_missing_file_policy: :warn, delayed_job_allowed_class_prefixes: [] }.freeze
Instance Attribute Summary collapse
-
#backend_runtime_context ⇒ Kaal::rbs_any
Returns the value of attribute backend_runtime_context.
Instance Method Summary collapse
- #add_backend_config_error(errors) ⇒ nil, Kaal::rbs_any
- #add_delayed_job_security_warning(warnings) ⇒ nil, Kaal::rbs_any
- #add_lease_ttl_error(errors) ⇒ nil, Kaal::rbs_any
- #add_lease_ttl_window_error(errors) ⇒ nil, Kaal::rbs_any
- #add_namespace_error(errors) ⇒ nil, Kaal::rbs_any
- #add_scheduler_config_path_error(errors) ⇒ nil, Kaal::rbs_any
- #add_scheduler_conflict_policy_error(errors) ⇒ nil, Kaal::rbs_any
- #add_scheduler_missing_file_policy_error(errors) ⇒ nil, Kaal::rbs_any
- #add_tick_interval_error(errors) ⇒ nil, Kaal::rbs_any
- #add_window_lookahead_error(errors) ⇒ nil, Kaal::rbs_any
- #add_window_lookback_error(errors) ⇒ nil, Kaal::rbs_any
- #apply_backend_runtime_context(runtime_context) ⇒ Object
- #handle_known_key(method_name) {|arg0, arg1| ... } ⇒ ::Array[false | nil], ::Array[true | Kaal::rbs_any]
-
#initialize ⇒ Configuration
constructor
Initialize a new Configuration instance with default values.
-
#method_missing(method_name, *args) ⇒ Kaal::rbs_any
Retrieve or assign configuration values by method name.
- #normalize_backend(value) ⇒ Kaal::rbs_any
- #normalize_backend_config ⇒ Kaal::rbs_any
- #normalize_delayed_job_allowed_class_prefixes(value) ⇒ Kaal::rbs_any
- #normalize_value(key, value) ⇒ Kaal::rbs_any
- #rebuild_symbolic_backend_if_needed(key) ⇒ nil, Kaal::rbs_any
-
#respond_to_missing?(method_name, include_private = false) ⇒ Boolean
Advertise supported configuration keys for respond_to?.
- #set_value(key, value) ⇒ Kaal::rbs_any
-
#to_h ⇒ Hash
Get a hash representation of the current configuration.
-
#validate ⇒ Array<String>
Validate configuration without raising.
-
#validate! ⇒ Configuration
Validate the configuration settings.
- #validation_errors ⇒ Kaal::rbs_any
-
#validation_warnings ⇒ Array<String>
Non-fatal configuration warnings.
Constructor Details
#initialize ⇒ Configuration
Initialize a new Configuration instance with default values.
44 45 46 47 48 |
# File 'lib/kaal/config/configuration.rb', line 44 def initialize @values = DEFAULTS.dup @backend_name = nil @backend_runtime_context = nil end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_name, *args) ⇒ Kaal::rbs_any
Retrieve or assign configuration values by method name.
52 53 54 55 56 57 58 59 60 |
# File 'lib/kaal/config/configuration.rb', line 52 def method_missing(method_name, *args) handled, value = handle_known_key(method_name) do |key, setter| setter ? set_value(key, args.first) : @values[key] end return value if handled super end |
Instance Attribute Details
#backend_runtime_context ⇒ Kaal::rbs_any
Returns the value of attribute backend_runtime_context.
19 20 21 |
# File 'sig/kaal/config/configuration.rbs', line 19 def backend_runtime_context @backend_runtime_context end |
Instance Method Details
#add_backend_config_error(errors) ⇒ nil, Kaal::rbs_any
183 184 185 186 187 |
# File 'lib/kaal/config/configuration.rb', line 183 def add_backend_config_error(errors) return if @values[:backend_config].is_a?(Hash) errors << 'backend_config must be a hash' end |
#add_delayed_job_security_warning(warnings) ⇒ nil, Kaal::rbs_any
221 222 223 224 225 226 |
# File 'lib/kaal/config/configuration.rb', line 221 def add_delayed_job_security_warning(warnings) warning = Kaal::Config::DelayedJobSecurityPolicy.warning_for(self) return unless warning warnings << warning end |
#add_lease_ttl_error(errors) ⇒ nil, Kaal::rbs_any
170 171 172 173 174 175 |
# File 'lib/kaal/config/configuration.rb', line 170 def add_lease_ttl_error(errors) value = @values[:lease_ttl] return unless value.to_i <= 0 errors << "lease_ttl must be greater than 0, got: #{value}" end |
#add_lease_ttl_window_error(errors) ⇒ nil, Kaal::rbs_any
189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/kaal/config/configuration.rb', line 189 def add_lease_ttl_window_error(errors) lease_ttl = @values[:lease_ttl].to_i window_lookback = @values[:window_lookback].to_i tick_interval = @values[:tick_interval].to_i # Skip if individual validations already failed return if lease_ttl <= 0 || window_lookback.negative? || tick_interval <= 0 minimum_ttl = window_lookback + tick_interval return unless lease_ttl < minimum_ttl errors << "lease_ttl (#{lease_ttl}s) must be >= window_lookback + tick_interval (#{minimum_ttl}s) to prevent duplicate dispatch" end |
#add_namespace_error(errors) ⇒ nil, Kaal::rbs_any
177 178 179 180 181 |
# File 'lib/kaal/config/configuration.rb', line 177 def add_namespace_error(errors) return unless @values[:namespace].to_s.strip.empty? errors << 'namespace cannot be blank' end |
#add_scheduler_config_path_error(errors) ⇒ nil, Kaal::rbs_any
203 204 205 206 207 |
# File 'lib/kaal/config/configuration.rb', line 203 def add_scheduler_config_path_error(errors) return unless @values[:scheduler_config_path].to_s.strip.empty? errors << 'scheduler_config_path cannot be blank' end |
#add_scheduler_conflict_policy_error(errors) ⇒ nil, Kaal::rbs_any
209 210 211 212 213 |
# File 'lib/kaal/config/configuration.rb', line 209 def add_scheduler_conflict_policy_error(errors) return if %i[error code_wins file_wins].include?(@values[:scheduler_conflict_policy]) errors << 'scheduler_conflict_policy must be :error, :code_wins, or :file_wins' end |
#add_scheduler_missing_file_policy_error(errors) ⇒ nil, Kaal::rbs_any
215 216 217 218 219 |
# File 'lib/kaal/config/configuration.rb', line 215 def add_scheduler_missing_file_policy_error(errors) return if %i[warn error].include?(@values[:scheduler_missing_file_policy]) errors << 'scheduler_missing_file_policy must be :warn or :error' end |
#add_tick_interval_error(errors) ⇒ nil, Kaal::rbs_any
149 150 151 152 153 154 |
# File 'lib/kaal/config/configuration.rb', line 149 def add_tick_interval_error(errors) value = @values[:tick_interval] return unless value.to_i <= 0 errors << "tick_interval must be greater than 0, got: #{value}" end |
#add_window_lookahead_error(errors) ⇒ nil, Kaal::rbs_any
163 164 165 166 167 168 |
# File 'lib/kaal/config/configuration.rb', line 163 def add_window_lookahead_error(errors) value = @values[:window_lookahead] return unless value.to_i.negative? errors << "window_lookahead must be greater than or equal to 0, got: #{value}" end |
#add_window_lookback_error(errors) ⇒ nil, Kaal::rbs_any
156 157 158 159 160 161 |
# File 'lib/kaal/config/configuration.rb', line 156 def add_window_lookback_error(errors) value = @values[:window_lookback] return unless value.to_i.negative? errors << "window_lookback must be greater than or equal to 0, got: #{value}" end |
#apply_backend_runtime_context(runtime_context) ⇒ Object
282 283 284 |
# File 'lib/kaal/config/configuration.rb', line 282 def apply_backend_runtime_context(runtime_context) @backend_runtime_context = runtime_context end |
#handle_known_key(method_name) {|arg0, arg1| ... } ⇒ ::Array[false | nil], ::Array[true | Kaal::rbs_any]
228 229 230 231 232 233 234 235 |
# File 'lib/kaal/config/configuration.rb', line 228 def handle_known_key(method_name) name = method_name.to_s setter = name.end_with?('=') key = setter ? name.delete_suffix('=').to_sym : method_name.to_sym return [false, nil] unless @values.key?(key) [true, yield(key, setter)] end |
#normalize_backend(value) ⇒ Kaal::rbs_any
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
# File 'lib/kaal/config/configuration.rb', line 265 def normalize_backend(value) unless value.is_a?(String) || value.is_a?(Symbol) @backend_name = nil return value end normalized_backend_name = Kaal::Config::BackendFactory.normalize_name(value) backend = Kaal::Config::BackendFactory.build( normalized_backend_name, backend_config: @values[:backend_config], namespace: @values[:namespace], runtime_context: @backend_runtime_context ) @backend_name = normalized_backend_name backend end |
#normalize_backend_config ⇒ Kaal::rbs_any
61 |
# File 'sig/kaal/config/configuration.rbs', line 61
def normalize_backend_config: (Kaal::rbs_any value) -> Kaal::rbs_any
|
#normalize_delayed_job_allowed_class_prefixes(value) ⇒ Kaal::rbs_any
300 301 302 303 304 305 |
# File 'lib/kaal/config/configuration.rb', line 300 def normalize_delayed_job_allowed_class_prefixes(value) Array(value).filter_map do |entry| normalized_entry = entry.to_s.strip normalized_entry unless normalized_entry.empty? end end |
#normalize_value(key, value) ⇒ Kaal::rbs_any
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'lib/kaal/config/configuration.rb', line 242 def normalize_value(key, value) case key when :backend normalize_backend(value) when :backend_config value.is_a?(Hash) ? Kaal::Support::HashTools.symbolize_keys(Kaal::Support::HashTools.deep_dup(value)) : (value || {}) when :tick_interval, :window_lookback, :window_lookahead, :lease_ttl value.to_i when :namespace, :scheduler_config_path value.to_s when :time_zone normalize_optional_string(value) when :enable_log_dispatch_registry !!value when :scheduler_conflict_policy, :scheduler_missing_file_policy normalize_optional_symbol(value) when :delayed_job_allowed_class_prefixes normalize_delayed_job_allowed_class_prefixes(value) else value end end |
#rebuild_symbolic_backend_if_needed(key) ⇒ nil, Kaal::rbs_any
287 288 289 290 291 292 293 294 295 296 297 298 |
# File 'lib/kaal/config/configuration.rb', line 287 def rebuild_symbolic_backend_if_needed(key) return unless @backend_name return unless %i[backend_config namespace backend].include?(key) return if key == :backend @values[:backend] = Kaal::Config::BackendFactory.build( @backend_name, backend_config: @values[:backend_config], namespace: @values[:namespace], runtime_context: @backend_runtime_context ) end |
#respond_to_missing?(method_name, include_private = false) ⇒ Boolean
Advertise supported configuration keys for respond_to?.
64 65 66 67 |
# File 'lib/kaal/config/configuration.rb', line 64 def respond_to_missing?(method_name, include_private = false) handled, value = handle_known_key(method_name) { true } (handled && value) || super end |
#set_value(key, value) ⇒ Kaal::rbs_any
237 238 239 240 |
# File 'lib/kaal/config/configuration.rb', line 237 def set_value(key, value) @values[key] = normalize_value(key, value) rebuild_symbolic_backend_if_needed(key) end |
#to_h ⇒ Hash
Get a hash representation of the current configuration.
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/kaal/config/configuration.rb', line 107 def to_h backend = @values[:backend] logger = @values[:logger] { tick_interval: @values[:tick_interval], window_lookback: @values[:window_lookback], window_lookahead: @values[:window_lookahead], lease_ttl: @values[:lease_ttl], namespace: @values[:namespace], backend: backend&.class&.name, backend_config: Kaal::Support::HashTools.deep_dup(@values[:backend_config]), logger: logger&.class&.name, time_zone: @values[:time_zone], enable_log_dispatch_registry: @values[:enable_log_dispatch_registry], enable_dispatch_recovery: @values[:enable_dispatch_recovery], recovery_window: @values[:recovery_window], recovery_startup_jitter: @values[:recovery_startup_jitter], scheduler_config_path: @values[:scheduler_config_path], scheduler_conflict_policy: @values[:scheduler_conflict_policy], scheduler_missing_file_policy: @values[:scheduler_missing_file_policy], delayed_job_allowed_class_prefixes: @values[:delayed_job_allowed_class_prefixes] } end |
#validate ⇒ Array<String>
Validate configuration without raising.
73 74 75 |
# File 'lib/kaal/config/configuration.rb', line 73 def validate validation_errors end |
#validate! ⇒ Configuration
Validate the configuration settings. Raises errors if required settings are invalid.
92 93 94 95 96 97 98 99 100 101 |
# File 'lib/kaal/config/configuration.rb', line 92 def validate! errors = validation_errors raise ConfigurationError, errors.join('; ') if errors.any? validation_warnings.each do |warning| @values[:logger]&.warn(warning) end self end |
#validation_errors ⇒ Kaal::rbs_any
134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/kaal/config/configuration.rb', line 134 def validation_errors errors = [] add_tick_interval_error(errors) add_window_lookback_error(errors) add_window_lookahead_error(errors) add_lease_ttl_error(errors) add_namespace_error(errors) add_backend_config_error(errors) add_lease_ttl_window_error(errors) add_scheduler_config_path_error(errors) add_scheduler_conflict_policy_error(errors) add_scheduler_missing_file_policy_error(errors) errors end |
#validation_warnings ⇒ Array<String>
Non-fatal configuration warnings.
80 81 82 83 84 |
# File 'lib/kaal/config/configuration.rb', line 80 def validation_warnings warnings = [] add_delayed_job_security_warning(warnings) warnings end |