faulty 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +1 -2
- data/bin/benchmark +52 -0
- data/lib/faulty/circuit.rb +3 -15
- data/lib/faulty/events/callback_listener.rb +1 -1
- data/lib/faulty/events/honeybadger_listener.rb +10 -2
- data/lib/faulty/events/log_listener.rb +6 -4
- data/lib/faulty/events.rb +2 -0
- data/lib/faulty/status.rb +9 -2
- data/lib/faulty/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e07febd816231284cfdc3f2f75e05381a26fb933af81e036c24bff019dcb1f2d
|
4
|
+
data.tar.gz: 3804c68b52a5fca7053a94bfb533444a3bb4250fbffe5ab7e966f1246629feaa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c8753deac6a63980050cb5a2a016515f45dafadcbebe356c8409e984ffd6d01d65f7c2b1b11c9c77bae2ff422601fd45aea7b92c77e0b82733d32cdab11ec9e2
|
7
|
+
data.tar.gz: 7d92e8f081b5902909709f2777d075e224700495259747701ac9a210d334b64a4c89abaf37cfd5546763216eacccb7bb4c6aa3b177e71c6cc0d852d5a245a25a
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
## Release v0.7.0
|
2
|
+
|
3
|
+
* Add initial benchmarks and performance improvements #36 justinhoward
|
4
|
+
|
5
|
+
### Breaking Changes
|
6
|
+
|
7
|
+
The `circuit_success` event no longer contains the status value. Computing this
|
8
|
+
value was causing performance problems.
|
9
|
+
|
1
10
|
## Release v0.6.0
|
2
11
|
|
3
12
|
* docs, use correct state in description for skipped event #27 senny
|
data/README.md
CHANGED
@@ -1064,8 +1064,7 @@ events. The full list of events is available from
|
|
1064
1064
|
half-open. Payload: `circuit`, `error`.
|
1065
1065
|
- `circuit_skipped` - A circuit execution was skipped because the circuit is
|
1066
1066
|
open. Payload: `circuit`
|
1067
|
-
- `circuit_success` - A circuit execution was successful. Payload: `circuit
|
1068
|
-
`status`
|
1067
|
+
- `circuit_success` - A circuit execution was successful. Payload: `circuit`
|
1069
1068
|
- `storage_failure` - A storage backend raised an error. Payload `circuit` (can
|
1070
1069
|
be nil), `action`, `error`
|
1071
1070
|
|
data/bin/benchmark
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'benchmark'
|
6
|
+
require 'faulty'
|
7
|
+
|
8
|
+
n = 100_000
|
9
|
+
|
10
|
+
puts "Starting circuit benchmarks with #{n} iterations each\n\n"
|
11
|
+
|
12
|
+
Benchmark.bm(25) do |b|
|
13
|
+
in_memory = Faulty.new(listeners: [])
|
14
|
+
b.report('memory storage') do
|
15
|
+
n.times { in_memory.circuit(:memory).run { true } }
|
16
|
+
end
|
17
|
+
|
18
|
+
b.report('memory storage failures') do
|
19
|
+
n.times do
|
20
|
+
begin
|
21
|
+
in_memory.circuit(:memory_fail, sample_threshold: n + 1).run { raise 'fail' }
|
22
|
+
rescue StandardError
|
23
|
+
# Expected to raise here
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
in_memory_large = Faulty.new(listeners: [], storage: Faulty::Storage::Memory.new(max_sample_size: 1000))
|
29
|
+
b.report('large memory storage') do
|
30
|
+
n.times { in_memory_large.circuit(:memory_large).run { true } }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
n = 1_000_000
|
35
|
+
|
36
|
+
puts "\n\nStarting extra benchmarks with #{n} iterations each\n\n"
|
37
|
+
|
38
|
+
Benchmark.bm(25) do |b|
|
39
|
+
in_memory = Faulty.new(listeners: [])
|
40
|
+
|
41
|
+
log_listener = Faulty::Events::LogListener.new(Logger.new(File::NULL))
|
42
|
+
log_circuit = in_memory.circuit(:log_listener)
|
43
|
+
log_status = log_circuit.status
|
44
|
+
b.report('log listener success') do
|
45
|
+
n.times { log_listener.handle(:circuit_success, circuit: log_circuit, status: log_status) }
|
46
|
+
end
|
47
|
+
|
48
|
+
log_error = StandardError.new('test error')
|
49
|
+
b.report('log listener failure') do
|
50
|
+
n.times { log_listener.handle(:circuit_failure, error: log_error, circuit: log_circuit, status: log_status) }
|
51
|
+
end
|
52
|
+
end
|
data/lib/faulty/circuit.rb
CHANGED
@@ -319,12 +319,10 @@ class Faulty
|
|
319
319
|
|
320
320
|
# @return [Boolean] True if the circuit transitioned to closed
|
321
321
|
def success!(status)
|
322
|
-
|
323
|
-
|
324
|
-
closed = false
|
325
|
-
closed = close! if should_close?(status)
|
322
|
+
storage.entry(self, Faulty.current_time, true)
|
323
|
+
closed = close! if status.half_open?
|
326
324
|
|
327
|
-
options.notifier.notify(:circuit_success, circuit: self
|
325
|
+
options.notifier.notify(:circuit_success, circuit: self)
|
328
326
|
closed
|
329
327
|
end
|
330
328
|
|
@@ -370,16 +368,6 @@ class Faulty
|
|
370
368
|
closed
|
371
369
|
end
|
372
370
|
|
373
|
-
# Test whether we should close after a successful run
|
374
|
-
#
|
375
|
-
# Currently this is always true if the circuit is half-open, which is the
|
376
|
-
# traditional behavior for a circuit-breaker
|
377
|
-
#
|
378
|
-
# @return [Boolean] True if we should close the circuit from half-open
|
379
|
-
def should_close?(status)
|
380
|
-
status.half_open?
|
381
|
-
end
|
382
|
-
|
383
371
|
# Read from the cache if it is configured
|
384
372
|
#
|
385
373
|
# @param key The key to read from the cache
|
@@ -23,7 +23,7 @@ class Faulty
|
|
23
23
|
# @param (see ListenerInterface#handle)
|
24
24
|
# @return [void]
|
25
25
|
def handle(event, payload)
|
26
|
-
return unless
|
26
|
+
return unless EVENT_SET.include?(event)
|
27
27
|
return unless @handlers.key?(event)
|
28
28
|
|
29
29
|
@handlers[event].each do |handler|
|
@@ -8,11 +8,19 @@ class Faulty
|
|
8
8
|
#
|
9
9
|
# The honeybadger gem must be available.
|
10
10
|
class HoneybadgerListener
|
11
|
+
HONEYBADGER_EVENTS = Set[
|
12
|
+
:circuit_failure,
|
13
|
+
:circuit_opened,
|
14
|
+
:circuit_reopened,
|
15
|
+
:cache_failure,
|
16
|
+
:storage_failure
|
17
|
+
].freeze
|
18
|
+
|
11
19
|
# (see ListenerInterface#handle)
|
12
20
|
def handle(event, payload)
|
13
|
-
return unless
|
21
|
+
return unless HONEYBADGER_EVENTS.include?(event)
|
14
22
|
|
15
|
-
send(event, payload)
|
23
|
+
send(event, payload)
|
16
24
|
end
|
17
25
|
|
18
26
|
private
|
@@ -16,9 +16,9 @@ class Faulty
|
|
16
16
|
|
17
17
|
# (see ListenerInterface#handle)
|
18
18
|
def handle(event, payload)
|
19
|
-
return unless
|
19
|
+
return unless EVENT_SET.include?(event)
|
20
20
|
|
21
|
-
send(event, payload)
|
21
|
+
send(event, payload)
|
22
22
|
end
|
23
23
|
|
24
24
|
private
|
@@ -79,8 +79,10 @@ class Faulty
|
|
79
79
|
end
|
80
80
|
|
81
81
|
def log(level, msg, action, extra = {})
|
82
|
-
|
83
|
-
|
82
|
+
@logger.public_send(level) do
|
83
|
+
extra_str = extra.map { |k, v| "#{k}=#{v}" }.join(' ')
|
84
|
+
"#{msg}: #{action} #{extra_str}"
|
85
|
+
end
|
84
86
|
end
|
85
87
|
end
|
86
88
|
end
|
data/lib/faulty/events.rb
CHANGED
data/lib/faulty/status.rb
CHANGED
@@ -64,10 +64,17 @@ class Faulty
|
|
64
64
|
# sample_size
|
65
65
|
# @return [Status]
|
66
66
|
def self.from_entries(entries, **hash)
|
67
|
+
window_start = Faulty.current_time - hash[:options].evaluation_window
|
68
|
+
size = entries.size
|
69
|
+
i = 0
|
67
70
|
failures = 0
|
68
71
|
sample_size = 0
|
69
|
-
|
70
|
-
|
72
|
+
|
73
|
+
# This is a hot loop, and while is slightly faster than each
|
74
|
+
while i < size
|
75
|
+
time, success = entries[i]
|
76
|
+
i += 1
|
77
|
+
next unless time > window_start
|
71
78
|
|
72
79
|
sample_size += 1
|
73
80
|
failures += 1 unless success
|
data/lib/faulty/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: faulty
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Howard
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-09-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -124,6 +124,7 @@ files:
|
|
124
124
|
- Gemfile
|
125
125
|
- LICENSE.txt
|
126
126
|
- README.md
|
127
|
+
- bin/benchmark
|
127
128
|
- bin/check-version
|
128
129
|
- bin/console
|
129
130
|
- bin/rspec
|