knifeswitch 1.1.1 → 1.2.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/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
|