faulty 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,117 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Faulty
4
- # A {Scope} is a group of options and circuits
5
- #
6
- # For most use-cases the default scope should be used, however, it's possible
7
- # to create any number of scopes for applications that require a more complex
8
- # configuration or for testing.
9
- #
10
- # For the most part, scopes are independent, however for some cache and
11
- # storage backends, you will need to ensure that the cache keys and circuit
12
- # names don't overlap between scopes. For example, if using the Redis storage
13
- # backend, you should specify different key prefixes for each scope.
14
- class Scope
15
- attr_reader :options
16
-
17
- # Options for {Scope}
18
- #
19
- # @!attribute [r] cache
20
- # @return [Cache::Interface] A cache backend if you want
21
- # to use Faulty's cache support. Automatically wrapped in a
22
- # {Cache::FaultTolerantProxy}. Default `Cache::Default.new`.
23
- # @!attribute [r] storage
24
- # @return [Storage::Interface] The storage backend.
25
- # Automatically wrapped in a {Storage::FaultTolerantProxy}.
26
- # Default `Storage::Memory.new`.
27
- # @!attribute [r] listeners
28
- # @return [Array] listeners Faulty event listeners
29
- # @!attribute [r] notifier
30
- # @return [Events::Notifier] A Faulty notifier. If given, listeners are
31
- # ignored.
32
- Options = Struct.new(
33
- :cache,
34
- :storage,
35
- :listeners,
36
- :notifier
37
- ) do
38
- include ImmutableOptions
39
-
40
- private
41
-
42
- def finalize
43
- self.notifier ||= Events::Notifier.new(listeners || [])
44
-
45
- self.storage ||= Storage::Memory.new
46
- unless storage.fault_tolerant?
47
- self.storage = Storage::FaultTolerantProxy.new(storage, notifier: notifier)
48
- end
49
-
50
- self.cache ||= Cache::Default.new
51
- unless cache.fault_tolerant?
52
- self.cache = Cache::FaultTolerantProxy.new(cache, notifier: notifier)
53
- end
54
- end
55
-
56
- def required
57
- %i[cache storage notifier]
58
- end
59
-
60
- def defaults
61
- {
62
- listeners: [Events::LogListener.new]
63
- }
64
- end
65
- end
66
-
67
- # Create a new Faulty Scope
68
- #
69
- # Note, the process of creating a new scope is not thread safe,
70
- # so make sure scopes are setup before spawning threads.
71
- #
72
- # @see Options
73
- # @param options [Hash] Attributes for {Options}
74
- # @yield [Options] For setting options in a block
75
- def initialize(**options, &block)
76
- @circuits = Concurrent::Map.new
77
- @options = Options.new(options, &block)
78
- end
79
-
80
- # Create or retrieve a circuit
81
- #
82
- # Within a scope, circuit instances have unique names, so if the given circuit
83
- # name already exists, then the existing circuit will be returned, otherwise
84
- # a new circuit will be created. If an existing circuit is returned, then
85
- # the {options} param and block are ignored.
86
- #
87
- # @param name [String] The name of the circuit
88
- # @param options [Hash] Attributes for {Circuit::Options}
89
- # @yield [Circuit::Options] For setting options in a block
90
- # @return [Circuit] The new circuit or the existing circuit if it already exists
91
- def circuit(name, **options, &block)
92
- name = name.to_s
93
- options = options.merge(circuit_options)
94
- @circuits.compute_if_absent(name) do
95
- Circuit.new(name, **options, &block)
96
- end
97
- end
98
-
99
- # Get a list of all circuit names
100
- #
101
- # @return [Array<String>] The circuit names
102
- def list_circuits
103
- options.storage.list
104
- end
105
-
106
- private
107
-
108
- # Get circuit options from the scope options
109
- #
110
- # @return [Hash] The circuit options
111
- def circuit_options
112
- options = @options.to_h
113
- options.delete(:listeners)
114
- options
115
- end
116
- end
117
- end