class Faulty::Storage::Memory
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.
@todo Add a more sophsticated implmentation that can limit the number of
circuits stored.
Constants
- MemoryCircuit
The internal object for storing a circuit
@private
- Options
Options
for {Memory}@!attribute [r] max_sample_size
@return [Integer] The number of cache run entries to keep in memory for each circuit. Default `100`.
Attributes
Public Class Methods
@param options [Hash] Attributes for {Options} @yield [Options] For setting options in a block
# File lib/faulty/storage/memory.rb, line 76 def initialize(**options, &block) @circuits = Concurrent::Map.new @options = Options.new(options, &block) end
Public Instance Methods
Mark a circuit as closed
@see Interface#close
@param (see Interface#close
) @return (see Interface#close
)
# 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
Add an entry to storage
@see Interface#entry
@param (see Interface#entry
) @return (see Interface#entry
)
# 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.runs.value end
Memory
storage is fault-tolerant by default
@return [true]
# File lib/faulty/storage/memory.rb, line 185 def fault_tolerant? true end
Get the circuit history up to `max_sample_size`
@see Interface#history
@param (see Interface#history
) @return (see Interface#history
)
# File lib/faulty/storage/memory.rb, line 171 def history(circuit) fetch(circuit).runs.value end
Get a list of circuit names
@return [Array<String>] The circuit names
# File lib/faulty/storage/memory.rb, line 178 def list @circuits.keys end
Lock a circuit open or closed
@see Interface#lock
@param (see Interface#lock
) @return (see Interface#lock
)
# File lib/faulty/storage/memory.rb, line 133 def lock(circuit, state) memory = fetch(circuit) memory.lock = state end
Mark a circuit as open
@see Interface#open
@param (see Interface#open
) @return (see Interface#open
)
# 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
Mark a circuit as reopened
@see Interface#reopen
@param (see Interface#reopen
) @return (see Interface#reopen
)
# 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 a circuit
@see Interface#reset
@param (see Interface#reset
) @return (see Interface#reset
)
# File lib/faulty/storage/memory.rb, line 153 def reset(circuit) @circuits.delete(circuit.name) end
Get the status of a circuit
@see Interface#status
@param (see Interface#status
) @return (see Interface#status
)
# File lib/faulty/storage/memory.rb, line 162 def status(circuit) fetch(circuit).status(circuit.options) end
Unlock a circuit
@see Interface#unlock
@param (see Interface#unlock
) @return (see Interface#unlock
)
# File lib/faulty/storage/memory.rb, line 143 def unlock(circuit) memory = fetch(circuit) memory.lock = nil end
Private Instance Methods
Fetch circuit storage safely or create it if it doesn't exist
@return [MemoryCircuit]
# File lib/faulty/storage/memory.rb, line 194 def fetch(circuit) @circuits.compute_if_absent(circuit.name) { MemoryCircuit.new } end