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 +4 -4
- data/.rubocop.yml +47 -0
- data/Gemfile +9 -8
- data/README.md +254 -55
- data/Rakefile +32 -25
- data/VERSION +1 -1
- data/assets/images/sc4ry_workflow.png +0 -0
- data/bin/console +4 -3
- data/lib/sc4ry/backends/init.rb +3 -1
- data/lib/sc4ry/backends/memory.rb +16 -18
- data/lib/sc4ry/backends/redis.rb +59 -62
- data/lib/sc4ry/circuits.rb +111 -105
- data/lib/sc4ry/config.rb +89 -81
- data/lib/sc4ry/constants.rb +50 -46
- data/lib/sc4ry/dependencies.rb +3 -3
- data/lib/sc4ry/exceptions.rb +36 -42
- data/lib/sc4ry/exporters/init.rb +3 -1
- data/lib/sc4ry/helpers.rb +29 -34
- data/lib/sc4ry/logger.rb +24 -23
- data/lib/sc4ry/notifiers/init.rb +34 -33
- data/lib/sc4ry/notifiers/mattermost.rb +37 -38
- data/lib/sc4ry/notifiers/prometheus.rb +15 -19
- data/lib/sc4ry/run_controller.rb +23 -30
- data/lib/sc4ry/store.rb +45 -39
- data/lib/sc4ry/version.rb +2 -1
- data/lib/sc4ry.rb +3 -9
- data/samples/test.rb +159 -0
- data/sc4ry.gemspec +19 -19
- metadata +23 -22
- data/ultragreen_roodi_coding_convention.yml +0 -25
data/lib/sc4ry/notifiers/init.rb
CHANGED
@@ -1,57 +1,58 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Dir["#{File.dirname(__FILE__)}/*.rb"].sort.each { |file| require file unless File.basename(file) == 'init.rb' }
|
2
4
|
|
3
5
|
# Sc4ry module
|
4
6
|
# @note namespace
|
5
|
-
module Sc4ry
|
6
|
-
|
7
|
-
#
|
8
|
-
|
9
|
-
module Notifiers
|
10
|
-
|
7
|
+
module Sc4ry
|
8
|
+
# Sc4ry::Notifiers module
|
9
|
+
# @note namespace
|
10
|
+
module Notifiers
|
11
11
|
# default notifiers specifications
|
12
|
-
DEFAULT_NOTIFIERS = {:
|
13
|
-
:
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
DEFAULT_NOTIFIERS = { prometheus: { class: Sc4ry::Notifiers::Prometheus, config: { url: 'http://localhost:9091' } },
|
13
|
+
mattermost: { class: Sc4ry::Notifiers::Mattermost, config: { url: 'http://localhost:9999', token: '<CHANGE_ME>' } } }
|
14
|
+
@@notifiers_list = DEFAULT_NOTIFIERS.dup
|
15
|
+
|
17
16
|
# class method how display a specific notifier config
|
18
17
|
# @param notifier [Symbol] a notifier name
|
19
|
-
# @return [Hash] the config
|
20
|
-
def
|
21
|
-
|
22
|
-
|
18
|
+
# @return [Hash] the config
|
19
|
+
def self.display_config(notifier:)
|
20
|
+
unless @@notifiers_list.include? notifier
|
21
|
+
raise Sc4ry::Exceptions::Sc4ryNotifierError,
|
22
|
+
"Notifier #{notifier} not found"
|
23
|
+
end
|
24
|
+
|
25
|
+
@@notifiers_list[notifier][:config]
|
23
26
|
end
|
24
27
|
|
25
28
|
# class method how return the list of known notifiers
|
26
29
|
# @return [Array] a list of [Symbol] notifiers name
|
27
|
-
def
|
28
|
-
|
30
|
+
def self.list
|
31
|
+
@@notifiers_list.keys
|
29
32
|
end
|
30
33
|
|
31
34
|
# class method how return a specific notifier by name
|
32
35
|
# @param name [Symbol] a notifier name
|
33
|
-
# @return [Hash] the notifier structure
|
34
|
-
def
|
35
|
-
|
36
|
+
# @return [Hash] the notifier structure
|
37
|
+
def self.get(name:)
|
38
|
+
@@notifiers_list[name]
|
36
39
|
end
|
37
40
|
|
38
|
-
# class method how register a specific notifier
|
41
|
+
# class method how register a specific notifier
|
39
42
|
# @param name [Symbol] a notifier name
|
40
|
-
# @param definition [Hash] a notifier definition
|
41
|
-
# @return [Hash] the notifier structure
|
42
|
-
def
|
43
|
+
# @param definition [Hash] a notifier definition
|
44
|
+
# @return [Hash] the notifier structure
|
45
|
+
def self.register(name:, definition:)
|
43
46
|
@@notifiers_list[name] = definition
|
44
47
|
end
|
45
48
|
|
46
|
-
|
47
|
-
# class method how configure a specific notifier
|
49
|
+
# class method how configure a specific notifier
|
48
50
|
# @param name [Symbol] a notifier name
|
49
|
-
# @param config [Hash] a notifier config
|
50
|
-
# @return [Hash] the notifier structure
|
51
|
-
def
|
51
|
+
# @param config [Hash] a notifier config
|
52
|
+
# @return [Hash] the notifier structure
|
53
|
+
def self.config(name:, config:)
|
52
54
|
@@notifiers_list[name][:config] = config
|
53
|
-
|
55
|
+
config
|
54
56
|
end
|
55
|
-
|
57
|
+
end
|
56
58
|
end
|
57
|
-
|
@@ -1,43 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Sc4ry module
|
2
|
-
# @note namespace
|
4
|
+
# @note namespace
|
3
5
|
module Sc4ry
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
request.body = ::JSON.dump(payload)
|
30
|
-
response = ::Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
|
31
|
-
http.request(request)
|
32
|
-
end
|
33
|
-
|
34
|
-
else
|
35
|
-
Sc4ry::Helpers.log level: :warn, message: "Mattermost Notifier : can't notify Mattermost not reachable."
|
36
|
-
end
|
37
|
-
rescue URI::InvalidURIError
|
38
|
-
Sc4ry::Helpers.log level: :warn, message: "Mattermost Notifier : URL malformed"
|
39
|
-
end
|
6
|
+
# Sc4ry::Notifiers module
|
7
|
+
# @note namespace
|
8
|
+
module Notifiers
|
9
|
+
# Mattermost Notifier class
|
10
|
+
class Mattermost
|
11
|
+
# send metrics to Prometheus PushGateway
|
12
|
+
# @return [Bool]
|
13
|
+
def self.notify(options = {})
|
14
|
+
config = Sc4ry::Notifiers.get(name: :mattermost)[:config]
|
15
|
+
status = options[:config][:status][:general]
|
16
|
+
circuit = options[:circuit]
|
17
|
+
begin
|
18
|
+
uri = URI.parse("#{config[:url]}/hooks/#{config[:token]}")
|
19
|
+
message = "notifying for circuit #{circuit}, state : #{status}."
|
20
|
+
if Sc4ry::Helpers.verify_service url: config[:url]
|
21
|
+
request = ::Net::HTTP::Post.new(uri)
|
22
|
+
request.content_type = 'application/json'
|
23
|
+
req_options = {
|
24
|
+
use_ssl: uri.scheme == 'https'
|
25
|
+
}
|
26
|
+
payload = { 'text' => "message : #{message} from #{Socket.gethostname}", 'username' => 'Sc4ry' }
|
27
|
+
Sc4ry::Helpers.log level: :debug, message: "Mattermost Notifying : #{message}"
|
28
|
+
request.body = ::JSON.dump(payload)
|
29
|
+
::Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
|
30
|
+
http.request(request)
|
40
31
|
end
|
32
|
+
|
33
|
+
else
|
34
|
+
Sc4ry::Helpers.log level: :warn, message: "Mattermost Notifier : can't notify Mattermost not reachable."
|
35
|
+
end
|
36
|
+
rescue URI::InvalidURIError
|
37
|
+
Sc4ry::Helpers.log level: :warn, message: 'Mattermost Notifier : URL malformed'
|
41
38
|
end
|
39
|
+
end
|
42
40
|
end
|
43
|
-
end
|
41
|
+
end
|
42
|
+
end
|
@@ -1,43 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Sc4ry module
|
2
4
|
# @note namespace
|
3
5
|
module Sc4ry
|
4
|
-
|
5
6
|
# Sc4ry::Notifiers module
|
6
7
|
# @note namespace
|
7
8
|
module Notifiers
|
8
|
-
|
9
|
-
|
10
9
|
# Prometheus notifier class
|
11
10
|
class Prometheus
|
12
|
-
|
13
|
-
@@
|
14
|
-
|
11
|
+
@@registry = ::Prometheus::Client::Registry.new
|
12
|
+
@@metric_circuit_state = ::Prometheus::Client::Gauge.new(:cuircuit_state,
|
13
|
+
docstring: 'Sc4ry metric : state of a circuit',
|
14
|
+
labels: [:circuit])
|
15
15
|
|
16
16
|
@@registry.register(@@metric_circuit_state)
|
17
17
|
|
18
|
-
|
19
|
-
|
20
18
|
# send metrics to Prometheus PushGateway
|
21
19
|
# @return [Bool]
|
22
|
-
def
|
20
|
+
def self.notify(options = {})
|
23
21
|
@config = Sc4ry::Notifiers.get(name: :prometheus)[:config]
|
24
22
|
status = options[:config][:status][:general]
|
25
23
|
circuit = options[:circuit]
|
26
|
-
status_map = {:
|
27
|
-
if Sc4ry::Helpers
|
28
|
-
|
29
|
-
@@metric_circuit_state.set(status_map[status], labels: {circuit: circuit.to_s })
|
30
|
-
Sc4ry::Helpers.log level: :debug,
|
24
|
+
status_map = { open: 0, half_open: 1, closed: 2 }
|
25
|
+
if Sc4ry::Helpers.verify_service url: @config[:url]
|
26
|
+
|
27
|
+
@@metric_circuit_state.set(status_map[status], labels: { circuit: circuit.to_s })
|
28
|
+
Sc4ry::Helpers.log level: :debug,
|
29
|
+
message: "Prometheus Notifier : notifying for circuit #{circuit}, state : #{status}."
|
31
30
|
|
32
|
-
|
31
|
+
::Prometheus::Client::Push.new(job: 'Sc4ry', instance: Socket.gethostname,
|
32
|
+
gateway: @config[:url]).add(@@registry)
|
33
33
|
else
|
34
34
|
Sc4ry::Helpers.log level: :warn, message: "Prometheus Notifier : can't notify Push Gateway not reachable."
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
38
|
-
|
39
|
-
|
40
|
-
|
41
38
|
end
|
42
|
-
|
43
39
|
end
|
data/lib/sc4ry/run_controller.rb
CHANGED
@@ -1,16 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
3
|
# Sc4ry module
|
3
|
-
# @note namespace
|
4
|
+
# @note namespace
|
4
5
|
module Sc4ry
|
5
|
-
|
6
6
|
# class Facility to run and update values/status for a circuit Proc
|
7
7
|
class RunController
|
8
|
-
|
9
8
|
# return the execution time of the proc
|
10
9
|
attr_reader :execution_time
|
11
10
|
|
12
11
|
# constructor
|
13
|
-
# @param [Hash] circuit the data of the circuit
|
12
|
+
# @param [Hash] circuit the data of the circuit
|
14
13
|
def initialize(circuit = {})
|
15
14
|
@circuit = circuit
|
16
15
|
@execution_time = 0
|
@@ -22,59 +21,53 @@ module Sc4ry
|
|
22
21
|
# return if the Proc failed on a covered exception by this circuit
|
23
22
|
# @return [Boolean]
|
24
23
|
def failed?
|
25
|
-
|
26
|
-
end
|
24
|
+
@failure
|
25
|
+
end
|
27
26
|
|
28
27
|
# return if the Proc overtime the specified time of the circuit
|
29
28
|
# @return [Boolean]
|
30
|
-
def overtimed?
|
31
|
-
|
29
|
+
def overtimed?
|
30
|
+
@overtime
|
32
31
|
end
|
33
32
|
|
34
33
|
# return if the Proc timeout the timeout defined value of the circuit, if timeout is active
|
35
34
|
# @return [Boolean]
|
36
|
-
def timeout?
|
37
|
-
|
35
|
+
def timeout?
|
36
|
+
@timeout
|
38
37
|
end
|
39
38
|
|
40
39
|
# run and update values for the bloc given by keyword
|
41
40
|
# @param [Proc] block a block to run and calculate
|
42
41
|
# @return [Hash] a result Hash
|
43
|
-
def run(block:
|
42
|
+
def run(block:)
|
44
43
|
start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
45
|
-
begin
|
44
|
+
begin
|
46
45
|
if @circuit[:timeout] == true
|
47
|
-
Timeout
|
46
|
+
Timeout.timeout(@circuit[:timeout_value]) do
|
48
47
|
block.call
|
49
48
|
end
|
50
49
|
@timeout = false
|
51
50
|
else
|
52
51
|
block.call
|
53
52
|
end
|
54
|
-
rescue
|
53
|
+
rescue StandardError => e
|
55
54
|
@last_exception = e.class.to_s
|
56
|
-
if e.
|
55
|
+
if e.instance_of?(Timeout::Error)
|
57
56
|
@timeout = true
|
58
57
|
elsif @circuit[:exceptions].include? e.class
|
59
58
|
@failure = true
|
60
|
-
|
61
|
-
|
59
|
+
elsif @circuit[:forward_unknown_exceptions]
|
60
|
+
raise e.class, "Sc4ry forward: #{e.message}"
|
61
|
+
else
|
62
|
+
Sc4ry::Helpers.log level: :debug, message: "skipped : #{@last_exception}"
|
62
63
|
|
63
|
-
|
64
|
-
else
|
65
|
-
Sc4ry::Helpers.log level: :debug, message: "skipped : #{@last_exception}"
|
66
|
-
end
|
67
|
-
|
68
|
-
end
|
64
|
+
end
|
69
65
|
end
|
70
66
|
@end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
71
67
|
@execution_time = @end_time - start_time
|
72
|
-
@overtime = @execution_time > @circuit[:max_time]
|
73
|
-
|
74
|
-
|
68
|
+
@overtime = @execution_time > @circuit[:max_time]
|
69
|
+
{ failure: @failure, overtime: @overtime, timeout: @timeout, execution_time: @execution_time,
|
70
|
+
end_time: @end_time, last_exception: @last_exception }
|
75
71
|
end
|
76
|
-
|
77
|
-
|
78
|
-
|
79
72
|
end
|
80
|
-
end
|
73
|
+
end
|
data/lib/sc4ry/store.rb
CHANGED
@@ -1,29 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Sc4ry module
|
2
4
|
# @note namespace
|
3
5
|
module Sc4ry
|
4
|
-
|
5
|
-
# Sc4ry::
|
6
|
-
#
|
7
|
-
# @note must be accessed by {Sc4ry::Circuits.store}
|
6
|
+
# Sc4ry::Store class
|
7
|
+
# Store Class Provider/manager singleton Forwarder on {Sc4ry::Backends::Memory} or {Sc4ry::Backends::Redis}
|
8
|
+
# @note must be accessed by {Sc4ry::Circuits.store}
|
8
9
|
class Store
|
9
|
-
|
10
10
|
@@current = :memory
|
11
11
|
|
12
12
|
extend Forwardable
|
13
13
|
include Singleton
|
14
14
|
|
15
|
-
@@backends = {:
|
16
|
-
|
15
|
+
@@backends = { memory: { class: Sc4ry::Backends::Memory, config: {} },
|
16
|
+
redis: { class: Sc4ry::Backends::Redis, config: { host: 'localhost', port: 6379, db: 1 } } }
|
17
17
|
|
18
18
|
# accessor on current backend (default :memory)
|
19
19
|
attr_reader :be
|
20
|
-
|
20
|
+
|
21
21
|
def_delegators :@be, :put, :get, :flush, :exist?, :del, :list
|
22
22
|
|
23
23
|
# constructor pointing on :memory backend
|
24
24
|
def initialize
|
25
|
-
change_backend name: @@current
|
26
|
-
end
|
25
|
+
change_backend name: @@current
|
26
|
+
end
|
27
27
|
|
28
28
|
# return the current backend
|
29
29
|
# @return [Object] in {Sc4ry::Backends::Memory} or {Sc4ry::Backends::Redis}
|
@@ -31,75 +31,81 @@ module Sc4ry
|
|
31
31
|
# include Sc4ry
|
32
32
|
# puts Circuits.store.current
|
33
33
|
def current
|
34
|
-
|
34
|
+
@@current
|
35
35
|
end
|
36
36
|
|
37
37
|
# return the config of a specific backend
|
38
|
-
# @param [Symbol] backend the name the backend
|
39
|
-
# @return [Hash] the config of the backend
|
38
|
+
# @param [Symbol] backend the name the backend
|
39
|
+
# @return [Hash] the config of the backend
|
40
40
|
# @raise Sc4ry::Exceptions::Sc4ryBackendError if backend is not found
|
41
41
|
# @example usage
|
42
42
|
# include Sc4ry
|
43
43
|
# puts Circuits.store.get_config backend: :redis
|
44
|
-
def get_config(backend:
|
44
|
+
def get_config(backend:)
|
45
45
|
raise Sc4ry::Exceptions::Sc4ryBackendError, "backend #{backend} not found" unless @@backends.include? backend
|
46
|
-
|
46
|
+
|
47
|
+
@@backends[backend][:config]
|
47
48
|
end
|
48
49
|
|
49
|
-
# list backend available
|
50
|
+
# list backend available
|
50
51
|
# @return [Array] of Symbol the list of backend name
|
51
52
|
# @example usage
|
52
53
|
# include Sc4ry
|
53
54
|
# puts Circuits.store.list_backend
|
54
55
|
def list_backend
|
55
|
-
|
56
|
+
@@backends.keys
|
56
57
|
end
|
57
58
|
|
58
|
-
# change the current backend
|
59
|
-
# @note if changing form :memory to :redis => all values and result are lost and circuits will be lost
|
60
|
-
# @note if changing to :redis, get all the define circuits with values and status (ideal)
|
59
|
+
# change the current backend
|
60
|
+
# @note if changing form :memory to :redis => all values and result are lost and circuits will be lost
|
61
|
+
# @note if changing to :redis, get all the define circuits with values and status (ideal)
|
62
|
+
# @note for distributed worker/instance/runner/services
|
61
63
|
# @param [Symbol] name the name of the target backend
|
62
64
|
# @return [Symbol] the name of the new current backend
|
63
65
|
# @raise Sc4ry::Exceptions::Sc4ryBackendError if backend is not found
|
64
|
-
def change_backend(name:
|
66
|
+
def change_backend(name:)
|
65
67
|
raise Sc4ry::Exceptions::Sc4ryBackendError, "backend #{name} not found" unless @@backends.include? name
|
68
|
+
|
66
69
|
@@current = name
|
67
|
-
@be = @@backends[@@current][:class]
|
68
|
-
|
70
|
+
@be = @@backends[@@current][:class].new(@@backends[@@current][:config])
|
71
|
+
name
|
69
72
|
end
|
70
73
|
|
71
|
-
# register a new backend
|
74
|
+
# register a new backend
|
72
75
|
# @param [Symbol] name the name of the backend
|
73
76
|
# @param [Hash] config the config for this backend
|
74
|
-
# @param [Class] backend_class the class name of the new backend
|
77
|
+
# @param [Class] backend_class the class name of the new backend
|
75
78
|
# @raise Sc4ry::Exceptions::Sc4ryBackendError if backend already exist
|
76
|
-
# @return [Symbol] the name of the backend
|
77
|
-
def register_backend(name:, config: {}
|
78
|
-
raise Sc4ry::Exceptions::Sc4ryBackendError
|
79
|
-
|
80
|
-
|
79
|
+
# @return [Symbol] the name of the backend
|
80
|
+
def register_backend(name:, backend_class:, config: {})
|
81
|
+
raise Sc4ry::Exceptions::Sc4ryBackendError, "backend #{name} already exist" if @@backends.include? name
|
82
|
+
|
83
|
+
@@backends[name] = { config: config, class: backend_class }
|
84
|
+
name
|
81
85
|
end
|
82
86
|
|
83
87
|
# delete the specified backend reference
|
84
88
|
# @param [Symbol] name the name of the target backend
|
85
89
|
# @raise Sc4ry::Exceptions::Sc4ryBackendError if backend is not found, or name == :memory or :redis
|
86
90
|
# @return [Boolean]
|
87
|
-
def delete_backend(name:
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
+
def delete_backend(name:)
|
92
|
+
forbidden_mes = 'Delete forbidden for backend in [:redis,:memory]'
|
93
|
+
notfound_mes = "backend #{name} not found"
|
94
|
+
raise Sc4ry::Exceptions::Sc4ryBackendError, forbidden_mes if %i[memory redis].include? name
|
95
|
+
raise Sc4ry::Exceptions::Sc4ryBackendError, notfound_mes unless @@backends.include? name
|
96
|
+
|
97
|
+
@@backends.delete(name)
|
91
98
|
end
|
92
|
-
|
99
|
+
|
93
100
|
# change the specified backend config
|
94
101
|
# @param [Symbol] name the name of the target backend
|
95
102
|
# @param [Hash] config the config of the specified backend
|
96
103
|
# @raise Sc4ry::Exceptions::Sc4ryBackendError if backend is not found, or name == :memory
|
97
104
|
def config_backend(name:, config:)
|
98
105
|
raise Sc4ry::Exceptions::Sc4ryBackendError, "backend #{name} not found" unless @@backends.include? name
|
99
|
-
raise Sc4ry::Exceptions::Sc4ryBackendError,
|
106
|
+
raise Sc4ry::Exceptions::Sc4ryBackendError, 'backend :memory not need config' if name == :memory
|
107
|
+
|
100
108
|
@@backends[name][:config] = config
|
101
109
|
end
|
102
|
-
|
103
|
-
|
104
110
|
end
|
105
|
-
end
|
111
|
+
end
|
data/lib/sc4ry/version.rb
CHANGED
data/lib/sc4ry.rb
CHANGED
data/samples/test.rb
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'sc4ry'
|
3
|
+
|
4
|
+
include Sc4ry
|
5
|
+
|
6
|
+
# display of default Sc4ry config
|
7
|
+
puts '1.1/ CONFIG : Initial default config'
|
8
|
+
Circuits.default_config.each do |item, value|
|
9
|
+
puts " * #{item} : #{value}"
|
10
|
+
end
|
11
|
+
puts ''
|
12
|
+
|
13
|
+
# testing the two ways to configure Sc4ry default config
|
14
|
+
puts '1.2/ CONFIG : modifying default config activate timout and set max_time to 12'
|
15
|
+
Circuits.merge_default_config diff: { timeout: true }
|
16
|
+
Circuits.configure do |spec|
|
17
|
+
spec.max_time = 12
|
18
|
+
end
|
19
|
+
puts ''
|
20
|
+
|
21
|
+
# display default config, must be override with a nested hash by calling default_config= method
|
22
|
+
puts '1.3/ CONFIG : Default config updated:'
|
23
|
+
Circuits.default_config.each do |item, value|
|
24
|
+
puts " * #{item} : #{value}"
|
25
|
+
end
|
26
|
+
puts ''
|
27
|
+
|
28
|
+
# display current data Store
|
29
|
+
print '2.1/ STORE : Current datastore backend : '
|
30
|
+
puts Circuits.store.current
|
31
|
+
puts ''
|
32
|
+
|
33
|
+
# display available backend
|
34
|
+
puts '2.2/ STORE : List of existing backends : '
|
35
|
+
Circuits.store.list_backend.each do |backend|
|
36
|
+
puts " - #{backend}"
|
37
|
+
end
|
38
|
+
puts ''
|
39
|
+
|
40
|
+
# display Redis backend config in store before change
|
41
|
+
puts '2.3/ STORE : display default config of redis backend'
|
42
|
+
Circuits.store.get_config(backend: :redis).each do |item, value|
|
43
|
+
puts " * #{item} : #{value}"
|
44
|
+
end
|
45
|
+
puts ''
|
46
|
+
|
47
|
+
# reconfigure a backend
|
48
|
+
puts '2.4/ STORE : reconfigure Redis backend'
|
49
|
+
Circuits.store.config_backend name: :redis, config: { host: 'localhost', port: 6379, db: 10 }
|
50
|
+
puts
|
51
|
+
|
52
|
+
# display after
|
53
|
+
puts '2.5/ STORE : display altered config of redis backend'
|
54
|
+
Circuits.store.get_config(backend: :redis).each do |item, value|
|
55
|
+
puts " * #{item} : #{value}"
|
56
|
+
end
|
57
|
+
puts ''
|
58
|
+
|
59
|
+
# change backend
|
60
|
+
|
61
|
+
puts '2.6/ STORE : change to redis backend (NEED a Redis installed) '
|
62
|
+
puts ' $ docker pull redis:latest'
|
63
|
+
puts ' $ docker run --rm -d -p 6379:6379/tcp redis:latest'
|
64
|
+
Circuits.store.change_backend name: :redis
|
65
|
+
puts ''
|
66
|
+
|
67
|
+
puts '2.7/ STORE : flush redis backend, just for test, and for idempotency (NEED a Redis installed) '
|
68
|
+
Circuits.store.flush
|
69
|
+
puts ''
|
70
|
+
|
71
|
+
# defining a circuit, config must be empty or override from default
|
72
|
+
puts '3.1/ CIRCUIT : registering a circuit by merge :'
|
73
|
+
Circuits.register circuit: :test, config: { notifiers: %i[prometheus mattermost], exceptions: [Errno::ECONNREFUSED, URI::InvalidURIError] }
|
74
|
+
puts ''
|
75
|
+
|
76
|
+
puts '3.2/ CIRCUIT : registering a circuit by block :'
|
77
|
+
Circuits.register circuit: :test2 do |spec|
|
78
|
+
spec.exceptions = [Errno::ECONNREFUSED]
|
79
|
+
end
|
80
|
+
puts ''
|
81
|
+
|
82
|
+
puts '3.3/ CIRCUIT : registering a circuit by default :'
|
83
|
+
Circuits.register circuit: :test3
|
84
|
+
puts ''
|
85
|
+
|
86
|
+
puts '3.4/ CIRCUITS : Circuits list'
|
87
|
+
Circuits.list.each do |circuit|
|
88
|
+
puts " * #{circuit}"
|
89
|
+
end
|
90
|
+
puts ''
|
91
|
+
|
92
|
+
puts '3.5/ CIRCUIT : display a circuit config :test3 :'
|
93
|
+
Circuits.get(circuit: :test3).each do |item, value|
|
94
|
+
puts " * #{item} : #{value}"
|
95
|
+
end
|
96
|
+
puts ''
|
97
|
+
|
98
|
+
puts '3.6/ CIRCUIT : update config of :test3 => :raise_on_opening == true :'
|
99
|
+
Circuits.update_config circuit: :test3, config: { raise_on_opening: true }
|
100
|
+
puts ''
|
101
|
+
|
102
|
+
puts '3.7/ CIRCUIT : display a circuit config :test3 after change :'
|
103
|
+
Circuits.get(circuit: :test3).each do |item, value|
|
104
|
+
puts " * #{item} : #{value}"
|
105
|
+
end
|
106
|
+
puts ''
|
107
|
+
|
108
|
+
puts '3.8/ unregister a circuit : :test2 :'
|
109
|
+
Circuits.unregister circuit: :test2
|
110
|
+
puts ''
|
111
|
+
|
112
|
+
puts '3.9/ CIRCUITS : Circuits list after unregister'
|
113
|
+
Circuits.list.each do |circuit|
|
114
|
+
puts " * #{circuit}"
|
115
|
+
end
|
116
|
+
puts ''
|
117
|
+
|
118
|
+
# Config an alternate logger
|
119
|
+
|
120
|
+
puts '4.1/ LOGGER : register a logger on file '
|
121
|
+
Circuits.loggers.register name: :perso, instance: ::Logger.new('/tmp/logfile.log')
|
122
|
+
puts ''
|
123
|
+
|
124
|
+
puts '4.2/ LOGGER : get the list of available loggers'
|
125
|
+
Circuits.loggers.list_available.each do |logger|
|
126
|
+
puts " * #{logger}"
|
127
|
+
end
|
128
|
+
puts ''
|
129
|
+
|
130
|
+
puts '4.3/ LOGGER : change logger to :perso'
|
131
|
+
Circuits.loggers.current = :perso
|
132
|
+
puts ''
|
133
|
+
|
134
|
+
# sample Mattermost notification
|
135
|
+
puts '5/ set notifier mattermost on dummy url, change with your slack or mattermost server'
|
136
|
+
Sc4ry::Notifiers.config name: :mattermost, config: { url: 'https://mattermost.mycorp.com', token: '<TOKEN>' }
|
137
|
+
puts ''
|
138
|
+
|
139
|
+
# sample loop
|
140
|
+
puts '6/ running circuits test, please wait ... (see /tmp/logfile.log for result)'
|
141
|
+
puts ' check endoint status for different result, you cloud use http://github.com/Ultragreen/MockWS for testing endpoint, on an other tty'
|
142
|
+
puts ' $ git clone https://github.com/Ultragreen/MockWS.git'
|
143
|
+
puts ' $ cd MockWS'
|
144
|
+
puts ' $ rackup'
|
145
|
+
begin
|
146
|
+
10.times do
|
147
|
+
sleep 1
|
148
|
+
Circuits.run circuit: :test do
|
149
|
+
# for the test choose or build an endpoint you must shutdown
|
150
|
+
puts RestClient.get('http://localhost:9292/test2/data')
|
151
|
+
end
|
152
|
+
end
|
153
|
+
rescue Interrupt
|
154
|
+
puts 'Interrputed'
|
155
|
+
ensure
|
156
|
+
Circuits.store.flush
|
157
|
+
end
|
158
|
+
|
159
|
+
puts 'end'
|