Skip to content

Commit 9a30b03

Browse files
committed
Fix ruby version compatibility and start README
1 parent 1732c87 commit 9a30b03

File tree

8 files changed

+164
-7
lines changed

8 files changed

+164
-7
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/.bundle/
22
/Gemfile.lock
33
/vendor/
4+
/.ruby-version
45

56
/coverage/
67
/doc/

.ruby-version

-1
This file was deleted.

LICENSE.txt

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
The MIT License (MIT)
2+
3+
Copyright © 2020 ParentSquare
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy of
6+
this software and associated documentation files (the “Software”), to deal in
7+
the Software without restriction, including without limitation the rights to
8+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9+
the Software, and to permit persons to whom the Software is furnished to do so,
10+
subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

README.md

+135
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
# Faulty
2+
3+
Fault-tolerance tools for ruby based on [circuit-breakers][martin fowler].
4+
5+
```ruby
6+
users = Faulty.circuit(:api).try_run do
7+
api.users
8+
end.or_default([])
9+
```
10+
11+
## Installation
12+
13+
Add it to your `Gemfile`:
14+
15+
```ruby
16+
gem 'faulty'
17+
```
18+
19+
Or install it manually:
20+
21+
```sh
22+
gem 'faulty'
23+
```
24+
25+
During your app startup, call `Faulty.init`. For Rails, you would do this in
26+
`config/initializers/faulty.rb`.
27+
28+
## Setup
29+
30+
Use the default configuration options:
31+
32+
```ruby
33+
Faulty.init
34+
```
35+
36+
Or specify your own configuration:
37+
38+
```ruby
39+
Faulty.init do |config|
40+
config.storage = Faulty::Storage::Redis.new
41+
42+
listener = Faulty::Events::CallbackListener.new
43+
config.listeners = [
44+
Faulty::Events::CallbackListener.new do |events|
45+
events.circuit_open do |payload|
46+
puts 'Circuit was opened'
47+
end
48+
end
49+
]
50+
end
51+
```
52+
53+
For a full list of configuration options, see the Configuration section.
54+
55+
## Basic Usage
56+
57+
## Configuration
58+
59+
## Faulty's Circuit Breaker Algorithm
60+
61+
Faulty implements a version of circuit breakers inspired by
62+
[Martin Fowler's post][martin fowler] on the subject. A few notable features of
63+
Faulty's implementation are:
64+
65+
- Rate-based failure thresholds
66+
- Integrated caching inspired by Netflix's [Hystrix][hystrix] with automatic
67+
cache jitter and error fallback.
68+
- Event-based monitoring
69+
70+
## Circuit Options
71+
72+
## Caching
73+
74+
Faulty integrates caching into it's circuits in a way that is particularly
75+
suited to fault-tolerance. To make use of caching, you must specify the `cache`
76+
configuration option when initializing Faulty. If you're using Rails, this is
77+
automatically set to the Rails cache.
78+
79+
Once your cache is configured, you can use the `cache` parameter when running
80+
a circuit:
81+
82+
```ruby
83+
feed = Faulty.circuit(:rss_feeds)
84+
.try_run(cache: "rss_feeds/#{feed}" do
85+
fetch_feed(feed)
86+
end.or_default([])
87+
```
88+
89+
By default a circuit has the following options:
90+
91+
- `cache_expires_in`: 86400 (1 day). This is sent to the cache backend and
92+
defines how long the cache entry should be stored. After this time elapses,
93+
queries will result in a cache miss.
94+
- `cache_refreshes_after`: 900 (15 minutes). This is used internally by Faulty
95+
to indicate when a cache should be refreshed. It does not affect how long the
96+
cache entry is stored.
97+
- `cache_refresh_jitter`: 180 (3 minutes = 20% of `cache_refreshes_after`). The
98+
maximum number of seconds to randomly add or subtract from
99+
`cache_refreshes_after` when determining whether to refresh a cache entry.
100+
This mitigates the "thundering herd" effect caused by many processes
101+
simultaneously refreshing the cache.
102+
103+
This code will attempt to fetch an RSS feed protected by a circuit. If the feed
104+
is within the cache refresh period, then the result will be returned from the
105+
cache and the block will not be executed regardless of the circuit state.
106+
107+
If the cache is hit, but outside its refresh period, then Faulty will check the
108+
circuit state. If the circuit is closed or half-open, then it will run the
109+
block. If the block is successful, then it will update the circuit, write to the
110+
cache and return the new value.
111+
112+
However, if the cache is hit and the block fails, then that failure is noted
113+
in the circuit and Faulty returns the cached value.
114+
115+
If the circuit is open and the cache is hit, then Faulty will always return the
116+
cached value.
117+
118+
If the cache query results in a miss, then faulty operates as normal. In the
119+
code above, the block will be executed. If the block succeeds, the cache is
120+
refreshed. If the block fails, the default of `[]` will be returned.
121+
122+
## Fault Tolerance
123+
124+
## Event Handling
125+
126+
## Scopes
127+
128+
## Implementing a Storage Backend
129+
130+
## Implementing a Cache Backend
131+
132+
## Implementing a Event Listener
133+
134+
[martin fowler]: https://www.martinfowler.com/bliki/CircuitBreaker.html
135+
[hystrix]: https://github.com/Netflix/Hystrix/wiki/How-it-Works

faulty.gemspec

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
1010
spec.authors = ['Justin Howard']
1111
spec.email = ['[email protected]']
1212

13-
spec.summary = ''
13+
spec.summary = 'Fault-tolerance tools for ruby based on circuit-breakers'
1414
spec.homepage = 'https://github.com/ParentSquare/faulty'
1515

1616
spec.files = `git ls-files -z`
@@ -33,8 +33,8 @@ Gem::Specification.new do |spec|
3333
spec.add_development_dependency 'rspec_junit_formatter', '~> 0.4'
3434
# 0.81 is the last rubocop version with Ruby 2.3 support
3535
spec.add_development_dependency 'rubocop', '0.81.0'
36-
spec.add_development_dependency 'rubocop-rspec', '1.41.0'
37-
spec.add_development_dependency 'simplecov', '~> 0.18'
36+
spec.add_development_dependency 'rubocop-rspec', '1.38.1'
37+
spec.add_development_dependency 'simplecov', '>= 0.17.1'
3838
spec.add_development_dependency 'timecop', '>= 0.9'
3939
spec.add_development_dependency 'yard', '~> 0.9.25'
4040
end

lib/faulty.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def init(scope_name = :default, **config, &block)
4949
self
5050
end
5151

52-
# Get the default scope given during {#init}
52+
# Get the default scope given during {.init}
5353
#
5454
# @return [Scope, nil] The default scope if it is registered
5555
def default

lib/faulty/storage/memory.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ module Storage
1313
# circuits that are created. To that end, it's a good idea to avoid
1414
# dynamically-named circuits with this backend.
1515
#
16-
# For a more robust multi-process implementation, use the {Redis} storage
16+
# For a more robust distributed implementation, use the {Redis} storage
1717
# backend.
1818
#
1919
# This can be used as a reference implementation for storage backends that

spec/spec_helper.rb

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
if ENV['COVERAGE']
66
require 'simplecov'
77
SimpleCov.start do
8-
enable_coverage :branch
8+
if Gem::Version.new(SimpleCov::VERSION) >= Gem::Version.new('0.18.0')
9+
enable_coverage :branch
10+
end
911
add_filter '/spec/'
1012
add_filter '/vendor/'
1113
end

0 commit comments

Comments
 (0)