sc4ry 0.1.8 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 19791a7d72756fe96464fd43fd648010a71ff7491b96702da23c8828c19f58a2
4
- data.tar.gz: 6e1d7318a3de28fd0950213f9e8bf344819dc5858f66f5ce0ec5b1eb7275b99f
3
+ metadata.gz: f4cbfc8c2a7a821c3374916cdd69650a91f1eca5faa4dbbd93ac94e29dae5f89
4
+ data.tar.gz: dfa68d210342122e96e6f9fcd234fa73f6fefee667addac8371424b39c1b63d4
5
5
  SHA512:
6
- metadata.gz: 7f2c87ddb8ee4dc04aa1d6b2b9b9f214309fc56749dbb85a648f541ca1c27621dffdfcb9619348c3cd57874f5f9e9f0c24371fc9926150d32bb62edf3d5e4798
7
- data.tar.gz: b43b8a8a6611fa76c890b10ccc40ffbee0f035bf8af298891919dbb9b4bf3ece9fb1ef13fb5386f0807c11e188d6cf7e9448979a4dc3552a62d1043cf53c3a78
6
+ metadata.gz: 82590002c1ac457715776b0be304d77fa2903885cc4dc21ee45cea87ee070648661b48520453ab011cd287da49997990b4e607940a54954f5f82b5c884089715
7
+ data.tar.gz: 8b63d6b39cee270a1e1ab38ffcde491b746011126615bc4a5908b9f8790017f0c30c8899453ca1848ee4022f8528a0edd61587b583d58a8404e4eef139ecbb84
@@ -0,0 +1,27 @@
1
+ name: Ruby
2
+
3
+ on: [push,pull_request]
4
+
5
+ jobs:
6
+ container-job:
7
+ runs-on: ubuntu-latest
8
+ container: ruby:latest
9
+ services:
10
+ redis:
11
+ image: redis
12
+ pushgateway:
13
+ image: prom/pushgateway
14
+
15
+ steps:
16
+ - uses: actions/checkout@v2
17
+ - name: Run the default task
18
+ run: |
19
+ gem install bundler -v 2.2.3
20
+ bundle install
21
+ bundle exec rake
22
+ env:
23
+ # The hostname used to communicate with the Redis service container
24
+ REDIS_HOST: redis
25
+ REDIS_PORT: 6379
26
+ PROM_PG_PORT: 9091
27
+ PROM_PG_HOST: pushgateway
data/.gitignore CHANGED
@@ -6,6 +6,6 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
-
9
+ /yardoc/
10
10
  # rspec failure tracking
11
11
  .rspec_status
data/Gemfile CHANGED
@@ -6,4 +6,7 @@ gemspec
6
6
  gem "rake", "~> 12.0"
7
7
  gem "rspec", "~> 3.0"
8
8
  gem "prometheus-client", "~> 3.0"
9
- gem "rest-client", "~> 2.1"
9
+ gem "rest-client", "~> 2.1"
10
+ gem "redis", "~> 4.6"
11
+ gem "version", "~> 1.1"
12
+
data/README.md CHANGED
@@ -2,7 +2,25 @@
2
2
 
3
3
  Sc4ry provide the Circuit Breaker Design Pattern for your applications
4
4
 
5
- ![Sc4ry logo](assets/images/logo_sc4ry.png) _Simple CircuitBreacker 4 RubY_
5
+ [![Ruby](https://github.com/Ultragreen/Sc4ry/workflows/Ruby/badge.svg)](https://github.com/Ultragreen/sc4ry/actions?query=workflow%3ARuby+branch%3Amaster)
6
+ ![GitHub](https://img.shields.io/github/license/Ultragreen/sc4ry)
7
+
8
+ [![Documentation](https://img.shields.io/badge/docs-rubydoc.info-brightgreen)](https://rubydoc.info/gems/sc4ry)
9
+ ![GitHub issues](https://img.shields.io/github/issues/Ultragreen/sc4ry)
10
+ ![GitHub tag (latest by date)](https://img.shields.io/github/v/tag/Ultragreen/sc4ry)
11
+ ![GitHub top language](https://img.shields.io/github/languages/top/Ultragreen/sc4ry)
12
+ ![GitHub milestones](https://img.shields.io/github/milestones/open/Ultragreen/sc4ry)
13
+
14
+ ![Gem](https://img.shields.io/gem/dt/sc4ry)
15
+ [![Gem Version](https://badge.fury.io/rb/sc4ry.svg)](https://badge.fury.io/rb/sc4ry)
16
+ ![Twitter Follow](https://img.shields.io/twitter/follow/Ultragreen?style=social)
17
+ ![GitHub Org's stars](https://img.shields.io/github/stars/Ultragreen?style=social)
18
+ ![GitHub watchers](https://img.shields.io/github/watchers/Ultragreen/sc4ry?style=social)
19
+
20
+ <noscript><a href="https://liberapay.com/ruydiaz/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a></noscript>
21
+
22
+ ![Sc4ry logo](assets/images/logo_sc4ry.png)
23
+ _Simple CircuitBreacker 4 RubY_
6
24
 
7
25
  ## Installation
8
26
 
@@ -22,6 +40,9 @@ Or install it yourself as:
22
40
 
23
41
  ## Usage
24
42
 
43
+ ### Circuits States Worflow
44
+
45
+ ![Sc4ry workflow](assets/images/sc4ry_workflow.png)
25
46
  ### sample with Restclient
26
47
 
27
48
  ```ruby
@@ -109,8 +130,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
109
130
 
110
131
  ## Contributing
111
132
 
112
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/sc4ry. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/sc4ry/blob/master/CODE_OF_CONDUCT.md).
113
-
133
+ Bug reports and pull requests are welcome on GitHub at https://github.com/Ultragreen/sc4ry.
114
134
 
115
135
  ## License
116
136
 
data/Rakefile CHANGED
@@ -1,6 +1,37 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rspec/core/rake_task"
3
+ require 'yard'
4
+ require 'yard/rake/yardoc_task.rb'
5
+ require 'code_statistics'
6
+ require "roodi"
7
+ require "roodi_task"
8
+ require "version"
9
+ require 'rake/version_task'
10
+ Rake::VersionTask.new
11
+
12
+
13
+ RoodiTask.new() do | t |
14
+ t.patterns = %w(lib/**/*.rb)
15
+ t.config = "ultragreen_roodi_coding_convention.yml"
16
+ end
17
+
3
18
 
4
19
  RSpec::Core::RakeTask.new(:spec)
5
20
 
6
21
  task :default => :spec
22
+
23
+
24
+ YARD::Rake::YardocTask.new do |t|
25
+ t.files = [ 'lib/**/*.rb', '-', 'doc/**/*','spec/**/*_spec.rb']
26
+ t.options += ['-o', "yardoc"]
27
+ end
28
+ YARD::Config.load_plugin('yard-rspec')
29
+
30
+ namespace :yardoc do
31
+ task :clobber do
32
+ rm_r "yardoc" rescue nil
33
+ rm_r ".yardoc" rescue nil
34
+ rm_r "pkg" rescue nil
35
+ end
36
+ end
37
+ task :clobber => "yardoc:clobber"
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.0
Binary file
@@ -1,33 +1,60 @@
1
+ # Sc4ry module
2
+ # @note namespace
1
3
  module Sc4ry
4
+
5
+ # Sc4ry:Backends module
6
+ # @note namespace
2
7
  module Backends
3
8
 
9
+ # class of the memory backend
4
10
  class Memory
11
+
12
+ # Constructor
13
+ # @param [Hash] config Config map
14
+ # @return [Sc4ry::Backends::Memory] a in Memory backend
5
15
  def initialize(config=nil?)
6
16
  @data = Hash::new
7
17
  end
8
18
 
19
+ # return the list of find records in backend for a specific pattern
20
+ # @return [Array] list of record (for all hostname if hostname is specified)
9
21
  def list
10
22
  return @data.keys
11
23
  end
12
24
 
13
- def get(options)
14
- return @data[options[:key]]
25
+ # return value of queried record
26
+ # @param key [Symbol] the name of the record
27
+ # @return [String] content value of record
28
+ def get(key: )
29
+ return @data[key]
15
30
  end
16
31
 
17
- def put(options)
18
- @data[options[:key]] = options[:value]
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[key] = value
19
38
  end
20
39
 
21
- def del(options)
22
- @data.delete options[:key]
40
+ # delete a specific record
41
+ # @param params [Symbol] the name of the record
42
+ # @return [Boolean] status of the operation
43
+ def del(key: )
44
+ @data.delete key
23
45
  end
24
46
 
47
+ # flush all records in backend
48
+ # @return [Boolean] status of the operation
25
49
  def flush
26
50
  @data.clear
27
51
  end
28
52
 
29
- def exist?(options)
30
- return @data.include? options[:key]
53
+ # verifiy a specific record existence
54
+ # @param key [Symbol] the name of the record
55
+ # @return [Boolean] presence of the record
56
+ def exist?(key: )
57
+ return @data.include? key
31
58
  end
32
59
 
33
60
  end
@@ -16,46 +16,47 @@ module Sc4ry
16
16
  # return the list of find records in backend for a specific pattern
17
17
  # @return [Array] list of record (for all hostname if hostname is specified)
18
18
  def list
19
- return @store.keys('*')
19
+ return @be.keys('*').map(&:to_sym)
20
20
  end
21
21
 
22
22
 
23
23
  # return value of queried record
24
- # @param [Hash] options
25
- # @option options [Symbol] :key the name of the record
24
+ # @param key [Symbol] the name of the record
26
25
  # @return [String] content value of record
27
- def get(options)
28
- return @store.get(options[:key])
26
+ def get(key:)
27
+ res = YAML.load(@be.get(key))
28
+ res[:exceptions].map! {|item| item = Object.const_get(item) if item.class == String }
29
+ return res
29
30
  end
30
31
 
31
32
  # 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
33
+ # @param key [Symbol] :key the name of the record
34
+ # @param value [Symbol] :value the content value of the record
35
35
  # @return [String] content value of record
36
- def put(options)
37
- @store.set options[:key], options[:value]
36
+ def put(key: ,value:)
37
+ data = value.dup
38
+ data[:exceptions].map! {|item| item = item.name.to_s if item.class == Class }
39
+ @be.set key, data.to_yaml
38
40
  end
39
41
 
40
42
  # delete a specific record
41
- # @param [Hash] options
42
- # @option options [Symbol] :key the name of the record
43
+ # @param key [Symbol] the name of the record
43
44
  # @return [Boolean] status of the operation
44
- def del(options)
45
- @store.del options[:key]
45
+ def del(key: )
46
+ @be.del key
46
47
  end
47
48
 
48
49
  # flush all records in backend
50
+ # @return [Boolean] status of the operation
49
51
  def flush
50
- @store.flushdb
52
+ @be.flushdb
51
53
  end
52
54
 
53
- # verifiy a specific record existance
54
- # @param [Hash] options
55
- # @option options [Symbol] :key the name of the record
55
+ # verifiy a specific record existence
56
+ # @param key [Symbol] the name of the record
56
57
  # @return [Boolean] presence of the record
57
- def exist?(options)
58
- return ( not @store.get(options[:key]).nil?)
58
+ def exist?(key: )
59
+ return ( not @be.get(key).nil?)
59
60
  end
60
61
 
61
62
 
@@ -1,17 +1,56 @@
1
+ # Sc4ry Module
2
+ # @note namespace
1
3
  module Sc4ry
4
+
5
+ # Circuits and default configuration management class
2
6
  class Circuits
3
7
 
4
8
  include Sc4ry::Constants
5
9
  include Sc4ry::Exceptions
6
10
 
7
11
  @@circuits_store = Sc4ry::Store.instance
8
-
12
+ @@circuits_notifiers = Sc4ry::Notifiers
13
+ @@circuits_loggers = Sc4ry::Loggers
9
14
  @@config = DEFAULT_CONFIG
10
15
 
16
+ # @!group forwarders
17
+
18
+ # Class method how forward the Notifiers class factory/manager
19
+ # @return [Sc4ry::Notifiers]
20
+ def Circuits.notifiers
21
+ return @@circuits_notifiers
22
+ end
23
+
24
+ # Class method how forward a Store manager class singleton
25
+ # @return [Sc4ry::Store]
26
+ def Circuits.store
27
+ return @@circuits_store
28
+ end
29
+
30
+ # Class method how forward the Logger manager class factory/manager
31
+ # @return [Sc4ry::Store]
32
+ def Circuits.loggers
33
+ return @@circuits_loggers
34
+ end
35
+
36
+
37
+
38
+ # @!endgroup
39
+
40
+
41
+ # @!group Default Sc4ry configuration management
42
+
43
+ # Class method how return de default Sc4ry config
44
+ # @return [Hash]
11
45
  def Circuits.default_config
12
46
  return @@config
13
47
  end
14
48
 
49
+ # class method how merge a differential hash to default config
50
+ # @param [Hash] diff the differential hash config
51
+ # @example usage
52
+ # include Sc4ry
53
+ # Circuits.merge_default_config diff: {max_time: 20, notifiers: [:mattermost]}
15
54
  def Circuits.merge_default_config(diff:)
16
55
  validator = Sc4ry::Config::Validator::new(definition: diff, from: @@config)
17
56
  validator.validate!
@@ -19,6 +58,13 @@ module Sc4ry
19
58
 
20
59
  end
21
60
 
61
+ # class method for specifiying config by block
62
+ # @yield [Sc4ry::Config::ConfigMapper]
63
+ # @example usage
64
+ # include Sc4ry
65
+ # Circuits.configure do |spec|
66
+ # spec.max_failure_count = 3
67
+ # end
22
68
  def Circuits.configure(&bloc)
23
69
  mapper = Sc4ry::Config::ConfigMapper::new(definition: @@config.dup)
24
70
  yield(mapper)
@@ -28,11 +74,33 @@ module Sc4ry
28
74
  end
29
75
 
30
76
 
77
+ # old default config setter
78
+ # @deprecated use {.merge_default_config} instead
79
+ # @param [Hash] config
31
80
  def Circuits.default_config=(config)
32
81
  Sc4ry::Helpers.log level: :warn, message: "DEPRECATED: Circuits.default_config= is deprecated please use Circuits.merge_default_config add: {<config_hash>}"
33
82
  Circuits.merge_default_config(diff: config)
34
83
  end
35
84
 
85
+ # @!endgroup
86
+
87
+ # @!group Circuits management
88
+
89
+ # class method for registering a new circuit, cloud work with a block
90
+ # @yield [Sc4ry::Config::ConfigMapper]
91
+ # @param [Symbol] circuit a circuit name
92
+ # @param [Hash] config a config override on default config for the circuit
93
+ # @example usage
94
+ # include Sc4ry
95
+ # Circuits.register circuit: :mycircuit, config: {raise_on_opening: true, timeout: true}
96
+ # # or
97
+ # Circuits.register circuit: :mycircuit do |spec|
98
+ # spec.raise_on_opening = true
99
+ # spec.timeout = true
100
+ # end
101
+ # @return [Hash] the full config of the circuit after merge on default
102
+ # @raise [Sc4ryGenericError] if use config keyword with a block
103
+ # @raise [Sc4ryGenericError] if circuit already exist in current store.
36
104
  def Circuits.register(circuit:, config: {})
37
105
  if config.size > 0 and block_given? then
38
106
  raise Sc4ryGenericError, "config: keyword must not be defined when block is given"
@@ -46,51 +114,141 @@ module Sc4ry
46
114
  end
47
115
  validator.validate!
48
116
  Sc4ry::Helpers.log level: :debug, message: "Circuit #{circuit} : registered"
117
+ raise Sc4ryGenericError, "Circuit: #{circuit} already exist in store" if @@circuits_store.exist? key: circuit
49
118
  @@circuits_store.put key: circuit, value: validator.result
119
+ return validator.result
50
120
  end
51
121
 
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
52
127
  def Circuits.list
53
128
  return @@circuits_store.list
54
129
  end
55
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 Circuits.flush
137
+ return @@circuits_store.flush
138
+ end
56
139
 
57
- def Circuits.get(options)
58
- @@circuits_store.get key: options[:circuit]
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 Circuits.unregister(circuit:)
148
+ if Circuits.list.include? circuit then
149
+ @@circuits_store.del key: circuit
150
+ return true
151
+ else
152
+ raise Sc4ryGenericError, "Circuit #{circuit} not found"
153
+ return false
154
+ end
59
155
  end
60
156
 
61
- def Circuits.run(options = {}, &block)
157
+
158
+ # class method for get a specific circuit by circuit name
159
+ # @param [Symbol] circuit a circuit name
160
+ # @example usage
161
+ # include Sc4ry
162
+ # Circuits.get circuit: :mycircuit
163
+ # @return [Hash] the circuit record in current store included values and status if the circuit have already run.
164
+ def Circuits.get(circuit:)
165
+ @@circuits_store.get key: circuit
166
+ end
167
+
168
+ # class method for update the config of a specific circuit by circuit name
169
+ # @param [Symbol] circuit a circuit name
170
+ # @param [Hash] config a config hash to merge on current config
171
+ # @example usage
172
+ # include Sc4ry
173
+ # Circuits.update_config circuit: :mycircuit, config: {}
174
+ # @note : <b>important</b> updating config will reset status and values !
175
+ # @return [Hash] new config for this circuit
176
+ def Circuits.update_config(circuit: , config: {forward_unknown_exceptions: false})
177
+ raise Sc4ryGenericError, "Circuit #{circuit} not found" unless Circuits.list.include? circuit
178
+ save = @@circuits_store.get key: circuit
179
+ save.delete_if {|key,val| [:status,:values].include? key}
180
+ Circuits.unregister(circuit: circuit)
181
+ save.merge! config
182
+ return Circuits.register circuit: circuit, config: save
183
+ end
184
+
185
+ # class method for get the status of a specific circuit by circuit name
186
+ # @param [Symbol] circuit a circuit name
187
+ # @example usage
188
+ # include Sc4ry
189
+ # Circuits.status circuit: :mycircuit
190
+ # @return [Symbol] status must in [:open,:half_open,:closed,:never_run]
191
+ def Circuits.status(circuit:)
192
+ data = @@circuits_store.get key: circuit
193
+ return (data.include? :status)? data[:status][:general] : :never_run
194
+ end
195
+
196
+
197
+ # class method for running circuit, need a block
198
+ # @yield [Proc]
199
+ # @param [Symbol] circuit a circuit name
200
+ # @example usage
201
+ # include Sc4ry
202
+ # Circuits.run circuit: :mycircuit do
203
+ # # [...] your code like a Restclient.get("URL")
204
+ # end
205
+ # # or
206
+ # Circuits.run do
207
+ # # [...] your code like a Restclient.get("URL")
208
+ # # running with the first define circuit (use only on a one circuit usage)
209
+ # end
210
+ # @return [Hash] a result like ":general=>:open, :failure_count=>X, :overtime_count=>X, :timeout_count=>X"
211
+ # @raise [Sc4ryGenericError] if circuit already not exit, block is missing or store empty
212
+ def Circuits.run(circuit: nil , &block)
62
213
  circuits_list = Circuits.list
63
214
  raise Sc4ryGenericError, "No circuit block given" unless block_given?
64
215
  raise Sc4ryGenericError, "No circuits defined" if circuits_list.empty?
65
- circuit_name = (options[:circuit])? options[:circuit] : circuits_list.first
216
+ circuit_name = (circuit)? circuit : circuits_list.first
66
217
  raise Sc4ryGenericError, "Circuit #{circuit_name} not found" unless circuits_list.include? circuit_name
67
- circuit = Circuits.get circuit: circuit_name
218
+ circuit_to_run = Circuits.get circuit: circuit_name
68
219
  skip = false
69
- if circuit.include? :status then
70
- if circuit[:status][:general] == :open then
220
+ if circuit_to_run.include? :status then
221
+ if circuit_to_run[:status][:general] == :open then
71
222
  @now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
72
- skip = true if ((@now - circuit[:values].last[:end_time]) < circuit[:check_delay])
223
+ skip = true if ((@now - circuit_to_run[:values].last[:end_time]) < circuit_to_run[:check_delay])
73
224
  end
74
225
  end
75
226
  unless skip
76
- controller = Sc4ry::RunController.new(circuit)
227
+ controller = Sc4ry::RunController.new(circuit_to_run)
77
228
  Circuits.control circuit: circuit_name, values: controller.run(block: block)
78
229
  end
79
- Sc4ry::Helpers.log level: :debug, message: "Circuit #{circuit_name} : status #{circuit[:status]}"
80
-
230
+ result = @@circuits_store.get key: circuit_name
231
+ Sc4ry::Helpers.log level: :debug, message: "Circuit #{circuit_name} : status #{result[:status]}"
232
+ return result
81
233
  end
82
234
 
235
+ # @!endgroup
236
+
83
237
  private
84
- def Circuits.control(options={})
85
- data = @@circuits_store.get key: options[:circuit]
238
+ # the private class method to control circuits running status
239
+ # @param [Symbol] circuit the name the circuit to control
240
+ # @param [Hash] values the resut value of a run
241
+ # @return [Boolean]
242
+ def Circuits.control(circuit: , values: )
243
+ data = @@circuits_store.get key: circuit
86
244
  data[:status] = {:general => :closed, :failure_count => 0, :overtime_count => 0, :timeout_count => 0} unless data.include? :status
87
245
  data[:values] = Array::new unless data.include? :values
88
246
  level = [data[:max_failure_count].to_i, data[:max_timeout_count].to_i, data[:max_overtime_count].to_i].max
89
247
  data[:values].shift if data[:values].size > level
90
- data[:values].push options[:values]
248
+ data[:values].push values
91
249
  worst_status = []
92
250
  ['failure','overtime','timeout'].each do |control|
93
- if options[:values][control.to_sym] == true then
251
+ if values[control.to_sym] == true then
94
252
  data[:status]["#{control}_count".to_sym] += 1
95
253
  else
96
254
  data[:status]["#{control}_count".to_sym] = 0
@@ -111,11 +269,11 @@ module Sc4ry
111
269
  end
112
270
  if save != data[:status][:general] then
113
271
  raise CircuitBreaked if data[:status][:general] == :open and data[:raise_on_opening]
114
- Sc4ry::Helpers.log level: :error, message: "Circuit #{options[:circuit]} : breacking ! " if data[:status][:general] == :open
115
- Sc4ry::Helpers.log level: :info, message: "Circuit #{options[:circuit]} : is now closed" if data[:status][:general] == :closed
116
- Sc4ry::Helpers.notify circuit: options[:circuit], config: data
272
+ Sc4ry::Helpers.log level: :error, message: "Circuit #{circuit} : breacking ! " if data[:status][:general] == :open
273
+ Sc4ry::Helpers.log level: :info, message: "Circuit #{circuit} : is now closed" if data[:status][:general] == :closed
274
+ Sc4ry::Helpers.notify circuit: circuit, config: data
117
275
  end
118
- @@circuits_store.put key: options[:circuit], value: data
276
+ @@circuits_store.put key: circuit, value: data
119
277
  end
120
278
  end
121
279
  end
data/lib/sc4ry/config.rb CHANGED
@@ -1,32 +1,49 @@
1
+ # Sc4ry module
2
+ # @note namespace
1
3
  module Sc4ry
4
+ # Sc4ry::Config module
5
+ # @note namespace
2
6
  module Config
7
+ # Configuration validator for Sc4ry default and circuits configuration
8
+ # @private
3
9
  class Validator
4
- attr_reader :definition
5
- attr_reader :default
10
+
11
+ # accessor on Circuit definition given for validation
12
+ attr_reader :input
13
+ # accessor on circuit initial definition from default config or given in construction by from keyword
14
+ # @note altered by reference to final result mapping with {#validate!}
15
+ attr_reader :config
6
16
 
7
17
  def result
8
- @default
18
+ @config
9
19
  end
10
20
 
11
21
  include Sc4ry::Constants
12
22
  include Sc4ry::Exceptions
13
-
23
+ # Validator constructor
24
+ # @param [Hash] definition the config hash to merge and validate
25
+ # @param [Hash] from config hash merged on origin (default : the Sc4ry base config from Constants )
26
+ # @return [Validator] a new instance of Validator
14
27
  def initialize(definition: , from: DEFAULT_CONFIG)
15
- @default = from
16
- @definition = definition
28
+ @config = from
29
+ @input = definition
17
30
  end
18
31
 
32
+ # Validation method, alter by reference the config attribut
33
+ # @raise ConfigError if un unknown key is given in definition to merge.
19
34
  def validate!
20
- unknown_keys = @definition.keys.difference @default.keys
35
+ unknown_keys = @input.keys.difference @config.keys
21
36
  raise ConfigError::new("Unknown keys in config set : #{unknown_keys.to_s}") unless unknown_keys.empty?
22
37
  validate_formats
23
- @default.merge! @definition
38
+ @config.merge! @input
24
39
  format_exceptions
25
40
  end
26
41
 
27
42
  private
43
+ # Validation private sub method
44
+ # @raise ConfigError if proposed values haven't the good format and deeply in array
28
45
  def validate_formats
29
- definition.each do |spec,value|
46
+ @input.each do |spec,value|
30
47
  raise ConfigError::new("#{spec} value #{DEFAULT_CONFIG_FORMATS[spec][:desc]}") unless DEFAULT_CONFIG_FORMATS[spec][:proc].call(value)
31
48
  if DEFAULT_CONFIG_FORMATS[spec].include? :list then
32
49
  value.each do |item|
@@ -36,17 +53,26 @@ module Sc4ry
36
53
  end
37
54
  end
38
55
 
56
+ # adapter for exception key in config String to Constant Class Name if need
57
+ # @note by reference
39
58
  def format_exceptions
40
- @default[:exceptions].map! {|item| item = (item.class == String)? Object.const_get(item) : item }
59
+ @config[:exceptions].map! {|item| item = (item.class == String)? Object.const_get(item) : item }
41
60
  end
42
61
 
43
62
  end
44
63
 
64
+ # Config Data mapper for block yielding methods for configuration
65
+ # @note work for/with {Sc4ry::Circuits.configure} and {Sc4ry::Circuits.register} when block given
45
66
  class ConfigMapper
46
67
 
47
68
  include Sc4ry::Constants
69
+
70
+ # config from given definition passed in constructor
48
71
  attr_reader :config
49
72
 
73
+ # the mapping constructor from a given definition or the default From Sc4ry config (Constant)
74
+ # @param [Hash] definition a config hash
75
+ # @note creating dynamically accessors on config record given in definition
50
76
  def initialize(definition: DEFAULT_CONFIG)
51
77
  @config = definition
52
78
  @config.each do |key,value|
@@ -1,7 +1,14 @@
1
+ # Sc4ry module
2
+ # @note namespace
1
3
  module Sc4ry
4
+ # Sc4ry::Constants module
5
+ # @note namespace
2
6
  module Constants
3
7
 
8
+ # notifiers available in Sc4ry natively
4
9
  CURRENT_NOTIFIERS = [:prometheus, :mattermost]
10
+
11
+ # the Sc4ry default config entries and values
5
12
  DEFAULT_CONFIG = {
6
13
  :max_failure_count => 5,
7
14
  :timeout_value => 20,
@@ -16,6 +23,7 @@ module Sc4ry
16
23
  :exceptions => [StandardError, RuntimeError]
17
24
  }
18
25
 
26
+ # Default config supported entries with format and Proc checker for {Sc4ry::Config::Validator}
19
27
  DEFAULT_CONFIG_FORMATS = {
20
28
  :max_failure_count => {:proc => Proc::new {|item| item.class == Integer}, :desc => "must be an Integer"},
21
29
  :timeout_value => {:proc => Proc::new {|item| item.class == Integer}, :desc => "must be an Integer"},