Class: Faulty::Storage::Interface
- Inherits:
-
Object
- Object
- Faulty::Storage::Interface
- Defined in:
- lib/faulty/storage/interface.rb
Overview
The interface required for a storage backend implementation
This is for documentation only and is not loaded
Instance Method Summary collapse
-
#clear ⇒ void
Reset all circuits.
-
#close(circuit) ⇒ Boolean
Set the circuit state to closed.
-
#entry(circuit, time, success, status) ⇒ Status?
Add a circuit run entry to storage.
-
#fault_tolerant? ⇒ Boolean
Can this storage backend raise an error?.
-
#get_options(circuit) ⇒ Hash
Get the options stored for circuit.
-
#history(circuit) ⇒ Array<Array>
Get the entry history of a circuit.
-
#list ⇒ Array<String>
Get a list of all circuit names.
-
#lock(circuit, state) ⇒ void
Lock the circuit in a given state.
-
#open(circuit, opened_at) ⇒ Boolean
Set the circuit state to open.
-
#reopen(circuit, opened_at, previous_opened_at) ⇒ Boolean
Reset the opened_at time for a half_open circuit.
-
#reserve(circuit, reserved_at, previous_reserved_at) ⇒ Boolean
Reserve an exclusive run for this circuit.
-
#reset(circuit) ⇒ void
Reset the circuit to a fresh state.
-
#set_options(circuit, stored_options) ⇒ void
Store the options for a circuit.
-
#status(circuit) ⇒ Status
Get the status object for a circuit.
-
#unlock(circuit) ⇒ void
Unlock the circuit from any state.
Instance Method Details
#clear ⇒ void
This method returns an undefined value.
Reset all circuits
Some implementions may clear circuits on a best-effort basis since all circuits may not be known.
242 243 244 |
# File 'lib/faulty/storage/interface.rb', line 242 def clear raise NotImplementedError end |
#close(circuit) ⇒ Boolean
Set the circuit state to closed
If multiple parallel processes close the circuit simultaneously, close may be called more than once. If so, this method should return true only once, when the circuit transitions from open to closed.
The backend should reset the reserved_at value to empty when closing the circuit.
If the backend does not support locking or atomic operations, then it may always return true, but that could result in duplicate close notifications.
128 129 130 |
# File 'lib/faulty/storage/interface.rb', line 128 def close(circuit) raise NotImplementedError end |
#entry(circuit, time, success, status) ⇒ Status?
Add a circuit run entry to storage
The backend may choose to store this in whatever manner it chooses as long as it can implement the other read methods.
44 45 46 |
# File 'lib/faulty/storage/interface.rb', line 44 def entry(circuit, time, success, status) raise NotImplementedError end |
#fault_tolerant? ⇒ Boolean
Can this storage backend raise an error?
If the storage backend returns false from this method, it will be wrapped in a FaultTolerantProxy, otherwise it will be used as-is.
252 253 254 |
# File 'lib/faulty/storage/interface.rb', line 252 def fault_tolerant? raise NotImplementedError end |
#get_options(circuit) ⇒ Hash
Get the options stored for circuit
They should be returned exactly as given by #set_options
15 16 17 |
# File 'lib/faulty/storage/interface.rb', line 15 def (circuit) raise NotImplementedError end |
#history(circuit) ⇒ Array<Array>
Get the entry history of a circuit
No concurrency gurantees are provided for getting status. It's possible that status may represent a circuit in the middle of modification.
A storage backend may choose not to implement this method and instead return an empty array.
Each item in the history array is an array of two items (a tuple) of
[run_time, succeeded], where run_time is a unix timestamp, and
succeeded is a boolean, true if the run succeeded.
221 222 223 |
# File 'lib/faulty/storage/interface.rb', line 221 def history(circuit) raise NotImplementedError end |
#list ⇒ Array<String>
Get a list of all circuit names
If the storage backend does not support listing circuits, this may return an empty array.
231 232 233 |
# File 'lib/faulty/storage/interface.rb', line 231 def list raise NotImplementedError end |
#lock(circuit, state) ⇒ void
This method returns an undefined value.
Lock the circuit in a given state
No concurrency gurantees are provided for locking
169 170 171 |
# File 'lib/faulty/storage/interface.rb', line 169 def lock(circuit, state) raise NotImplementedError end |
#open(circuit, opened_at) ⇒ Boolean
Set the circuit state to open
If multiple parallel processes open the circuit simultaneously, open may be called more than once. If so, this method should return true only once, when the circuit transitions from closed to open.
If the backend does not support locking or atomic operations, then it may always return true, but that could result in duplicate open notifications.
If returning true, this method also updates opened_at to the current time.
65 66 67 |
# File 'lib/faulty/storage/interface.rb', line 65 def open(circuit, opened_at) raise NotImplementedError end |
#reopen(circuit, opened_at, previous_opened_at) ⇒ Boolean
Reset the opened_at time for a half_open circuit
If multiple parallel processes open the circuit simultaneously, reopen may be called more than once. If so, this method should return true only once, when the circuit updates the opened_at value. It can use the value from previous_opened_at to do a compare-and-set operation.
If the backend does not support locking or atomic operations, then it may always return true, but that could result in duplicate reopen notifications.
The backend MUST NOT clear reserved_at here.
Preserving the prior cycle's reserved_at is load-bearing for
half-open exclusivity. If a late-arriving caller read status while
reserved_at was still nil (before the winning process reserved),
its subsequent reserve(circuit, T, nil) CAS must fail. Clearing
reserved_at in reopen would let that stale CAS incorrectly
succeed and produce a duplicate half-open run.
Beyond exclusivity, the prior reservation expires naturally at
reserved_at + cool_down, aligned with the start of the next
half-open window (since reserved_at <= new_opened_at). An
explicit reset would be redundant with the cool-down-aligned expiry
that already handles crash recovery.
This invariant assumes the reservation TTL equals cool_down. If
a separate reservation_ttl is ever introduced, this method must
be revisited and may need to clear reserved_at explicitly.
110 111 112 |
# File 'lib/faulty/storage/interface.rb', line 110 def reopen(circuit, opened_at, previous_opened_at) raise NotImplementedError end |
#reserve(circuit, reserved_at, previous_reserved_at) ⇒ Boolean
Reserve an exclusive run for this circuit
This is used when the circuit is half-open and the test run is being attempted. We need to make sure only a single run is allowed.
The backend should store reserved_at and use it to serve future status requests. When setting reserved_at, the backend should atomically compare any existing value using previous_reserved_at. This ensures that mutltiple parallel processes can't reserve the circuit.
The return value is the caller's signal to proceed with the half-open
test run, not a strict report of whether atomic acquisition succeeded.
Atomic backends should return true only when the CAS against
previous_reserved_at succeeds. Non-atomic backends, no-op backends
(Null), or wrappers that fail open (FaultTolerantProxy) may always
return true; the caller will proceed at the cost of allowing
duplicate half-open test runs.
158 159 160 |
# File 'lib/faulty/storage/interface.rb', line 158 def reserve(circuit, reserved_at, previous_reserved_at) raise NotImplementedError end |
#reset(circuit) ⇒ void
This method returns an undefined value.
Reset the circuit to a fresh state
Clears all circuit status including entries, state, locks, opened_at, options, and any other values that would affect Status.
No concurrency gurantees are provided for resetting
192 193 194 |
# File 'lib/faulty/storage/interface.rb', line 192 def reset(circuit) raise NotImplementedError end |
#set_options(circuit, stored_options) ⇒ void
This method returns an undefined value.
Store the options for a circuit
They should be returned exactly as given by #set_options
28 29 30 |
# File 'lib/faulty/storage/interface.rb', line 28 def (circuit, ) raise NotImplementedError end |
#status(circuit) ⇒ Status
Get the status object for a circuit
No concurrency gurantees are provided for getting status. It's possible that status may represent a circuit in the middle of modification.
203 204 205 |
# File 'lib/faulty/storage/interface.rb', line 203 def status(circuit) raise NotImplementedError end |
#unlock(circuit) ⇒ void
This method returns an undefined value.
Unlock the circuit from any state
No concurrency gurantees are provided for locking
179 180 181 |
# File 'lib/faulty/storage/interface.rb', line 179 def unlock(circuit) raise NotImplementedError end |