Class: HTTPX::Plugins::CircuitBreaker::Circuit

Inherits:
Object
  • Object
show all
Defined in:
lib/httpx/plugins/circuit_breaker/circuit.rb

Overview

A circuit is assigned to a given absoolute url or origin.

It sets max_attempts, the number of attempts the circuit allows, before it is opened. It sets reset_attempts_in, the time a circuit stays open at most, before it resets. It sets break_in, the time that must elapse before an open circuit can transit to the half-open state. It sets circuit_breaker_half_open_drip_rate, the rate of requests a circuit allows to be performed when in an half-open state.

Instance Method Summary collapse

Constructor Details

#initialize(max_attempts, reset_attempts_in, break_in, circuit_breaker_half_open_drip_rate) ⇒ Circuit

Returns a new instance of Circuit.



14
15
16
17
18
19
20
21
22
23
24
# File 'lib/httpx/plugins/circuit_breaker/circuit.rb', line 14

def initialize(max_attempts, reset_attempts_in, break_in, circuit_breaker_half_open_drip_rate)
  @max_attempts = max_attempts
  @reset_attempts_in = reset_attempts_in
  @break_in = break_in
  @circuit_breaker_half_open_drip_rate = circuit_breaker_half_open_drip_rate
  @attempts = 0

  total_real_attempts = @max_attempts * @circuit_breaker_half_open_drip_rate
  @drip_factor = (@max_attempts / total_real_attempts).round
  @state = :closed
end

Instance Method Details

#respondObject



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/httpx/plugins/circuit_breaker/circuit.rb', line 26

def respond
  try_close

  case @state
  when :closed
    nil
  when :half_open
    @attempts += 1

    # do real requests while drip rate valid
    if (@real_attempts % @drip_factor).zero?
      @real_attempts += 1
      return
    end

    @response
  when :open

    @response
  end
end

#try_closeObject



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/httpx/plugins/circuit_breaker/circuit.rb', line 76

def try_close
  case @state
  when :closed
    nil
  when :half_open

    # do not close circuit unless attempts exhausted
    return unless @attempts >= @max_attempts

    # reset!
    @attempts = 0
    @opened_at = @attempted_at = @response = nil
    @state = :closed

  when :open
    if Utils.elapsed_time(@opened_at) > @break_in
      @state = :half_open
      @attempts = 0
      @real_attempts = 0
    end
  end
end

#try_open(response) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/httpx/plugins/circuit_breaker/circuit.rb', line 48

def try_open(response)
  case @state
  when :closed
    now = Utils.now

    if @attempts.positive?
      # reset if error happened long ago
      @attempts = 0 if now - @attempted_at > @reset_attempts_in
    else
      @attempted_at = now
    end

    @attempts += 1

    return unless @attempts >= @max_attempts

    @state = :open
    @opened_at = now
    @response = response
  when :half_open
    # open immediately

    @state = :open
    @attempted_at = @opened_at = Utils.now
    @response = response
  end
end