knifeswitch 1.1.1 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +11 -7
- data/lib/knifeswitch/circuit.rb +13 -2
- data/lib/knifeswitch/version.rb +3 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9c6aa778648af60364b2908e30af44007663408f56e151c8be0648582ada1148
|
4
|
+
data.tar.gz: 91c9fe63b444786c685fb4c58e1f2f3635fd462836097179813ce0610c79779f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c69427977d6d5a5c5ec5eea19e3cbb3606f0b7881c57938c33775d499a56f7a0ee017bdb5ebba4906e99075520969debdb77e77b612e9d2b64e924754b296712
|
7
|
+
data.tar.gz: 47a9dbfcd419a66f6423f08a9b1eeedf5a3fcd07a919366d195d16cabf98679efeaff9448f7f6dd9b7e26384286cfce2a474e5eec51e2ce0a211adf04a841d52
|
data/README.md
CHANGED
@@ -10,13 +10,13 @@ Yet another circuit breaker gem. This one strives to be as small and simple as p
|
|
10
10
|
circuit = Knifeswitch::Circuit.new(
|
11
11
|
namespace: 'whatever',
|
12
12
|
exceptions: [TimeoutExceptionToCatch, Timeout::Error],
|
13
|
-
error_threshold: 5,
|
14
|
-
error_timeout: 60
|
13
|
+
error_threshold: 5, # Open circuit after 5 consecutive errors
|
14
|
+
error_timeout: 60 # Stay open for 60 seconds
|
15
15
|
)
|
16
16
|
|
17
17
|
response = circuit.run { client.request(...) }
|
18
18
|
# 'run' will raise Knifeswitch::CircuitOpen if its error_threshold has
|
19
|
-
# been exceeded
|
19
|
+
# been exceeded: after a watched exception has been raised 5 times.
|
20
20
|
#
|
21
21
|
# The error threshold counter is shared among all Knifeswitch::Circuit
|
22
22
|
# instances with the same namespace. The counters are stored in the db,
|
@@ -28,6 +28,11 @@ response = circuit.run { client.request(...) }
|
|
28
28
|
# When closed, it will just run the block like normal and return the result.
|
29
29
|
```
|
30
30
|
|
31
|
+
### Disabling
|
32
|
+
|
33
|
+
To "disable" knifeswitch globally, set the environment variable `KNIFESWITCH=OFF`.
|
34
|
+
This makes all calls to `Knifeswitch::Circuit#run` yield unconditionally.
|
35
|
+
|
31
36
|
## Installation
|
32
37
|
Add this line to your application's Gemfile:
|
33
38
|
|
@@ -56,18 +61,17 @@ $ bin/dockertest
|
|
56
61
|
You'll need to set up the test Rails app's database. Edit `test/dummy/config/database.yml` as you see fit, and run:
|
57
62
|
|
58
63
|
```bash
|
59
|
-
$ rake knifeswitch:create_migrations db:create db:migrate
|
64
|
+
$ cd test/dummy && rake knifeswitch:create_migrations db:create db:migrate
|
60
65
|
```
|
61
|
-
inside of the `test/dummy` directory.
|
62
66
|
|
63
67
|
After that you can run:
|
64
68
|
```bash
|
65
69
|
$ bin/test
|
66
70
|
```
|
67
|
-
in the project root with no problem. If you end up changing the migration generation rake task, you'll have to
|
71
|
+
in the project root with no problem. If you end up changing the migration generation rake task, you'll have to manually remove the old migration from the dummy app.
|
68
72
|
|
69
73
|
## Limitations
|
70
74
|
|
71
75
|
To keep the gem simple, Knifeswitch depends on [Rails](https://github.com/rails/rails). Technically, it should be pretty simple to make Knifeswitch work without the Rails dependency, but for us since we use Rails it's easier to just keep it as is.
|
72
76
|
|
73
|
-
Knifeswitch
|
77
|
+
Knifeswitch softly depends on MySQL because it uses MySQL's `ON DUPLICATE KEY UPDATE` syntax.
|
data/lib/knifeswitch/circuit.rb
CHANGED
@@ -30,6 +30,7 @@ module Knifeswitch
|
|
30
30
|
# exceptions: an array of error types that bump the counter
|
31
31
|
# error_threshold: number of errors required to open the circuit
|
32
32
|
# error_timeout: seconds to keep the circuit open
|
33
|
+
# callback: proc to be called when watched errors raise
|
33
34
|
def initialize(
|
34
35
|
namespace: 'default',
|
35
36
|
exceptions: [Timeout::Error],
|
@@ -47,11 +48,15 @@ module Knifeswitch
|
|
47
48
|
# Call this with a block to execute the contents of the block under
|
48
49
|
# circuit breaker protection.
|
49
50
|
#
|
51
|
+
# When ENV['KNIFESWITCH'] == 'OFF', this method always just yields.
|
52
|
+
#
|
50
53
|
# Raises Knifeswitch::CircuitOpen when called while the circuit is open.
|
51
54
|
def run
|
55
|
+
return yield if turned_off?
|
56
|
+
|
52
57
|
with_connection do
|
53
58
|
if open?
|
54
|
-
callback
|
59
|
+
callback&.call CircuitOpen.new
|
55
60
|
raise CircuitOpen
|
56
61
|
end
|
57
62
|
|
@@ -60,7 +65,7 @@ module Knifeswitch
|
|
60
65
|
rescue Exception => error
|
61
66
|
if exceptions.any? { |watched| error.is_a?(watched) }
|
62
67
|
increment_counter!
|
63
|
-
callback
|
68
|
+
callback&.call error
|
64
69
|
else
|
65
70
|
reset_counter!
|
66
71
|
end
|
@@ -127,7 +132,13 @@ module Knifeswitch
|
|
127
132
|
|
128
133
|
private
|
129
134
|
|
135
|
+
# If this is true, knifeswitch should not do anything
|
136
|
+
def turned_off?
|
137
|
+
ENV['KNIFESWITCH']&.downcase == 'off'
|
138
|
+
end
|
139
|
+
|
130
140
|
def load_record
|
141
|
+
return nil if turned_off?
|
131
142
|
sql(:select_one, %(
|
132
143
|
SELECT counter, closetime FROM knifeswitch_counters
|
133
144
|
WHERE name = ?
|
data/lib/knifeswitch/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knifeswitch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nigel Baillie
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-10-
|
11
|
+
date: 2019-10-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|