sc4ry 0.1.7 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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'