Class: Faulty

Inherits:
Object
  • Object
show all
Defined in:
lib/faulty.rb,
lib/faulty/cache.rb,
lib/faulty/error.rb,
lib/faulty/events.rb,
lib/faulty/result.rb,
lib/faulty/status.rb,
lib/faulty/circuit.rb,
lib/faulty/storage.rb,
lib/faulty/version.rb,
lib/faulty/cache/mock.rb,
lib/faulty/cache/null.rb,
lib/faulty/cache/rails.rb,
lib/faulty/cache/default.rb,
lib/faulty/storage/redis.rb,
lib/faulty/storage/memory.rb,
lib/faulty/cache/auto_wire.rb,
lib/faulty/cache/interface.rb,
lib/faulty/events/notifier.rb,
lib/faulty/immutable_options.rb,
lib/faulty/storage/auto_wire.rb,
lib/faulty/storage/interface.rb,
lib/faulty/cache/circuit_proxy.rb,
lib/faulty/events/log_listener.rb,
lib/faulty/storage/circuit_proxy.rb,
lib/faulty/storage/fallback_chain.rb,
lib/faulty/events/callback_listener.rb,
lib/faulty/events/listener_interface.rb,
lib/faulty/cache/fault_tolerant_proxy.rb,
lib/faulty/events/honeybadger_listener.rb,
lib/faulty/storage/fault_tolerant_proxy.rb

Overview

The Faulty class has class-level methods for global state or can be instantiated to create an independent configuration.

If you are using global state, call Faulty.init during your application's initialization. This is the simplest way to use Faulty. If you prefer, you can also call new to create independent Faulty instances.

Defined Under Namespace

Modules: Cache, Events, ImmutableOptions, Storage Classes: AllFailedError, AlreadyInitializedError, Circuit, CircuitError, CircuitFailureError, CircuitTrippedError, FaultyError, FaultyMultiError, MissingDefaultInstanceError, OpenCircuitError, Options, PartialFailureError, Result, Status, UncheckedResultError, UninitializedError, WrongResultError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

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

Create a new Faulty instance

Note, the process of creating a new instance is not thread safe, so make sure instances are setup during your application's initialization phase.

For the most part, Faulty instances are independent, however for some cache and storage backends, you will need to ensure that the cache keys and circuit names don't overlap between instances. For example, if using the Faulty::Storage::Redis storage backend, you should specify different key prefixes for each instance.

Parameters:

  • options (Hash)

    Attributes for Options

Yields:

  • (Options)

    For setting options in a block

See Also:


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

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


123
124
125
# File 'lib/faulty.rb', line 123

def options
  @options
end

Class Method Details

.[](name) ⇒ Faulty?

Get an instance by name

Returns:

  • (Faulty, nil)

    The named instance if it is registered

Raises:


66
67
68
69
70
# File 'lib/faulty.rb', line 66

def [](name)
  raise UninitializedError unless @instances

  @instances[name]
end

.circuit(name, **config) {|Circuit::Options| ... } ⇒ Circuit

Get or create a circuit for the default instance

Parameters:

Yields:

Returns:

  • (Circuit)

    The new circuit or the existing circuit if it already exists

Raises:

  • UninitializedError If the default instance has not been created


101
102
103
# File 'lib/faulty.rb', line 101

def circuit(name, **config, &block)
  default.circuit(name, **config, &block)
end

.current_timeTime

The current time

Used by Faulty wherever the current time is needed. Can be overridden for testing

Returns:

  • (Time)

    The current time


118
119
120
# File 'lib/faulty.rb', line 118

def current_time
  Time.now.to_i
end

.defaultFaulty?

Get the default instance given during init

Returns:

  • (Faulty, nil)

    The default instance if it is registered

Raises:


56
57
58
59
60
61
# File 'lib/faulty.rb', line 56

def default
  raise UninitializedError unless @instances
  raise MissingDefaultInstanceError unless @default_instance

  self[@default_instance]
end

.init(default_name = :default, **config) {|Faulty::Options| ... } ⇒ self

Start the Faulty environment

This creates a global shared Faulty state for configuration and for re-using State objects.

Not thread safe, should be executed before any worker threads are spawned.

If you prefer dependency-injection instead of global state, you can skip init and use new to pass an instance directoy to your dependencies.

to nil to skip creating a default instance.

Parameters:

  • default_name (Symbol) (defaults to: :default)

    The name of the default instance. Can be set

  • config (Hash)

    Attributes for Options

Yields:

Returns:

  • (self)

41
42
43
44
45
46
47
48
49
50
51
# File 'lib/faulty.rb', line 41

def init(default_name = :default, **config, &block)
  raise AlreadyInitializedError if @instances

  @default_instance = default_name
  @instances = Concurrent::Map.new
  register(default_name, new(**config, &block)) unless default_name.nil?
  self
rescue StandardError
  @instances = nil
  raise
end

.list_circuitsArray<String>

Get a list of all circuit names for the default instance

Returns:

  • (Array<String>)

    The circuit names


108
109
110
# File 'lib/faulty.rb', line 108

def list_circuits
  options.storage.list
end

.optionsFaulty::Options

Get the options for the default instance

Returns:

Raises:

  • MissingDefaultInstanceError If the default instance has not been created


91
92
93
# File 'lib/faulty.rb', line 91

def options
  default.options
end

.register(name, instance) ⇒ Faulty?

Register an instance to the global Faulty state

Will not replace an existing instance with the same name. Check the return value if you need to know whether the instance already existed.

Parameters:

  • name (Symbol)

    The name of the instance to register

  • instance (Faulty)

    The instance to register

Returns:

  • (Faulty, nil)

    The previously-registered instance of that name if it already existed, otherwise nil.

Raises:


81
82
83
84
85
# File 'lib/faulty.rb', line 81

def register(name, instance)
  raise UninitializedError unless @instances

  @instances.put_if_absent(name, instance)
end

.versionObject

The current Faulty version


5
6
7
# File 'lib/faulty/version.rb', line 5

def self.version
  Gem::Version.new('0.2.0')
end

Instance Method Details

#circuit(name, **options) {|Circuit::Options| ... } ⇒ Circuit

Create or retrieve a circuit

Within an instance, circuit instances have unique names, so if the given circuit name already exists, then the existing circuit will be returned, otherwise a new circuit will be created. If an existing circuit is returned, then the options param and block are ignored.

Parameters:

Yields:

Returns:

  • (Circuit)

    The new circuit or the existing circuit if it already exists


201
202
203
204
205
206
207
# File 'lib/faulty.rb', line 201

def circuit(name, **options, &block)
  name = name.to_s
  options = options.merge(circuit_options)
  @circuits.compute_if_absent(name) do
    Circuit.new(name, **options, &block)
  end
end

#list_circuitsArray<String>

Get a list of all circuit names

Returns:

  • (Array<String>)

    The circuit names


212
213
214
# File 'lib/faulty.rb', line 212

def list_circuits
  options.storage.list
end