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/deprecation.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/patch/elasticsearch.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, Deprecation, Events, ImmutableOptions, Patch, Storage Classes: AllFailedError, AlreadyInitializedError, Circuit, CircuitError, CircuitFailureError, CircuitRegistry, CircuitTrippedError, DeprecationError, 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:


239
240
241
242
# File 'lib/faulty.rb', line 239

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.


171
172
173
# File 'lib/faulty.rb', line 171

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:


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

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


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

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

.clear!void

This method returns an undefined value.

Reset all circuits for the default instance

See Also:

  • #clear

166
167
168
# File 'lib/faulty.rb', line 166

def clear!
  default.clear
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


131
132
133
# File 'lib/faulty.rb', line 131

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:


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

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.


144
145
146
# File 'lib/faulty.rb', line 144

def disable!
  @disabled = true
end

.disabled?Boolean

Check whether Faulty was disabled with disable!

Returns:

  • (Boolean)

    True if disabled


158
159
160
# File 'lib/faulty.rb', line 158

def disabled?
  @disabled == true
end

.enable!void

This method returns an undefined value.

Re-enable Faulty if disabled with disable!


151
152
153
# File 'lib/faulty.rb', line 151

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)

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

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

See Also:


121
122
123
# File 'lib/faulty.rb', line 121

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


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

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:


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

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


255
256
257
258
# File 'lib/faulty.rb', line 255

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

#clear!void

This method returns an undefined value.

Reset all circuits

Intended for use in tests. This can be expensive and is not appropriate to call in production code

See the documentation for your chosen backend for specific semantics and safety concerns. For example, the Redis backend resets all circuits, but it does not clear the circuit list to maintain thread-safety.


277
278
279
# File 'lib/faulty.rb', line 277

def clear!
  options.storage.clear
end

#list_circuitsArray<String>

Get a list of all circuit names

Returns:

  • (Array<String>)

    The circuit names


263
264
265
# File 'lib/faulty.rb', line 263

def list_circuits
  options.storage.list
end