Class: Faulty::Storage::Memory

Inherits:
Object
  • Object
show all
Defined in:
lib/faulty/storage/memory.rb

Overview

TODO:

Add a more sophsticated implmentation that can limit the number of circuits stored.

The default in-memory storage for circuits

This implementation is thread-safe and circuit state is shared across threads. Since state is stored in-memory, this state is not shared across processes, or persisted across application restarts.

Circuit state and runs are stored in memory. Although runs have a maximum size within a circuit, there is no limit on the number of circuits that can be stored. This means the user should be careful about the number of circuits that are created. To that end, it's a good idea to avoid dynamically-named circuits with this backend.

For a more robust distributed implementation, use the Redis storage backend.

This can be used as a reference implementation for storage backends that store a list of circuit run entries.

Defined Under Namespace

Classes: MemoryCircuit, Options

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(**options) {|Options| ... } ⇒ Memory

Returns a new instance of Memory.

Parameters:

  • options (Hash)

    Attributes for Options

Yields:

  • (Options)

    For setting options in a block


76
77
78
79
# File 'lib/faulty/storage/memory.rb', line 76

def initialize(**options, &block)
  @circuits = Concurrent::Map.new
  @options = Options.new(options, &block)
end

Instance Attribute Details

#optionsObject (readonly)

Returns the value of attribute options


26
27
28
# File 'lib/faulty/storage/memory.rb', line 26

def options
  @options
end

Instance Method Details

#close(circuit) ⇒ Boolean

Mark a circuit as closed

Returns:

  • (Boolean)

    True if the circuit transitioned from open to closed

See Also:


122
123
124
125
126
# File 'lib/faulty/storage/memory.rb', line 122

def close(circuit)
  memory = fetch(circuit)
  memory.runs.modify { |_old| [] }
  memory.state.compare_and_set(:open, :closed)
end

#entry(circuit, time, success) ⇒ Status

Add an entry to storage

Parameters:

  • circuit (Circuit)

    The circuit that ran

  • time (Integer)

    The unix timestamp for the run

  • success (Boolean)

    True if the run succeeded

Returns:

  • (Status)

    The circuit status after the run is added

See Also:


86
87
88
89
90
91
92
93
# File 'lib/faulty/storage/memory.rb', line 86

def entry(circuit, time, success)
  memory = fetch(circuit)
  memory.runs.borrow do |runs|
    runs.push([time, success])
    runs.shift if runs.size > options.max_sample_size
  end
  memory.status(circuit.options)
end

#fault_tolerant?true

Memory storage is fault-tolerant by default

Returns:

  • (true)

185
186
187
# File 'lib/faulty/storage/memory.rb', line 185

def fault_tolerant?
  true
end

#history(circuit) ⇒ Array<Array>

Get the circuit history up to max_sample_size

Parameters:

  • circuit (Circuit)

    The circuit to get history for

Returns:

  • (Array<Array>)

    An array of history tuples

See Also:


171
172
173
# File 'lib/faulty/storage/memory.rb', line 171

def history(circuit)
  fetch(circuit).runs.value
end

#listArray<String>

Get a list of circuit names

Returns:

  • (Array<String>)

    The circuit names


178
179
180
# File 'lib/faulty/storage/memory.rb', line 178

def list
  @circuits.keys
end

#lock(circuit, state) ⇒ void

This method returns an undefined value.

Lock a circuit open or closed

Parameters:

  • circuit (Circuit)

    The circuit to lock

  • state (:open, :closed)

    The state to lock the circuit in

See Also:


133
134
135
136
# File 'lib/faulty/storage/memory.rb', line 133

def lock(circuit, state)
  memory = fetch(circuit)
  memory.lock = state
end

#open(circuit, opened_at) ⇒ Boolean

Mark a circuit as open

Parameters:

  • circuit (Circuit)

    The circuit to open

  • opened_at (Integer)

    The timestmp the circuit was opened at

Returns:

  • (Boolean)

    True if the circuit transitioned from closed to open

See Also:


100
101
102
103
104
105
# File 'lib/faulty/storage/memory.rb', line 100

def open(circuit, opened_at)
  memory = fetch(circuit)
  opened = memory.state.compare_and_set(:closed, :open)
  memory.opened_at.reset(opened_at) if opened
  opened
end

#reopen(circuit, opened_at, previous_opened_at) ⇒ Boolean

Mark a circuit as reopened

Parameters:

  • circuit (Circuit)

    The circuit to reopen

  • opened_at (Integer)

    The timestmp the circuit was opened at

  • previous_opened_at (Integer)

    The last known value of opened_at. Can be used to comare-and-set.

Returns:

  • (Boolean)

    True if the opened_at time was updated

See Also:


112
113
114
115
# File 'lib/faulty/storage/memory.rb', line 112

def reopen(circuit, opened_at, previous_opened_at)
  memory = fetch(circuit)
  memory.opened_at.compare_and_set(previous_opened_at, opened_at)
end

#reset(circuit) ⇒ void

This method returns an undefined value.

Reset a circuit

Parameters:

  • circuit (Circuit)

    The circuit to unlock

See Also:


153
154
155
# File 'lib/faulty/storage/memory.rb', line 153

def reset(circuit)
  @circuits.delete(circuit.name)
end

#status(circuit) ⇒ Status

Get the status of a circuit

Parameters:

  • circuit (Circuit)

    The circuit to get status for

Returns:

  • (Status)

    The current status

See Also:


162
163
164
# File 'lib/faulty/storage/memory.rb', line 162

def status(circuit)
  fetch(circuit).status(circuit.options)
end

#unlock(circuit) ⇒ void

This method returns an undefined value.

Unlock a circuit

Parameters:

  • circuit (Circuit)

    The circuit to unlock

See Also:


143
144
145
146
# File 'lib/faulty/storage/memory.rb', line 143

def unlock(circuit)
  memory = fetch(circuit)
  memory.lock = nil
end