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/storage/null.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/circuit_registry.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/events/filter_notifier.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, CircuitRegistry, 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:


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

def initialize(**options, &block)
  @options = Options.new(options, &block)
  @registry = CircuitRegistry.new(circuit_options)
end

Instance Attribute Details

#optionsObject (readonly)

Returns the value of attribute options.


161
162
163
# File 'lib/faulty.rb', line 161

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:


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

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


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

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


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

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:


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

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

  self[@default_instance]
end

.disable!void

This method returns an undefined value.

Disable Faulty circuits

This allows circuits to run as if they were always closed. Does not disable caching.

Intended for use in tests, or to disable Faulty entirely for an environment.


142
143
144
# File 'lib/faulty.rb', line 142

def disable!
  @disabled = true
end

.disabled?Boolean

Check whether Faulty was disabled with #disable!

Returns:

  • (Boolean)

    True if disabled


156
157
158
# File 'lib/faulty.rb', line 156

def disabled?
  @disabled == true
end

.enable!void

This method returns an undefined value.

Re-enable Faulty if disabled with #disable!


149
150
151
# File 'lib/faulty.rb', line 149

def enable!
  @disabled = false
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)

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

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


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

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


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

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:


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

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.8.2')
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


245
246
247
248
# File 'lib/faulty.rb', line 245

def circuit(name, **options, &block)
  name = name.to_s
  @registry.retrieve(name, options, &block)
end

#list_circuitsArray<String>

Get a list of all circuit names

Returns:

  • (Array<String>)

    The circuit names


253
254
255
# File 'lib/faulty.rb', line 253

def list_circuits
  options.storage.list
end