Class: FoucaultHttp::Circuit

Inherits:
Object
  • Object
show all
Includes:
Dry::Monads::Result::Mixin, Logging
Defined in:
lib/foucault_http/circuit.rb

Defined Under Namespace

Classes: MonadFailure

Constant Summary collapse

MAX_RETRIES =
3

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Logging

#debug, #error, #fatal, #info, #logger

Constructor Details

#initialize(name:, max_retries: MAX_RETRIES) ⇒ Circuit

Returns a new instance of Circuit.



26
27
28
29
30
31
32
# File 'lib/foucault_http/circuit.rb', line 26

def initialize(name:, max_retries: MAX_RETRIES)
  # redis = Redis.new
  # datastore = Stoplight::DataStore::Redis.new(redis)
  # Stoplight::Light.default_data_store = datastore
  @name = name
  @max_retries = max_retries
end

Instance Attribute Details

#circuitObject (readonly)

Returns the value of attribute circuit.



15
16
17
# File 'lib/foucault_http/circuit.rb', line 15

def circuit
  @circuit
end

Class Method Details

.monad_circuit_wrapper_fnObject

Provides a wrapper fn that allows a monad result to be thrown as an exception so that Stoplight can execute retry behaviour.



21
22
23
# File 'lib/foucault_http/circuit.rb', line 21

def monad_circuit_wrapper_fn
  -> caller { result = caller.(); result.success? ? result : raise(FoucaultHttp::MonadException.new(result: result)) }
end

Instance Method Details

#call(circuit_fn:, caller: nil) ⇒ Object



34
35
36
37
38
39
40
41
42
# File 'lib/foucault_http/circuit.rb', line 34

def call(circuit_fn: , caller: nil)
  info(msg: "CircuitBreaker: #{circuit_to_s}", service_name: @name)
  @circuit = if caller.nil?
                Stoplight(@name) { circuit_fn.() }.with_threshold(@max_retries).with_cool_off_time(10)
              else
                Stoplight(@name) { circuit_fn.(caller) }.with_threshold(@max_retries).with_cool_off_time(10)#.with_fallback {|e| binding.pry; e.result}
              end
  run(@circuit)
end

#circuit_failureObject



67
68
69
70
71
72
73
# File 'lib/foucault_http/circuit.rb', line 67

def circuit_failure
  NetResponseValue.new(
    status: NetResponseValue::CIRCUIT_RED,
    body: nil,
    code: 500
  )
end

#circuit_to_sObject



75
76
77
# File 'lib/foucault_http/circuit.rb', line 75

def circuit_to_s
  "Circuit: #{@name}"
end

#colourObject



63
64
65
# File 'lib/foucault_http/circuit.rb', line 63

def colour
  @circuit.color
end

#failuresObject



59
60
61
# File 'lib/foucault_http/circuit.rb', line 59

def failures
  Stoplight::Light.default_data_store.get_failures(@circuit)
end

#run(circuit) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/foucault_http/circuit.rb', line 44

def run(circuit)
  begin
    circuit.run
  rescue Stoplight::Error::RedLight => e
    info({msg: "CircuitBreaker: #{circuit_to_s}", service_name: @name, circuit_state: "red"})
    @last_error
  rescue FoucaultHttp::MonadException => e
    @last_error = e.result
    retry
  rescue StandardError => e
    @last_error = e
    retry
  end
end