expeditor 0.5.0 → 0.6.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/.travis.yml +4 -3
- data/CHANGELOG.md +5 -2
- data/README.md +14 -5
- data/examples/circuit_breaker.rb +27 -0
- data/lib/expeditor/bucket.rb +14 -8
- data/lib/expeditor/command.rb +5 -1
- data/lib/expeditor/service.rb +8 -2
- data/lib/expeditor/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 06fd643997ffcbbcf94b5243a56f00a31e4788a3
|
4
|
+
data.tar.gz: 6aa12d927eab977c0d0b6c822b78b37877555637
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f81815f7920543475b352185f62dca303173988600a16db97b329662f72d6405e14b7efd834b3ff2eb7d393e9eccf3daa4a8eb4072d36997c33cdca2e1f16ea0
|
7
|
+
data.tar.gz: 1623ce5ccf9f6537e6ce87f0b056742dec4d71157c9108aedefbf4fd2924fa41211c50c76d13f8e9bedaa15d25a1192af2fe5d1f2994d2ad4f33cad7719788f6
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
-
|
1
|
+
## 0.6.0
|
2
|
+
- Improve default configuration of circuit breaker [#25](https://github.com/cookpad/expeditor/pull/25)
|
3
|
+
- Default `non_break_count` is reduced from 100 to 20
|
4
|
+
- Return proper status of service [#26](https://github.com/cookpad/expeditor/pull/26)
|
5
|
+
- Use `Expeditor::Service#status` instead of `#current_status`
|
2
6
|
|
3
7
|
## 0.5.0
|
4
|
-
|
5
8
|
- Add a `current_thread` option of `Expeditor::Command#start` method to execute a task on current thread [#13](https://github.com/cookpad/expeditor/pull/13)
|
6
9
|
- Drop support for MRI 2.0.x [#15](https://github.com/cookpad/expeditor/pull/15)
|
7
10
|
- Deprecate Expeditor::Command#with_fallback. Use `set_fallback` instead [#14](https://github.com/cookpad/expeditor/pull/14)
|
data/README.md
CHANGED
@@ -126,20 +126,29 @@ command = Expeditor::Command.new(service: service) do
|
|
126
126
|
...
|
127
127
|
end
|
128
128
|
|
129
|
-
service.
|
129
|
+
service.status
|
130
130
|
# => #<Expeditor::Status:0x007fdeeeb18468 @break=0, @dependency=0, @failure=0, @rejection=0, @success=0, @timeout=0>
|
131
131
|
|
132
132
|
service.reset_status! # reset status in the service
|
133
133
|
```
|
134
134
|
|
135
135
|
### circuit breaker
|
136
|
+
The circuit breaker needs a service metrics (success, failure, timeout, ...) to decide open the circuit or not.
|
137
|
+
Expeditor's circuit breaker has a few configuration for how it collects service metrics and how it opens the circuit.
|
138
|
+
|
139
|
+
For service metrics, Expeditor collects them with the given time window.
|
140
|
+
The metrics is guradually collected by breaking given time window into some peice of short time windows and resetting previous metrics when passing each short time window.
|
141
|
+
|
142
|
+
`non_break_count` is used to ignore requests to the service which is not frequentlly requested. Configure this value considering your estimated "requests per period to the service".
|
143
|
+
For example, when `period = 10` and `non_break_count = 20` and the requests do not occur more than 20 per 10 seconds, the circuit never opens because Expeditor ignores that "small number of requests".
|
144
|
+
If you don't ignore the failures in that case, set `non_break_count` to smaller value than `20`.
|
136
145
|
|
137
146
|
```ruby
|
138
147
|
service = Expeditor::Service.new(
|
139
|
-
|
140
|
-
sleep: 1,
|
141
|
-
|
142
|
-
|
148
|
+
threshold: 0.5, # If the failure rate is more than or equal to threshold, the circuit will be opened.
|
149
|
+
sleep: 1, # If once the circuit is opened, the circuit is still open until sleep time seconds is passed even though failure rate is less than threshold.
|
150
|
+
non_break_count: 20 # If the total count of metrics is not more than non_break_count, the circuit is not opened even though failure rate is more than threshold.
|
151
|
+
period: 10, # Time window of collecting metrics (in seconds).
|
143
152
|
)
|
144
153
|
|
145
154
|
command = Expeditor::Command.new(service: service) do
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'expeditor'
|
2
|
+
|
3
|
+
service = Expeditor::Service.new
|
4
|
+
|
5
|
+
i = 1
|
6
|
+
loop do
|
7
|
+
puts '=' * 100
|
8
|
+
p i
|
9
|
+
|
10
|
+
command = Expeditor::Command.new(service: service, timeout: 1) {
|
11
|
+
sleep 0.001 # simulate remote resource access
|
12
|
+
if File.exist?('foo')
|
13
|
+
'result'
|
14
|
+
else
|
15
|
+
raise 'Demo error'
|
16
|
+
end
|
17
|
+
}.set_fallback { |e|
|
18
|
+
p e
|
19
|
+
'default value'
|
20
|
+
}.start
|
21
|
+
|
22
|
+
p command.get
|
23
|
+
p service.status
|
24
|
+
puts
|
25
|
+
|
26
|
+
i += 1
|
27
|
+
end
|
data/lib/expeditor/bucket.rb
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
require 'expeditor/status'
|
2
2
|
|
3
3
|
module Expeditor
|
4
|
+
# Bucket is a data structure like circular buffer. It holds some status
|
5
|
+
# objects and it rolls statuses each `per` time (default is 1 second). Once
|
6
|
+
# it reaches the end of statuses array, it backs to start of statuses array
|
7
|
+
# and then reset the status and resumes recording. This is done so that the
|
8
|
+
# statistics are recorded gradually with short time interval rahter than
|
9
|
+
# reset all the record every wide time range (default is 10 seconds).
|
4
10
|
class Bucket
|
5
11
|
def initialize(opts = {})
|
6
12
|
@mutex = Mutex.new
|
@@ -23,14 +29,14 @@ module Expeditor
|
|
23
29
|
def total
|
24
30
|
acc = @mutex.synchronize do
|
25
31
|
update
|
26
|
-
@statuses.inject([0, 0, 0, 0, 0, 0]) do |
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
32
|
+
@statuses.inject([0, 0, 0, 0, 0, 0]) do |i, s|
|
33
|
+
i[0] += s.success
|
34
|
+
i[1] += s.failure
|
35
|
+
i[2] += s.rejection
|
36
|
+
i[3] += s.timeout
|
37
|
+
i[4] += s.break
|
38
|
+
i[5] += s.dependency
|
39
|
+
i
|
34
40
|
end
|
35
41
|
end
|
36
42
|
status = Expeditor::Status.new
|
data/lib/expeditor/command.rb
CHANGED
@@ -238,7 +238,11 @@ module Expeditor
|
|
238
238
|
if @fallback_block
|
239
239
|
future = RichFuture.new(executor: executor) do
|
240
240
|
success, value, reason = Concurrent::SafeTaskExecutor.new(@fallback_block, rescue_exception: true).execute(reason)
|
241
|
-
|
241
|
+
if success
|
242
|
+
@ivar.set(value)
|
243
|
+
else
|
244
|
+
@ivar.fail(reason)
|
245
|
+
end
|
242
246
|
end
|
243
247
|
future.safe_execute
|
244
248
|
else
|
data/lib/expeditor/service.rb
CHANGED
@@ -7,8 +7,8 @@ module Expeditor
|
|
7
7
|
|
8
8
|
def initialize(opts = {})
|
9
9
|
@executor = opts.fetch(:executor) { Concurrent::ThreadPoolExecutor.new }
|
10
|
-
@threshold = opts.fetch(:threshold, 0.5)
|
11
|
-
@non_break_count = opts.fetch(:non_break_count,
|
10
|
+
@threshold = opts.fetch(:threshold, 0.5)
|
11
|
+
@non_break_count = opts.fetch(:non_break_count, 20)
|
12
12
|
@sleep = opts.fetch(:sleep, 1)
|
13
13
|
@bucket_opts = {
|
14
14
|
size: 10,
|
@@ -70,7 +70,13 @@ module Expeditor
|
|
70
70
|
@executor.shutdown
|
71
71
|
end
|
72
72
|
|
73
|
+
def status
|
74
|
+
@bucket.total
|
75
|
+
end
|
76
|
+
|
77
|
+
# @deprecated
|
73
78
|
def current_status
|
79
|
+
warn 'Expeditor::Service#current_status is deprecated. Please use #status instead'
|
74
80
|
@bucket.current
|
75
81
|
end
|
76
82
|
|
data/lib/expeditor/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: expeditor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- shohei-yasutake
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-04-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -111,6 +111,7 @@ files:
|
|
111
111
|
- Rakefile
|
112
112
|
- bin/console
|
113
113
|
- bin/setup
|
114
|
+
- examples/circuit_breaker.rb
|
114
115
|
- examples/example.rb
|
115
116
|
- expeditor.gemspec
|
116
117
|
- lib/expeditor.rb
|
@@ -143,7 +144,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
143
144
|
version: '0'
|
144
145
|
requirements: []
|
145
146
|
rubyforge_project:
|
146
|
-
rubygems_version: 2.
|
147
|
+
rubygems_version: 2.6.11
|
147
148
|
signing_key:
|
148
149
|
specification_version: 4
|
149
150
|
summary: Expeditor provides asynchronous execution and fault tolerance for microservices
|