sc4ry 0.1.7 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,65 +1,63 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sc4ry
2
- module Backends
3
- # Redis backend definition
4
- class Redis
4
+ module Backends
5
+ # Redis backend definition
6
+ class Redis
7
+ # Constructor
8
+ # @param [Hash] config Config map
9
+ # @return [Sc4ry::Backends::Redis] a Redis backend
10
+ def initialize(config)
11
+ @auth = config.slice(:auth)[:auth]
12
+ @config = config.slice(:host, :port, :db)
13
+ @be = ::Redis.new @config
14
+ @be.auth(@auth) if @auth
15
+ end
16
+
17
+ # return the list of find records in backend for a specific pattern
18
+ # @return [Array] list of record (for all hostname if hostname is specified)
19
+ def list
20
+ @be.keys('*').map(&:to_sym)
21
+ end
22
+
23
+ # return value of queried record
24
+ # @param key [Symbol] the name of the record
25
+ # @return [String] content value of record
26
+ def get(key:)
27
+ res = YAML.load(@be.get(key))
28
+ res[:exceptions].map! { |item| Object.const_get(item) if item.instance_of?(String) }
29
+ res
30
+ end
31
+
32
+ # defined and store value for specified key
33
+ # @param key [Symbol] :key the name of the record
34
+ # @param value [Symbol] :value the content value of the record
35
+ # @return [String] content value of record
36
+ def put(key:, value:)
37
+ data = value.dup
38
+ data[:exceptions].map! { |item| item.name.to_s if item.instance_of?(Class) }
39
+ @be.set key, data.to_yaml
40
+ end
41
+
42
+ # delete a specific record
43
+ # @param key [Symbol] the name of the record
44
+ # @return [Boolean] status of the operation
45
+ def del(key:)
46
+ @be.del key
47
+ end
48
+
49
+ # flush all records in backend
50
+ # @return [Boolean] status of the operation
51
+ def flush
52
+ @be.flushdb
53
+ end
5
54
 
6
- # Constructor
7
- # @param [Hash] config Config map
8
- # @return [Sc4ry::Backends::Redis] a Redis backend
9
- def initialize(config)
10
- @auth = config.slice(:auth)[:auth]
11
- @config = config.slice(:host, :port, :db)
12
- @be = ::Redis.new @config
13
- @be.auth(@auth) if @auth
14
- end
15
-
16
- # return the list of find records in backend for a specific pattern
17
- # @return [Array] list of record (for all hostname if hostname is specified)
18
- def list
19
- return @store.keys('*')
20
- end
21
-
22
-
23
- # return value of queried record
24
- # @param [Hash] options
25
- # @option options [Symbol] :key the name of the record
26
- # @return [String] content value of record
27
- def get(options)
28
- return @store.get(options[:key])
29
- end
30
-
31
- # defined and store value for specified key
32
- # @param [Hash] options
33
- # @option options [Symbol] :key the name of the record
34
- # @option options [Symbol] :value the content value of the record
35
- # @return [String] content value of record
36
- def put(options)
37
- @store.set options[:key], options[:value]
38
- end
39
-
40
- # delete a specific record
41
- # @param [Hash] options
42
- # @option options [Symbol] :key the name of the record
43
- # @return [Boolean] status of the operation
44
- def del(options)
45
- @store.del options[:key]
46
- end
47
-
48
- # flush all records in backend
49
- def flush
50
- @store.flushdb
51
- end
52
-
53
- # verifiy a specific record existance
54
- # @param [Hash] options
55
- # @option options [Symbol] :key the name of the record
56
- # @return [Boolean] presence of the record
57
- def exist?(options)
58
- return ( not @store.get(options[:key]).nil?)
59
- end
60
-
61
-
55
+ # verifiy a specific record existence
56
+ # @param key [Symbol] the name of the record
57
+ # @return [Boolean] presence of the record
58
+ def exist?(key:)
59
+ !@be.get(key).nil?
62
60
  end
63
-
64
61
  end
65
- end
62
+ end
63
+ end
@@ -1,86 +1,258 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Sc4ry Module
4
+ # @note namespace
1
5
  module Sc4ry
6
+ # Circuits and default configuration management class
2
7
  class Circuits
8
+ include Sc4ry::Constants
9
+ include Sc4ry::Exceptions
10
+
11
+ @@circuits_store = Sc4ry::Store.instance
12
+ @@circuits_notifiers = Sc4ry::Notifiers
13
+ @@circuits_loggers = Sc4ry::Loggers
14
+ @@config = DEFAULT_CONFIG
15
+
16
+ # @!group forwarders
17
+
18
+ # Class method how forward the Notifiers class factory/manager
19
+ # @return [Sc4ry::Notifiers]
20
+ def self.notifiers
21
+ @@circuits_notifiers
22
+ end
23
+
24
+ # Class method how forward a Store manager class singleton
25
+ # @return [Sc4ry::Store]
26
+ def self.store
27
+ @@circuits_store
28
+ end
29
+
30
+ # Class method how forward the Logger manager class factory/manager
31
+ # @return [Sc4ry::Store]
32
+ def self.loggers
33
+ @@circuits_loggers
34
+ end
35
+
36
+ # @!endgroup
37
+
38
+ # @!group Default Sc4ry configuration management
39
+
40
+ # Class method how return de default Sc4ry config
41
+ # @return [Hash]
42
+ def self.default_config
43
+ @@config
44
+ end
45
+
46
+ # class method how merge a differential hash to default config
47
+ # @param [Hash] diff the differential hash config
48
+ # @example usage
49
+ # include Sc4ry
50
+ # Circuits.merge_default_config diff: {max_time: 20, notifiers: [:mattermost]}
51
+ def self.merge_default_config(diff:)
52
+ validator = Sc4ry::Config::Validator.new(definition: diff, from: @@config)
53
+ validator.validate!
54
+ @@config = validator.result
55
+ end
56
+
57
+ # class method for specifiying config by block
58
+ # @yield [Sc4ry::Config::ConfigMapper]
59
+ # @example usage
60
+ # include Sc4ry
61
+ # Circuits.configure do |spec|
62
+ # spec.max_failure_count = 3
63
+ # end
64
+ def self.configure
65
+ mapper = Sc4ry::Config::ConfigMapper.new(definition: @@config.dup)
66
+ yield(mapper)
67
+ validator = Sc4ry::Config::Validator.new(definition: mapper.config, from: @@config)
68
+ validator.validate!
69
+ @@config = validator.result
70
+ end
71
+
72
+ # old default config setter
73
+ # @deprecated use {.merge_default_config} instead
74
+ # @param [Hash] config
75
+ def self.default_config=(config)
76
+ warning_mess = 'DEPRECATED: Circuits.default_config= use Circuits.merge_default_config add: {<config_hash>}'
77
+ Sc4ry::Helpers.log level: :warn,
78
+ message: warning_mess
79
+ Circuits.merge_default_config(diff: config)
80
+ end
3
81
 
4
- @@circuits_store = Sc4ry::Store.instance
82
+ # @!endgroup
5
83
 
6
- @@config = { :max_failure_count => 5,
7
- :timeout_value => 20,
8
- :timeout => false,
9
- :max_timeout_count => 5,
10
- :max_time => 10,
11
- :max_overtime_count => 3,
12
- :check_delay => 30,
13
- :notifiers => [],
14
- :forward_unknown_exceptions => true,
15
- :raise_on_opening => false,
16
- :exceptions => [StandardError, RuntimeError]
17
- }
84
+ # @!group Circuits management
18
85
 
19
- def Circuits.default_config
20
- return @@config
86
+ # class method for registering a new circuit, cloud work with a block
87
+ # @yield [Sc4ry::Config::ConfigMapper]
88
+ # @param [Symbol] circuit a circuit name
89
+ # @param [Hash] config a config override on default config for the circuit
90
+ # @example usage
91
+ # include Sc4ry
92
+ # Circuits.register circuit: :mycircuit, config: {raise_on_opening: true, timeout: true}
93
+ # # or
94
+ # Circuits.register circuit: :mycircuit do |spec|
95
+ # spec.raise_on_opening = true
96
+ # spec.timeout = true
97
+ # end
98
+ # @return [Hash] the full config of the circuit after merge on default
99
+ # @raise [Sc4ryGenericError] if use config keyword with a block
100
+ # @raise [Sc4ryGenericError] if circuit already exist in current store.
101
+ def self.register(circuit:, config: {})
102
+ if !config.empty? && block_given?
103
+ raise Sc4ryGenericError,
104
+ 'config: keyword must not be defined when block is given'
105
+ end
106
+
107
+ if block_given?
108
+ mapper = Sc4ry::Config::ConfigMapper.new(definition: @@config.dup)
109
+ yield(mapper)
110
+ validator = Sc4ry::Config::Validator.new(definition: mapper.config, from: @@config.dup)
111
+ else
112
+ validator = Sc4ry::Config::Validator.new(definition: config, from: @@config.dup)
113
+ end
114
+ validator.validate!
115
+ Sc4ry::Helpers.log level: :debug, message: "Circuit #{circuit} : registered"
116
+ raise Sc4ryGenericError, "Circuit: #{circuit} already exist in store" if @@circuits_store.exist? key: circuit
117
+
118
+ @@circuits_store.put key: circuit, value: validator.result
119
+ validator.result
21
120
  end
22
121
 
23
- def Circuits.default_config=(config)
24
- @@config = config
25
- @@config[:exceptions].map! {|item| item = Object.const_get item if item.class == String}
122
+ # class method how list all circuits in current store
123
+ # @example usage
124
+ # include Sc4ry
125
+ # circuits = Circuits.list
126
+ # @return [Array] the list of [Symbol] circuits name
127
+ def self.list
128
+ @@circuits_store.list
129
+ end
26
130
 
131
+ # class method how flush all circuits in current store
132
+ # @example usage
133
+ # include Sc4ry
134
+ # Circuits.flush
135
+ # @return [true,false]
136
+ def self.flush
137
+ @@circuits_store.flush
27
138
  end
28
139
 
29
- def Circuits.register(options = {})
30
- raise ":circuit is mandatory" unless options[:circuit]
31
- name = options[:circuit]
32
- override = (options[:config].class == Hash)? options[:config] : {}
33
- config = @@config.merge override
34
- @@circuits_store.put key: name, value: config
140
+ # class method for unregistering a circuit
141
+ # @param [Symbol] circuit a circuit name
142
+ # @example usage
143
+ # include Sc4ry
144
+ # Circuits.unregister circuit: :mycircuit
145
+ # @raise [Sc4ryGenericError] if circuit not found in current store.
146
+ # @return [true,false]
147
+ def self.unregister(circuit:)
148
+ raise Sc4ryGenericError, "Circuit #{circuit} not found" unless Circuits.list.include? circuit
149
+
150
+ @@circuits_store.del key: circuit
151
+ Sc4ry::Helpers.log level: :debug, message: "Circuit #{circuit} : unregistered"
152
+ true
35
153
  end
36
154
 
37
- def Circuits.list
38
- return @@circuits_store.list
155
+ # class method for get a specific circuit by circuit name
156
+ # @param [Symbol] circuit a circuit name
157
+ # @example usage
158
+ # include Sc4ry
159
+ # Circuits.get circuit: :mycircuit
160
+ # @return [Hash] the circuit record in current store included values and status if the circuit have already run.
161
+ def self.get(circuit:)
162
+ @@circuits_store.get key: circuit
39
163
  end
40
164
 
165
+ # class method for update the config of a specific circuit by circuit name
166
+ # @param [Symbol] circuit a circuit name
167
+ # @param [Hash] config a config hash to merge on current config
168
+ # @example usage
169
+ # include Sc4ry
170
+ # Circuits.update_config circuit: :mycircuit, config: {}
171
+ # @note : <b>important</b> updating config will reset status and values !
172
+ # @return [Hash] new config for this circuit
173
+ def self.update_config(circuit:, config: { forward_unknown_exceptions: false })
174
+ raise Sc4ryGenericError, "Circuit #{circuit} not found" unless Circuits.list.include? circuit
175
+
176
+ save = @@circuits_store.get key: circuit
177
+ save.delete_if { |key, _val| %i[status values].include? key }
178
+ Circuits.unregister(circuit: circuit)
179
+ save.merge! config
180
+ Circuits.register circuit: circuit, config: save
181
+ end
41
182
 
42
- def Circuits.get(options)
43
- @@circuits_store.get key: options[:circuit]
183
+ # class method for get the status of a specific circuit by circuit name
184
+ # @param [Symbol] circuit a circuit name
185
+ # @example usage
186
+ # include Sc4ry
187
+ # Circuits.status circuit: :mycircuit
188
+ # @return [Symbol] status must in [:open,:half_open,:closed,:never_run]
189
+ def self.status(circuit:)
190
+ data = @@circuits_store.get key: circuit
191
+ data.include?(:status) ? data[:status][:general] : :never_run
44
192
  end
45
193
 
46
- def Circuits.run(options = {}, &block)
194
+ # class method for running circuit, need a block
195
+ # @yield [Proc]
196
+ # @param [Symbol] circuit a circuit name
197
+ # @example usage
198
+ # include Sc4ry
199
+ # Circuits.run circuit: :mycircuit do
200
+ # # [...] your code like a Restclient.get("URL")
201
+ # end
202
+ # # or
203
+ # Circuits.run do
204
+ # # [...] your code like a Restclient.get("URL")
205
+ # # running with the first define circuit (use only on a one circuit usage)
206
+ # end
207
+ # @return [Hash] a result like ":general=>:open, :failure_count=>X, :overtime_count=>X, :timeout_count=>X"
208
+ # @raise [Sc4ryGenericError] if circuit already not exit, block is missing or store empty
209
+ def self.run(circuit: nil, &block)
47
210
  circuits_list = Circuits.list
48
- raise "No circuit block given" unless block_given?
49
- raise "No circuits defined" if circuits_list.empty?
50
- circuit_name = (options[:circuit])? options[:circuit] : circuits_list.first
51
- raise "Circuit #{circuit_name} not found" unless circuits_list.include? circuit_name
52
- circuit = Circuits.get circuit: circuit_name
211
+ raise Sc4ryGenericError, 'No circuit block given' unless block_given?
212
+ raise Sc4ryGenericError, 'No circuits defined' if circuits_list.empty?
213
+
214
+ circuit_name = circuit || circuits_list.first
215
+ raise Sc4ryGenericError, "Circuit #{circuit_name} not found" unless circuits_list.include? circuit_name
216
+
217
+ circuit_to_run = Circuits.get circuit: circuit_name
53
218
  skip = false
54
- if circuit.include? :status then
55
- if circuit[:status][:general] == :open then
56
- @now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
57
- skip = true if ((@now - circuit[:values].last[:end_time]) < circuit[:check_delay])
58
- end
219
+ if circuit_to_run.include?(:status) && (circuit_to_run[:status][:general] == :open)
220
+ @now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
221
+ skip = true if (@now - circuit_to_run[:values].last[:end_time]) < circuit_to_run[:check_delay]
59
222
  end
60
- unless skip
61
- controller = Sc4ry::RunController.new(circuit)
223
+ unless skip
224
+ controller = Sc4ry::RunController.new(circuit_to_run)
62
225
  Circuits.control circuit: circuit_name, values: controller.run(block: block)
63
226
  end
64
- Sc4ry::Helpers.log level: :info, message: "Circuit #{circuit_name} : status #{circuit[:status]}"
65
-
227
+ result = @@circuits_store.get key: circuit_name
228
+ Sc4ry::Helpers.log level: :debug, message: "Circuit #{circuit_name} : status #{result[:status]}"
229
+ result
66
230
  end
67
231
 
68
- private
69
- def Circuits.control(options={})
70
- data = @@circuits_store.get key: options[:circuit]
71
- data[:status] = {:general => :closed, :failure_count => 0, :overtime_count => 0, :timeout_count => 0} unless data.include? :status
72
- data[:values] = Array::new unless data.include? :values
232
+ # @!endgroup
233
+
234
+ # the private class method to control circuits running status
235
+ # @param [Symbol] circuit the name the circuit to control
236
+ # @param [Hash] values the resut value of a run
237
+ # @return [Boolean]
238
+ def self.control(circuit:, values:)
239
+ data = @@circuits_store.get key: circuit
240
+ unless data.include? :status
241
+ data[:status] =
242
+ { general: :closed, failure_count: 0, overtime_count: 0, timeout_count: 0 }
243
+ end
244
+ data[:values] = [] unless data.include? :values
73
245
  level = [data[:max_failure_count].to_i, data[:max_timeout_count].to_i, data[:max_overtime_count].to_i].max
74
246
  data[:values].shift if data[:values].size > level
75
- data[:values].push options[:values]
247
+ data[:values].push values
76
248
  worst_status = []
77
- ['failure','overtime','timeout'].each do |control|
78
- if options[:values][control.to_sym] == true then
249
+ %w[failure overtime timeout].each do |control|
250
+ if values[control.to_sym] == true
79
251
  data[:status]["#{control}_count".to_sym] += 1
80
252
  else
81
253
  data[:status]["#{control}_count".to_sym] = 0
82
254
  end
83
-
255
+
84
256
  case data[:status]["#{control}_count".to_sym]
85
257
  when 0
86
258
  worst_status.push :closed
@@ -91,14 +263,23 @@ module Sc4ry
91
263
  end
92
264
  end
93
265
  save = data[:status][:general]
94
- [:closed,:half_open,:open].each do |status|
266
+ %i[closed half_open open].each do |status|
95
267
  data[:status][:general] = status if worst_status.include? status
96
268
  end
97
- if save != data[:status][:general] then
98
- raise Sc4ry::Exceptions::CircuitBreaked if data[:status][:general] == :open and data[:raise_on_opening]
99
- Sc4ry::Helpers.notify circuit: options[:circuit], config: data
100
- end
101
- @@circuits_store.put key: options[:circuit], value: data
269
+ if save != data[:status][:general]
270
+ raise CircuitBreaked if data[:status][:general] == :open && data[:raise_on_opening]
271
+
272
+ if data[:status][:general] == :open
273
+ Sc4ry::Helpers.log level: :error,
274
+ message: "Circuit #{circuit} : breacking ! "
275
+ end
276
+ if data[:status][:general] == :closed
277
+ Sc4ry::Helpers.log level: :info,
278
+ message: "Circuit #{circuit} : is now closed"
279
+ end
280
+ Sc4ry::Helpers.notify circuit: circuit, config: data
281
+ end
282
+ @@circuits_store.put key: circuit, value: data
102
283
  end
103
284
  end
104
- end
285
+ end
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Sc4ry module
4
+ # @note namespace
5
+ module Sc4ry
6
+ # Sc4ry::Config module
7
+ # @note namespace
8
+ module Config
9
+ # Configuration validator for Sc4ry default and circuits configuration
10
+ # @private
11
+ class Validator
12
+ # accessor on Circuit definition given for validation
13
+ attr_reader :input
14
+
15
+ # accessor on circuit initial definition from default config or given in construction by from keyword
16
+ # @note altered by reference to final result mapping with {#validate!}
17
+ attr_reader :config
18
+
19
+ def result
20
+ @config
21
+ end
22
+
23
+ include Sc4ry::Constants
24
+ include Sc4ry::Exceptions
25
+ # Validator constructor
26
+ # @param [Hash] definition the config hash to merge and validate
27
+ # @param [Hash] from config hash merged on origin (default : the Sc4ry base config from Constants )
28
+ # @return [Validator] a new instance of Validator
29
+ def initialize(definition:, from: DEFAULT_CONFIG)
30
+ @config = from
31
+ @input = definition
32
+ end
33
+
34
+ # Validation method, alter by reference the config attribut
35
+ # @raise ConfigError if un unknown key is given in definition to merge.
36
+ def validate!
37
+ unknown_keys = @input.keys.difference @config.keys
38
+ raise ConfigError, "Unknown keys in config set : #{unknown_keys}" unless unknown_keys.empty?
39
+
40
+ validate_formats
41
+ @config.merge! @input
42
+ format_exceptions
43
+ end
44
+
45
+ private
46
+
47
+ # Validation private sub method
48
+ # @raise ConfigError if proposed values haven't the good format and deeply in array
49
+ def validate_formats
50
+ @input.each do |spec, value|
51
+ unless DEFAULT_CONFIG_FORMATS[spec][:proc].call(value)
52
+ raise ConfigError,
53
+ "#{spec} value #{DEFAULT_CONFIG_FORMATS[spec][:desc]}"
54
+ end
55
+
56
+ next unless DEFAULT_CONFIG_FORMATS[spec].include? :list
57
+
58
+ value.each do |item|
59
+ unless DEFAULT_CONFIG_FORMATS[spec][:list].include? item
60
+ raise ConfigError,
61
+ "#{spec} value must be in #{DEFAULT_CONFIG_FORMATS[spec][:list]}"
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ # adapter for exception key in config String to Constant Class Name if need
68
+ # @note by reference
69
+ def format_exceptions
70
+ @config[:exceptions].map! { |item| item.instance_of?(String) ? Object.const_get(item) : item }
71
+ end
72
+ end
73
+
74
+ # Config Data mapper for block yielding methods for configuration
75
+ # @note work for/with {Sc4ry::Circuits.configure} and {Sc4ry::Circuits.register} when block given
76
+ class ConfigMapper
77
+ include Sc4ry::Constants
78
+
79
+ # config from given definition passed in constructor
80
+ attr_reader :config
81
+
82
+ # the mapping constructor from a given definition or the default From Sc4ry config (Constant)
83
+ # @param [Hash] definition a config hash
84
+ # @note creating dynamically accessors on config record given in definition
85
+ def initialize(definition: DEFAULT_CONFIG)
86
+ @config = definition
87
+ @config.each do |key, _value|
88
+ define_singleton_method "#{key}=".to_sym do |val|
89
+ key = __method__.to_s.chop.to_sym
90
+ @config[key] = val
91
+ end
92
+ define_singleton_method key do
93
+ return @config[__method__]
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Sc4ry module
4
+ # @note namespace
5
+ module Sc4ry
6
+ # Sc4ry::Constants module
7
+ # @note namespace
8
+ module Constants
9
+ # notifiers available in Sc4ry natively
10
+ CURRENT_NOTIFIERS = %i[prometheus mattermost]
11
+
12
+ # the Sc4ry default config entries and values
13
+ DEFAULT_CONFIG = {
14
+ max_failure_count: 5,
15
+ timeout_value: 20,
16
+ timeout: false,
17
+ max_timeout_count: 5,
18
+ max_time: 10,
19
+ max_overtime_count: 3,
20
+ check_delay: 30,
21
+ notifiers: [],
22
+ forward_unknown_exceptions: true,
23
+ raise_on_opening: false,
24
+ exceptions: [StandardError, RuntimeError]
25
+ }
26
+
27
+ # Default config supported entries with format and Proc checker for {Sc4ry::Config::Validator}
28
+ DEFAULT_CONFIG_FORMATS = {
29
+ max_failure_count: { proc: proc { |item| item.instance_of?(Integer) }, desc: 'must be an Integer' },
30
+ timeout_value: { proc: proc { |item| item.instance_of?(Integer) }, desc: 'must be an Integer' },
31
+ timeout: { proc: proc { |item| [true, false].include? item }, desc: 'must be a Boolean' },
32
+ max_timeout_count: { proc: proc { |item| item.instance_of?(Integer) }, desc: 'must be an Integer' },
33
+ max_time: { proc: proc { |item| item.instance_of?(Integer) }, desc: 'must be an Integer' },
34
+ max_overtime_count: { proc: proc { |item| item.instance_of?(Integer) }, desc: 'must be an Integer' },
35
+ check_delay: { proc: proc { |item| item.instance_of?(Integer) }, desc: 'must be an Integer' },
36
+ notifiers: {
37
+ proc: proc do |item|
38
+ item.instance_of?(Array) and item.select { |val| val.instance_of?(Symbol) }.size == item.size
39
+ end,
40
+ desc: 'must be an Array of Symbol',
41
+ list: CURRENT_NOTIFIERS
42
+ },
43
+ forward_unknown_exceptions: { proc: proc { |item| [true, false].include? item }, desc: 'must be a Boolean' },
44
+ raise_on_opening: { proc: proc { |item| [true, false].include? item }, desc: 'must be a Boolean' },
45
+ exceptions: {
46
+ proc: proc do |item|
47
+ item.instance_of?(Array) and item.select do |val|
48
+ [Class, String].include? val.class
49
+ end.size == item.size
50
+ end,
51
+ desc: 'must be an Array of Exception(Class) or String'
52
+ }
53
+ }
54
+ end
55
+ end
@@ -1,8 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubygems depends
1
4
  require 'rest-client'
2
5
  require 'prometheus/client'
3
6
  require 'prometheus/client/push'
7
+ require 'redis'
8
+ require 'version'
4
9
 
5
- require 'logger'
10
+ # Stdlibs depends
11
+ require 'logger'
6
12
  require 'timeout'
7
13
  require 'forwardable'
8
14
  require 'singleton'
@@ -11,15 +17,18 @@ require 'openssl'
11
17
  require 'net/http'
12
18
  require 'uri'
13
19
  require 'json'
20
+ require 'yaml'
14
21
 
15
-
16
-
22
+ # Sc4ry internal depends
17
23
  require_relative 'helpers'
18
24
  require_relative 'exceptions'
19
25
  require_relative 'logger'
26
+ require_relative 'constants'
27
+ require_relative 'config'
28
+ require_relative 'notifiers/init'
29
+ require_relative 'exporters/init'
20
30
  require_relative 'backends/init'
31
+
21
32
  require_relative 'store'
22
33
  require_relative 'run_controller'
23
34
  require_relative 'circuits'
24
- require_relative 'notifiers/init'
25
- require_relative 'exporters/init'