Class: Sc4ry::Circuits

Inherits:
Object
  • Object
show all
Includes:
Constants, Exceptions
Defined in:
lib/sc4ry/circuits.rb

Overview

Circuits and default configuration management class

Constant Summary collapse

@@circuits_store =
Sc4ry::Store.instance
@@circuits_notifiers =
Sc4ry::Notifiers
@@circuits_loggers =
Sc4ry::Loggers
@@config =
DEFAULT_CONFIG

Constants included from Constants

Sc4ry::Constants::CURRENT_NOTIFIERS, Sc4ry::Constants::DEFAULT_CONFIG, Sc4ry::Constants::DEFAULT_CONFIG_FORMATS

forwarders collapse

Default Sc4ry configuration management collapse

Circuits management collapse

Class Method Details

.configure {|Sc4ry::Config::ConfigMapper| ... } ⇒ Object

class method for specifiying config by block

Examples:

usage

include Sc4ry
Circuits.configure do |spec|
   spec.max_failure_count = 3 
end

Yields:



68
69
70
71
72
73
74
# File 'lib/sc4ry/circuits.rb', line 68

def Circuits.configure(&bloc)
  mapper = Sc4ry::Config::ConfigMapper::new(definition: @@config.dup)
  yield(mapper)
  validator = Sc4ry::Config::Validator::new(definition: mapper.config, from: @@config)
  validator.validate!
  @@config = validator.result 
end

.default_configHash

Class method how return de default Sc4ry config

Returns:

  • (Hash)


45
46
47
# File 'lib/sc4ry/circuits.rb', line 45

def Circuits.default_config
  return @@config
end

.default_config=(config) ⇒ Object

Deprecated.

use merge_default_config instead

old default config setter

Parameters:

  • config (Hash)


80
81
82
83
# File 'lib/sc4ry/circuits.rb', line 80

def Circuits.default_config=(config)
  Sc4ry::Helpers.log level: :warn, message: "DEPRECATED: Circuits.default_config= is deprecated please use Circuits.merge_default_config add: {<config_hash>}"
  Circuits.merge_default_config(diff: config)
end

.flushtrue, false

class method how flush all circuits in current store

Examples:

usage

include Sc4ry 
Circuits.flush

Returns:

  • (true, false)


136
137
138
# File 'lib/sc4ry/circuits.rb', line 136

def Circuits.flush
  return @@circuits_store.flush
end

.get(circuit:) ⇒ Hash

class method for get a specific circuit by circuit name

Examples:

usage

include Sc4ry 
Circuits.get circuit: :mycircuit

Parameters:

  • circuit (Symbol)

    a circuit name

Returns:

  • (Hash)

    the circuit record in current store included values and status if the circuit have already run.



164
165
166
# File 'lib/sc4ry/circuits.rb', line 164

def Circuits.get(circuit:)
  @@circuits_store.get key: circuit
end

.listArray

class method how list all circuits in current store

Examples:

usage

include Sc4ry 
circuits = Circuits.list

Returns:

  • (Array)

    the list of [Symbol] circuits name



127
128
129
# File 'lib/sc4ry/circuits.rb', line 127

def Circuits.list
  return @@circuits_store.list
end

.loggersSc4ry::Store

Class method how forward the Logger manager class factory/manager

Returns:



32
33
34
# File 'lib/sc4ry/circuits.rb', line 32

def Circuits.loggers
  return @@circuits_loggers
end

.merge_default_config(diff:) ⇒ Object

class method how merge a differential hash to default config

Examples:

usage

include Sc4ry
Circuits.merge_default_config diff: {max_time: 20, notifiers: [:mattermost]}  

Parameters:

  • diff (Hash)

    the differential hash config



54
55
56
57
58
59
# File 'lib/sc4ry/circuits.rb', line 54

def Circuits.merge_default_config(diff:)
  validator = Sc4ry::Config::Validator::new(definition: diff, from: @@config)
  validator.validate!
  @@config = validator.result 

end

.notifiersSc4ry::Notifiers

Class method how forward the Notifiers class factory/manager

Returns:



20
21
22
# File 'lib/sc4ry/circuits.rb', line 20

def Circuits.notifiers
  return @@circuits_notifiers
end

.register(circuit:, config: {}) {|Sc4ry::Config::ConfigMapper| ... } ⇒ Hash

class method for registering a new circuit, cloud work with a block

Examples:

usage

include Sc4ry 
Circuits.register circuit: :mycircuit, config: {raise_on_opening: true, timeout: true}
# or
Circuits.register circuit: :mycircuit do |spec|
  spec.raise_on_opening = true
  spec.timeout = true
end

Parameters:

  • circuit (Symbol)

    a circuit name

  • config (Hash) (defaults to: {})

    a config override on default config for the circuit

Yields:

Returns:

  • (Hash)

    the full config of the circuit after merge on default

Raises:



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/sc4ry/circuits.rb', line 104

def Circuits.register(circuit:, config: {})
  if config.size > 0 and block_given? then 
    raise Sc4ryGenericError, "config: keyword must not be defined when block is given"
  end
  if block_given? then 
    mapper = Sc4ry::Config::ConfigMapper::new(definition: @@config.dup)
    yield(mapper)
    validator = Sc4ry::Config::Validator::new(definition: mapper.config, from: @@config.dup)
  else 
    validator = Sc4ry::Config::Validator::new(definition: config, from: @@config.dup )
  end
  validator.validate!
  Sc4ry::Helpers.log level: :debug, message: "Circuit #{circuit} : registered"
  raise Sc4ryGenericError, "Circuit: #{circuit} already exist in store" if @@circuits_store.exist? key: circuit 
  @@circuits_store.put key: circuit, value: validator.result 
  return validator.result
end

.run(circuit: nil) {|Proc| ... } ⇒ Hash

class method for running circuit, need a block

Examples:

usage

include Sc4ry 
Circuits.run circuit: :mycircuit do 
    #  [...]  your code like a Restclient.get("URL")
end
# or
Circuits.run do 
     # [...] your code like a Restclient.get("URL")
     #  running with the first define circuit (use only on a one circuit usage)
end

Parameters:

  • circuit (Symbol) (defaults to: nil)

    a circuit name

Yields:

  • (Proc)

Returns:

  • (Hash)

    a result like “:general=>:open, :failure_count=>X, :overtime_count=>X, :timeout_count=>X”

Raises:

  • (Sc4ryGenericError)

    if circuit already not exit, block is missing or store empty



212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/sc4ry/circuits.rb', line 212

def Circuits.run(circuit: nil , &block)
  circuits_list = Circuits.list
  raise Sc4ryGenericError, "No circuit block given" unless block_given?
  raise Sc4ryGenericError, "No circuits defined" if circuits_list.empty? 
  circuit_name = (circuit)? circuit : circuits_list.first
  raise Sc4ryGenericError, "Circuit #{circuit_name} not found" unless circuits_list.include? circuit_name
  circuit_to_run = Circuits.get circuit: circuit_name
  skip = false
  if circuit_to_run.include? :status then
    if circuit_to_run[:status][:general] == :open then 
      @now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
      skip = true if ((@now - circuit_to_run[:values].last[:end_time]) <  circuit_to_run[:check_delay])
    end
  end
  unless skip 
    controller = Sc4ry::RunController.new(circuit_to_run)
    Circuits.control circuit: circuit_name, values: controller.run(block: block)
  end
  result = @@circuits_store.get key: circuit_name
  Sc4ry::Helpers.log level: :debug, message: "Circuit #{circuit_name} : status #{result[:status]}"
  return result
end

.status(circuit:) ⇒ Symbol

class method for get the status of a specific circuit by circuit name

Examples:

usage

include Sc4ry 
Circuits.status circuit: :mycircuit

Parameters:

  • circuit (Symbol)

    a circuit name

Returns:

  • (Symbol)

    status must in [:open,:half_open,:closed,:never_run]



191
192
193
194
# File 'lib/sc4ry/circuits.rb', line 191

def Circuits.status(circuit:)
  data = @@circuits_store.get key: circuit
  return (data.include? :status)? data[:status][:general] : :never_run
end

.storeSc4ry::Store

Class method how forward a Store manager class singleton

Returns:



26
27
28
# File 'lib/sc4ry/circuits.rb', line 26

def Circuits.store
  return @@circuits_store
end

.unregister(circuit:) ⇒ true, false

class method for unregistering a circuit

Examples:

usage

include Sc4ry 
Circuits.unregister circuit: :mycircuit

Parameters:

  • circuit (Symbol)

    a circuit name

Returns:

  • (true, false)

Raises:



147
148
149
150
151
152
153
154
155
# File 'lib/sc4ry/circuits.rb', line 147

def Circuits.unregister(circuit:)
  if Circuits.list.include? circuit then
    @@circuits_store.del key: circuit
    return true
  else
    raise Sc4ryGenericError, "Circuit #{circuit} not found"
    return false
  end
end

.update_config(circuit:, config: {forward_unknown_exceptions: false}) ⇒ Hash

Note:

: important updating config will reset status and values !

class method for update the config of a specific circuit by circuit name

Examples:

usage

include Sc4ry 
Circuits.update_config circuit: :mycircuit, config: {}

Parameters:

  • circuit (Symbol)

    a circuit name

  • config (Hash) (defaults to: {forward_unknown_exceptions: false})

    a config hash to merge on current config

Returns:

  • (Hash)

    new config for this circuit

Raises:



176
177
178
179
180
181
182
183
# File 'lib/sc4ry/circuits.rb', line 176

def Circuits.update_config(circuit: , config: {forward_unknown_exceptions: false})
  raise Sc4ryGenericError, "Circuit #{circuit} not found" unless Circuits.list.include? circuit
  save = @@circuits_store.get key: circuit
  save.delete_if {|key,val| [:status,:values].include? key}
  Circuits.unregister(circuit: circuit)
  save.merge! config
  return Circuits.register circuit: circuit, config: save 
end