Class: Faulty

Inherits:
Object
  • Object
show all
Defined in:
lib/faulty.rb,
lib/faulty/cache.rb,
lib/faulty/error.rb,
lib/faulty/patch.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/patch/base.rb,
lib/faulty/cache/rails.rb,
lib/faulty/patch/redis.rb,
lib/faulty/patch/mysql2.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, CircuitErrorBase, Events, ImmutableOptions, Patch, 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:



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

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.



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

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:



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

def [](name)
  raise UninitializedError unless @instances

  @instances[name.to_s]
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



111
112
113
# File 'lib/faulty.rb', line 111

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



128
129
130
# File 'lib/faulty.rb', line 128

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:



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

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)


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

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



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

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



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

def options
  default.options
end

.register(name, instance = nil, **config) {|Faulty::Options| ... } ⇒ 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) (defaults to: nil)

    The instance to register. If nil, a new instance will be created from the given options or block.

  • config (Hash)

    Attributes for Options

Yields:

Returns:

  • (Faulty, nil)

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

Raises:



85
86
87
88
89
90
91
92
93
94
95
# File 'lib/faulty.rb', line 85

def register(name, instance = nil, **config, &block)
  raise UninitializedError unless @instances

  if instance
    raise ArgumentError, 'Do not give config options if an instance is given' if !config.empty? || block
  else
    instance = new(**config, &block)
  end

  @instances.put_if_absent(name.to_s, instance)
end

.versionObject

The current Faulty version



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

def self.version
  Gem::Version.new('0.6.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



217
218
219
220
221
222
223
# File 'lib/faulty.rb', line 217

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

#list_circuitsArray<String>

Get a list of all circuit names

Returns:

  • (Array<String>)

    The circuit names



228
229
230
# File 'lib/faulty.rb', line 228

def list_circuits
  options.storage.list
end