sc4ry 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f4cbfc8c2a7a821c3374916cdd69650a91f1eca5faa4dbbd93ac94e29dae5f89
4
- data.tar.gz: dfa68d210342122e96e6f9fcd234fa73f6fefee667addac8371424b39c1b63d4
3
+ metadata.gz: 5a0a0b0ccc0176505d96bfe85b978f155a989db942cc031972d7c31f24db0d2a
4
+ data.tar.gz: 1e0a528951e291efb0f04b05eaa6ae0897a6a98fb3834b11e7a8e45597848da4
5
5
  SHA512:
6
- metadata.gz: 82590002c1ac457715776b0be304d77fa2903885cc4dc21ee45cea87ee070648661b48520453ab011cd287da49997990b4e607940a54954f5f82b5c884089715
7
- data.tar.gz: 8b63d6b39cee270a1e1ab38ffcde491b746011126615bc4a5908b9f8790017f0c30c8899453ca1848ee4022f8528a0edd61587b583d58a8404e4eef139ecbb84
6
+ metadata.gz: c0159b1b8254dbc358eb68b33cb96cafdd5007c065e549ce307fbeacfeaf22f4739181b996fb62ce27dba3b33947eccd6e1d497970c0c218d8ec199633d3f480
7
+ data.tar.gz: 58280b4b7fe4cc20c30738aabaf258e35efc349dc0df1d2211a058e3b9acd7d61f55df9b3a9cda01b5493c9cfd48bd96993835460c5da8e4205f8a85f74e9559
data/.rubocop.yml ADDED
@@ -0,0 +1,47 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2022-07-26 15:23:44 UTC using RuboCop version 1.32.0.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ AllCops:
10
+ NewCops: enable
11
+ SuggestExtensions: false
12
+ Exclude:
13
+ - 'spec/sc4ry_spec.rb'
14
+ - 'samples/test.rb'
15
+
16
+
17
+ # definitive :
18
+ Style/ClassVars:
19
+ Enabled: false
20
+ Gemspec/RequireMFA:
21
+ Enabled: false
22
+ Security/YAMLLoad:
23
+ Enabled: false
24
+ Style/MutableConstant:
25
+ Enabled: false
26
+
27
+ # to study :
28
+
29
+ Metrics/ClassLength:
30
+ Enabled: false
31
+ Metrics/AbcSize:
32
+ Enabled: false
33
+ Metrics/CyclomaticComplexity:
34
+ Enabled: false
35
+ Metrics/MethodLength:
36
+ Enabled: false
37
+ Metrics/PerceivedComplexity:
38
+ Enabled: false
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+
47
+
data/Gemfile CHANGED
@@ -1,12 +1,13 @@
1
- source "https://rubygems.org"
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in sc4ry.gemspec
4
6
  gemspec
5
7
 
6
- gem "rake", "~> 12.0"
7
- gem "rspec", "~> 3.0"
8
- gem "prometheus-client", "~> 3.0"
9
- gem "rest-client", "~> 2.1"
10
- gem "redis", "~> 4.6"
11
- gem "version", "~> 1.1"
12
-
8
+ gem 'prometheus-client', '~> 3.0'
9
+ gem 'rake', '~> 12.0'
10
+ gem 'redis', '~> 4.6'
11
+ gem 'rest-client', '~> 2.1'
12
+ gem 'rspec', '~> 3.0'
13
+ gem 'version', '~> 1.1'
data/README.md CHANGED
@@ -43,83 +43,282 @@ Or install it yourself as:
43
43
  ### Circuits States Worflow
44
44
 
45
45
  ![Sc4ry workflow](assets/images/sc4ry_workflow.png)
46
- ### sample with Restclient
46
+ ### Quickstart : sample with Restclient
47
+
48
+ A quick circuit test :
49
+ create a test script lile test.rb :
47
50
 
48
51
  ```ruby
49
52
 
50
- require 'rubygems'
51
- require 'sc4ry'
53
+ require 'rubygems'
54
+ require 'sc4ry'
52
55
 
56
+ include Sc4ry
53
57
 
54
- puts 'Initial default config'
55
- pp Sc4ry::Circuits.default_config
58
+ Circuits.register circuit: :mycircuit, config: {:notifiers => [:prometheus,:mattermost],
59
+ :exceptions => [Errno::ECONNREFUSED, URI::InvalidURIError]}
56
60
 
61
+ Circuits.run do # circuit: :mycircuit is optional, run work with the first circuit registered
62
+ puts RestClient.get('http://your_service/endpoint')
63
+ end
57
64
 
58
- Sc4ry::Circuits.merge_default_config diff: {timeout: true }
59
- # or with a block
60
- Sc4ry::Circuits.configure do |spec|
61
- spec.max_time = 12
62
- end
65
+
63
66
 
67
+ ```
64
68
 
65
- # display default config
66
- puts 'Default config'
67
- pp Sc4ry::Circuits.default_config
69
+ ### the Sc4ry Config default values :
68
70
 
71
+ Default values, circuit is half open before one of the max count is reached :
69
72
 
70
- # defining a circuit, config must be empty or override from default
71
- Sc4ry::Circuits.register circuit: :test, config: {:notifiers => [:prometheus,:mattermost], :exceptions => [Errno::ECONNREFUSED, URI::InvalidURIError] }
72
- # or with a block
73
- Sc4ry::Circuits.register circuit: :test2 do |spec|
74
- spec.exceptions = [Errno::ECONNREFUSED]
75
- end
76
- # or
77
- Sc4ry::Circuits.register circuit: :test3
73
+ * _:max_failure_count_
74
+ <br>*description* : maximum failure before opening circuit
75
+ <br>*default value* : 5
76
+ <br>
78
77
 
78
+ * _:timeout_value_
79
+ <br>*description* : timeout value, if :timeout => true
80
+ <br>*default value* : 20
81
+ <br>
79
82
 
83
+ * _:timeout_
84
+ <br>*description* : (de)activate internal timeout
85
+ <br>*default value* : false
86
+ <br>
80
87
 
81
- puts "Circuits list"
82
- pp Sc4ry::Circuits::list
88
+ * _:max_timeout_count_
89
+ <br>*description* : maximum timeout try before opening circuit
90
+ <br>*default value** : 5
91
+ <br>
83
92
 
84
- # Config an alternate logger
85
- Sc4ry::Logger.register name: :perso, instance: ::Logger.new('/tmp/logfile.log')
86
- Sc4ry::Logger::current = :stdout
93
+ * _:max_time_
94
+ <br>*description* : maximum time for a circuit run
95
+ <br>*default value* : 10
96
+ <br>
87
97
 
98
+ * _:max_overtime_count_
99
+ <br>*description* : maximum count of overtime before opening circuit
100
+ <br>*default value* : 3
101
+ <br>
88
102
 
89
- # default values, circuit is half open before one of the max count is reached
103
+ * _:check_delay_
104
+ <br>*description* : delay after opening, before trying again to closed circuit or after an other check
105
+ <br>*default value* : 30
106
+ <br>
90
107
 
91
- # DEFAULT_CONFIG = {
92
- # :max_failure_count => 5,
93
- # :timeout_value => 20,
94
- # :timeout => false,
95
- # :max_timeout_count => 5,
96
- # :max_time => 10,
97
- # :max_overtime_count => 3,
98
- # :check_delay => 30,
99
- # :notifiers => [],
100
- # :forward_unknown_exceptions => true,
101
- # :raise_on_opening => false,
102
- # :exceptions => [StandardError, RuntimeError]
103
- # }
108
+ * _:notifiers_
109
+ <br>*description* : active notifier, must be :symbol in [:prometheus, :mattermost]
110
+ <br>*default value* : []
111
+ <br>
104
112
 
105
- # display configuration for a specific circuit
106
- Sc4ry::Circuits::list.each do |circuit|
107
- puts "Config #{circuit} :"
108
- pp Sc4ry::Circuits.get circuit: circuit
109
- end
113
+ * _:forward_unknown_exceptions_
114
+ <br>*description* : (de)activate forwarding of unknown exceptions, just log in DEBUG if false
115
+ <br>*default value* : true
116
+ <br>
110
117
 
111
- # sample Mattermost notification
112
- #Sc4ry::Notifiers::config({:name => :mattermost, :config => {:url => 'https://mattermost.mycorp.com', :token => "<TOKEN>"}})
118
+ * _:raise_on_opening_
119
+ <br>*description* : (de)activate raise specific Sc4ry exceptions ( CircuitBreaked ) if circuit opening
120
+ <br>*default value* : false
121
+ <br>
113
122
 
114
- # sample loop
115
- 100.times do
116
- sleep 1
117
- Sc4ry::Circuits.run circuit: :test do
118
- # for the test choose or build an endpoint you must shutdown
119
- puts RestClient.get('http://<URL_OF_AN_ENDPOINT>')
120
- end
121
- end
123
+ * _:exceptions_
124
+ <br>*description* : [StandardError, RuntimeError]
125
+ <br>*default value* : list of selected Exceptions considered for failure, others are SKIPPED.
126
+
127
+ ### Global overview for all features
128
+
129
+ This script could be usefull to test all feature on your installation
130
+
131
+ You need:
132
+ * Redis
133
+ * Prometheus pushgateway
134
+ * an endpoint if you want to check real endpoint
135
+ * a Mattermost/Slack incoming webhook (optional)
136
+
137
+ You could gate all this pre-requistes simply if you jave docker up on your machine
138
+
139
+ ```
140
+ $ docker pull redis:latest
141
+ $ docker run --rm -d -p 6379:6379/tcp redis:latest
142
+ $ docker pull prom/pushgateway:latest
143
+ $ docker run --rm -d -p 9091:9091 prom/pushgateway:latest
144
+ $ git clone https://github.com/Ultragreen/MockWS.git
145
+ $ cd MockWS
146
+ $ rackup
147
+ ```
148
+
149
+ create the test script like :
150
+
151
+ ```ruby
152
+
153
+ require 'rubygems'
154
+ require 'sc4ry'
155
+
156
+
157
+ include Sc4ry
158
+
159
+ # display of default Sc4ry config
160
+ puts '1.1/ CONFIG : Initial default config'
161
+ Circuits.default_config.each do |item,value|
162
+ puts " * #{item} : #{value}"
163
+ end
164
+ puts ''
165
+
166
+ # testing the two ways to configure Sc4ry default config
167
+ puts "1.2/ CONFIG : modifying default config activate timout and set max_time to 12"
168
+ Circuits.merge_default_config diff: {timeout: true }
169
+ Circuits.configure do |spec|
170
+ spec.max_time = 12
171
+ end
172
+ puts ''
173
+
174
+ # display default config, must be override with a nested hash by calling default_config= method
175
+ puts '1.3/ CONFIG : Default config updated:'
176
+ Circuits.default_config.each do |item,value|
177
+ puts " * #{item} : #{value}"
178
+ end
179
+ puts ''
180
+
181
+ # display current data Store
182
+ print "2.1/ STORE : Current datastore backend : "
183
+ puts Circuits.store.current
184
+ puts ''
185
+
186
+
187
+ # display available backend
188
+ puts "2.2/ STORE : List of existing backends : "
189
+ Circuits.store.list_backend.each do |backend|
190
+ puts " - #{backend}"
191
+ end
192
+ puts ''
193
+
194
+
195
+ # display Redis backend config in store before change
196
+ puts '2.3/ STORE : display default config of redis backend'
197
+ Circuits.store.get_config(backend: :redis).each do |item,value|
198
+ puts " * #{item} : #{value}"
199
+ end
200
+ puts ''
201
+
202
+ # reconfigure a backend
203
+ puts "2.4/ STORE : reconfigure Redis backend"
204
+ Circuits.store.config_backend name: :redis, config: {:host => 'localhost', :port => 6379, :db => 10 }
205
+ puts
122
206
 
207
+ # display after
208
+ puts '2.5/ STORE : display altered config of redis backend'
209
+ Circuits.store.get_config(backend: :redis).each do |item,value|
210
+ puts " * #{item} : #{value}"
211
+ end
212
+ puts ''
213
+
214
+
215
+ # change backend
216
+
217
+ puts '2.6/ STORE : change to redis backend (NEED a Redis installed) '
218
+ puts " $ docker pull redis:latest"
219
+ puts " $ docker run --rm -d -p 6379:6379/tcp redis:latest"
220
+ Circuits.store.change_backend name: :redis
221
+ puts ''
222
+
223
+ puts '2.7/ STORE : flush redis backend, just for test, and for idempotency (NEED a Redis installed) '
224
+ Circuits.store.flush
225
+ puts ''
226
+
227
+ # defining a circuit, config must be empty or override from default
228
+ puts "3.1/ CIRCUIT : registering a circuit by merge :"
229
+ Circuits.register circuit: :test, config: {:notifiers => [:prometheus,:mattermost], :exceptions => [Errno::ECONNREFUSED, URI::InvalidURIError] }
230
+ puts ""
231
+
232
+ puts "3.2/ CIRCUIT : registering a circuit by block :"
233
+ Circuits.register circuit: :test2 do |spec|
234
+ spec.exceptions = [Errno::ECONNREFUSED]
235
+ end
236
+ puts ''
237
+
238
+ puts "3.3/ CIRCUIT : registering a circuit by default :"
239
+ Circuits.register circuit: :test3
240
+ puts ''
241
+
242
+ puts "3.4/ CIRCUITS : Circuits list"
243
+ Circuits::list.each do |circuit|
244
+ puts " * #{circuit}"
245
+ end
246
+ puts ""
247
+
248
+ puts "3.5/ CIRCUIT : display a circuit config :test3 :"
249
+ Circuits.get(circuit: :test3).each do |item,value|
250
+ puts " * #{item} : #{value}"
251
+ end
252
+ puts ""
253
+
254
+ puts "3.6/ CIRCUIT : update config of :test3 => :raise_on_opening == true :"
255
+ Circuits.update_config circuit: :test3, config: {raise_on_opening: true}
256
+ puts ''
257
+
258
+ puts "3.7/ CIRCUIT : display a circuit config :test3 after change :"
259
+ Circuits.get(circuit: :test3).each do |item,value|
260
+ puts " * #{item} : #{value}"
261
+ end
262
+ puts ""
263
+
264
+
265
+ puts "3.8/ unregister a circuit : :test2 :"
266
+ Circuits.unregister circuit: :test2
267
+ puts ''
268
+
269
+ puts "3.9/ CIRCUITS : Circuits list after unregister"
270
+ Circuits::list.each do |circuit|
271
+ puts " * #{circuit}"
272
+ end
273
+ puts ""
274
+
275
+ # Config an alternate logger
276
+
277
+ puts "4.1/ LOGGER : register a logger on file "
278
+ Circuits.loggers.register name: :perso, instance: ::Logger.new('/tmp/logfile.log')
279
+ puts ''
280
+
281
+ puts "4.2/ LOGGER : get the list of available loggers"
282
+ Circuits.loggers.list_available.each do |logger|
283
+ puts " * #{logger}"
284
+ end
285
+ puts ''
286
+
287
+ puts "4.3/ LOGGER : change logger to :perso"
288
+ Circuits.loggers.current = :perso
289
+ puts ""
290
+
291
+
292
+
293
+
294
+
295
+ # sample Mattermost notification
296
+ puts "5/ set notifier mattermost on dummy url, change with your slack or mattermost server"
297
+ Sc4ry::Notifiers::config name: :mattermost, config: {:url => 'https://mattermost.mycorp.com', :token => "<TOKEN>"}
298
+ puts ""
299
+
300
+
301
+ # sample loop
302
+ puts "6/ running circuits test, please wait ... (see /tmp/logfile.log for result)"
303
+ puts " check endoint status for different result, you cloud use http://github.com/Ultragreen/MockWS for testing endpoint, on an other tty"
304
+ puts " $ git clone https://github.com/Ultragreen/MockWS.git"
305
+ puts " $ cd MockWS"
306
+ puts " $ rackup"
307
+ begin
308
+ 10.times do
309
+ sleep 1
310
+ Circuits.run circuit: :test do
311
+ # for the test choose or build an endpoint you must shutdown
312
+ puts RestClient.get('http://localhost:9292/test2/data')
313
+ end
314
+ end
315
+ rescue Interrupt
316
+ puts 'Interrputed'
317
+ ensure
318
+ Circuits.store.flush
319
+ end
320
+
321
+ puts "end"
123
322
  ```
124
323
 
125
324
  ## Development
data/Rakefile CHANGED
@@ -1,37 +1,44 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
3
5
  require 'yard'
4
- require 'yard/rake/yardoc_task.rb'
6
+ require 'yard/rake/yardoc_task'
5
7
  require 'code_statistics'
6
- require "roodi"
7
- require "roodi_task"
8
- require "version"
8
+ require 'version'
9
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
-
10
+ require 'rubocop//rake_task'
18
11
 
12
+ Rake::VersionTask.new
13
+ RuboCop::RakeTask.new
19
14
  RSpec::Core::RakeTask.new(:spec)
20
15
 
21
- task :default => :spec
22
-
16
+ task default: :spec
23
17
 
24
18
  YARD::Rake::YardocTask.new do |t|
25
- t.files = [ 'lib/**/*.rb', '-', 'doc/**/*','spec/**/*_spec.rb']
26
- t.options += ['-o', "yardoc"]
19
+ t.files = ['lib/**/*.rb', '-', 'doc/**/*', 'spec/**/*_spec.rb']
20
+ t.options += ['-o', 'yardoc']
27
21
  end
28
22
  YARD::Config.load_plugin('yard-rspec')
29
-
23
+
30
24
  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
25
+ task :clobber do
26
+ begin
27
+ rm_r 'yardoc'
28
+ rescue StandardError
29
+ nil
30
+ end
31
+ begin
32
+ rm_r '.yardoc'
33
+ rescue StandardError
34
+ nil
35
+ end
36
+ begin
37
+ rm_r 'pkg'
38
+ rescue StandardError
39
+ nil
40
+ end
41
+ end
35
42
  end
36
- end
37
- task :clobber => "yardoc:clobber"
43
+
44
+ task clobber: 'yardoc:clobber'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.2.1
Binary file
data/bin/console CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- require "bundler/setup"
4
- require "sc4ry"
4
+ require 'bundler/setup'
5
+ require 'sc4ry'
5
6
 
6
7
  # You can add fixtures and/or initialization code here to make experimenting
7
8
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +11,5 @@ require "sc4ry"
10
11
  # require "pry"
11
12
  # Pry.start
12
13
 
13
- require "irb"
14
+ require 'irb'
14
15
  IRB.start(__FILE__)
@@ -1 +1,3 @@
1
- Dir[File.dirname(__FILE__) + '/*.rb'].sort.each { |file| require file unless File.basename(file) == 'init.rb' }
1
+ # frozen_string_literal: true
2
+
3
+ Dir["#{File.dirname(__FILE__)}/*.rb"].sort.each { |file| require file unless File.basename(file) == 'init.rb' }
@@ -1,48 +1,47 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Sc4ry module
2
4
  # @note namespace
3
5
  module Sc4ry
4
-
5
6
  # Sc4ry:Backends module
6
7
  # @note namespace
7
8
  module Backends
8
-
9
9
  # class of the memory backend
10
10
  class Memory
11
-
12
11
  # Constructor
13
- # @param [Hash] config Config map
12
+ # @param [Hash] config Config map
14
13
  # @return [Sc4ry::Backends::Memory] a in Memory backend
15
- def initialize(config=nil?)
16
- @data = Hash::new
14
+ def initialize(_config = nil?)
15
+ @data = {}
17
16
  end
18
17
 
19
18
  # return the list of find records in backend for a specific pattern
20
19
  # @return [Array] list of record (for all hostname if hostname is specified)
21
20
  def list
22
- return @data.keys
21
+ @data.keys
23
22
  end
24
23
 
25
24
  # return value of queried record
26
25
  # @param key [Symbol] the name of the record
27
26
  # @return [String] content value of record
28
- def get(key: )
29
- return @data[key]
27
+ def get(key:)
28
+ @data[key]
30
29
  end
31
30
 
32
31
  # defined and store value for specified key
33
32
  # @param key [Symbol] :key the name of the record
34
33
  # @param value [Symbol] :value the content value of the record
35
34
  # @return [String] content value of record
36
- def put(key:, value: )
35
+ def put(key:, value:)
37
36
  @data[key] = value
38
- end
37
+ end
39
38
 
40
39
  # delete a specific record
41
40
  # @param params [Symbol] the name of the record
42
- # @return [Boolean] status of the operation
43
- def del(key: )
41
+ # @return [Boolean] status of the operation
42
+ def del(key:)
44
43
  @data.delete key
45
- end
44
+ end
46
45
 
47
46
  # flush all records in backend
48
47
  # @return [Boolean] status of the operation
@@ -53,10 +52,9 @@ module Sc4ry
53
52
  # verifiy a specific record existence
54
53
  # @param key [Symbol] the name of the record
55
54
  # @return [Boolean] presence of the record
56
- def exist?(key: )
57
- return @data.include? key
55
+ def exist?(key:)
56
+ @data.include? key
58
57
  end
59
-
60
58
  end
61
59
  end
62
- end
60
+ end