Class: Faulty::Storage::FaultTolerantProxy

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/faulty/storage/fault_tolerant_proxy.rb

Overview

A wrapper for storage backends that may raise errors

Faulty#initialize automatically wraps all non-fault-tolerant storage backends with this class.

If the storage backend raises a StandardError, it will be captured and sent to the notifier.

Defined Under Namespace

Classes: Options

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(storage, **options) {|Options| ... } ⇒ FaultTolerantProxy

Returns a new instance of FaultTolerantProxy.

Parameters:

Yields:

  • (Options)

    For setting options in a block



34
35
36
37
# File 'lib/faulty/storage/fault_tolerant_proxy.rb', line 34

def initialize(storage, **options, &block)
  @storage = storage
  @options = Options.new(options, &block)
end

Instance Attribute Details

#optionsObject (readonly)

Returns the value of attribute options.



15
16
17
# File 'lib/faulty/storage/fault_tolerant_proxy.rb', line 15

def options
  @options
end

Class Method Details

.wrap(storage, **options, &block) ⇒ Storage::Interface

Wrap a storage backend in a FaultTolerantProxy unless it's already fault tolerant

Parameters:

Returns:



44
45
46
47
48
# File 'lib/faulty/storage/fault_tolerant_proxy.rb', line 44

def self.wrap(storage, **options, &block)
  return storage if storage.fault_tolerant?

  new(storage, **options, &block)
end

Instance Method Details

#clearObject

Clear is not called in normal operation, so it doesn't capture errors

See Also:



91
# File 'lib/faulty/storage/fault_tolerant_proxy.rb', line 91

def_delegators :@storage, :lock, :unlock, :reset, :history, :list, :clear

#close(circuit) ⇒ Boolean

Safely mark a circuit as closed

Returns:

  • (Boolean)

    True if the circuit transitioned from open to closed

See Also:



158
159
160
161
162
163
# File 'lib/faulty/storage/fault_tolerant_proxy.rb', line 158

def close(circuit)
  @storage.close(circuit)
rescue StandardError => e
  options.notifier.notify(:storage_failure, circuit: circuit, action: :close, error: e)
  false
end

#entry(circuit, time, success, status) ⇒ Status?

Add a history entry safely

Parameters:

  • circuit (Circuit)

    The circuit that ran

  • time (Integer)

    The unix timestamp for the run

  • success (Boolean)

    True if the run succeeded

  • status (Status, nil)

    The previous status. If given, this method must return an updated status object from the new entry data.

Returns:

  • (Status, nil)

    If status is not nil, the updated status object.

See Also:



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

def entry(circuit, time, success, status)
  @storage.entry(circuit, time, success, status)
rescue StandardError => e
  options.notifier.notify(:storage_failure, circuit: circuit, action: :entry, error: e)
  stub_status(circuit) if status
end

#fault_tolerant?true

This cache makes any storage fault tolerant, so this is always true

Returns:

  • (true)


183
184
185
# File 'lib/faulty/storage/fault_tolerant_proxy.rb', line 183

def fault_tolerant?
  true
end

#get_options(circuit) ⇒ Hash

Get circuit options safely

Returns:

  • (Hash)

    A hash of the options stored by #set_options. The keys must be symbols.

See Also:



98
99
100
101
102
103
# File 'lib/faulty/storage/fault_tolerant_proxy.rb', line 98

def get_options(circuit)
  @storage.get_options(circuit)
rescue StandardError => e
  options.notifier.notify(:storage_failure, circuit: circuit, action: :get_options, error: e)
  nil
end

#history(circuit) ⇒ Object

History is not called in normal operation, so it doesn't capture errors

See Also:



91
# File 'lib/faulty/storage/fault_tolerant_proxy.rb', line 91

def_delegators :@storage, :lock, :unlock, :reset, :history, :list, :clear

#listObject

List is not called in normal operation, so it doesn't capture errors

See Also:



91
# File 'lib/faulty/storage/fault_tolerant_proxy.rb', line 91

def_delegators :@storage, :lock, :unlock, :reset, :history, :list, :clear

#lock(circuit, state) ⇒ Object

Lock is not called in normal operation, so it doesn't capture errors

See Also:



91
# File 'lib/faulty/storage/fault_tolerant_proxy.rb', line 91

def_delegators :@storage, :lock, :unlock, :reset, :history, :list, :clear

#open(circuit, opened_at) ⇒ Boolean

Safely 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:



134
135
136
137
138
139
# File 'lib/faulty/storage/fault_tolerant_proxy.rb', line 134

def open(circuit, opened_at)
  @storage.open(circuit, opened_at)
rescue StandardError => e
  options.notifier.notify(:storage_failure, circuit: circuit, action: :open, error: e)
  false
end

#reopen(circuit, opened_at, previous_opened_at) ⇒ Boolean

Safely 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:



146
147
148
149
150
151
# File 'lib/faulty/storage/fault_tolerant_proxy.rb', line 146

def reopen(circuit, opened_at, previous_opened_at)
  @storage.reopen(circuit, opened_at, previous_opened_at)
rescue StandardError => e
  options.notifier.notify(:storage_failure, circuit: circuit, action: :reopen, error: e)
  false
end

#reset(circuit) ⇒ Object

Reset is not called in normal operation, so it doesn't capture errors

See Also:



91
# File 'lib/faulty/storage/fault_tolerant_proxy.rb', line 91

def_delegators :@storage, :lock, :unlock, :reset, :history, :list, :clear

#set_options(circuit, stored_options) ⇒ void

This method returns an undefined value.

Set circuit options safely

Parameters:

  • circuit (Circuit)

    The circuit to set options for

  • stored_options (Hash<Symbol, Object>)

    A hash of symbol option names to circuit options. These option values are guranteed to be primive values.

See Also:



110
111
112
113
114
115
# File 'lib/faulty/storage/fault_tolerant_proxy.rb', line 110

def set_options(circuit, stored_options)
  @storage.set_options(circuit, stored_options)
rescue StandardError => e
  options.notifier.notify(:storage_failure, circuit: circuit, action: :set_options, error: e)
  nil
end

#status(circuit) ⇒ Status

Safely get the status of a circuit

If the backend is unavailable, this returns a stub status that indicates that the circuit is closed.

Parameters:

  • circuit (Circuit)

    The circuit to get status for

Returns:

  • (Status)

    The current status

See Also:



173
174
175
176
177
178
# File 'lib/faulty/storage/fault_tolerant_proxy.rb', line 173

def status(circuit)
  @storage.status(circuit)
rescue StandardError => e
  options.notifier.notify(:storage_failure, circuit: circuit, action: :status, error: e)
  stub_status(circuit)
end

#unlock(circuit) ⇒ Object

Unlock is not called in normal operation, so it doesn't capture errors

See Also:



91
# File 'lib/faulty/storage/fault_tolerant_proxy.rb', line 91

def_delegators :@storage, :lock, :unlock, :reset, :history, :list, :clear