cb2 0.0.1
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 +15 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +34 -0
- data/lib/breaker.rb +40 -0
- data/lib/cb2.rb +9 -0
- data/lib/error.rb +4 -0
- data/lib/strategies/rolling_window.rb +41 -0
- data/lib/strategies/stub.rb +14 -0
- metadata +106 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
YzM2YWYxM2YyMmMxMmQ4NWZkNjczYjM5OGQ3NDBlZTk4MjViODdlNw==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
YTcwMzhiMTAyMDk0Mjc5YzZkMWM0MzBmYmQ2OTM2ZGQ2NDJhMTE5OA==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MjYzYzVhNTFhNWJiMDgyMTBhZTMzYTg1Mjk5ZGFkZDRkMzM4MTY2YjdhMGI0
|
10
|
+
YjY2MTJhMDY0MzdkZjAyZTk2M2MxYWFjMTc5OTIyZWY0YjVhYWVmYmU1MmM0
|
11
|
+
ZDNhNWI4NWEwOGVhYmIyNTVmNmZlMDNhMjQwNmU0MTViNzAwMzE=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
NjY4OWQxMGZhYjI5OWFhYTk2ZWJkZGU4NDgwNTJiMDIyNjRmMmQ3OTk1OTRk
|
14
|
+
ZTcwNjhiM2UxNzEzNzQ2MGFlZDZjNTQ0ZjkwOGUxZjEwYzYzMTgzYzkyNjE4
|
15
|
+
N2UxZTU1ZTBlOGJhZjU4MWEzMzcxZTIwMzllMmFlMjRiMDYwNzQ=
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
cb2 (0.0.1)
|
5
|
+
redis (~> 3.1)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: http://rubygems.org/
|
9
|
+
specs:
|
10
|
+
diff-lcs (1.2.5)
|
11
|
+
rake (10.3.2)
|
12
|
+
redis (3.1.0)
|
13
|
+
rspec (3.1.0)
|
14
|
+
rspec-core (~> 3.1.0)
|
15
|
+
rspec-expectations (~> 3.1.0)
|
16
|
+
rspec-mocks (~> 3.1.0)
|
17
|
+
rspec-core (3.1.7)
|
18
|
+
rspec-support (~> 3.1.0)
|
19
|
+
rspec-expectations (3.1.2)
|
20
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
21
|
+
rspec-support (~> 3.1.0)
|
22
|
+
rspec-mocks (3.1.3)
|
23
|
+
rspec-support (~> 3.1.0)
|
24
|
+
rspec-support (3.1.2)
|
25
|
+
timecop (0.7.1)
|
26
|
+
|
27
|
+
PLATFORMS
|
28
|
+
ruby
|
29
|
+
|
30
|
+
DEPENDENCIES
|
31
|
+
cb2!
|
32
|
+
rake (> 0)
|
33
|
+
rspec (~> 3.1)
|
34
|
+
timecop (~> 0.7)
|
data/lib/breaker.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
class CB2::Breaker
|
2
|
+
attr_accessor :service, :strategy
|
3
|
+
|
4
|
+
def initialize(options)
|
5
|
+
@service = options[:service] || "default"
|
6
|
+
@strategy = initialize_strategy(options)
|
7
|
+
end
|
8
|
+
|
9
|
+
def run
|
10
|
+
if open?
|
11
|
+
raise CB2::BreakerOpen
|
12
|
+
end
|
13
|
+
|
14
|
+
begin
|
15
|
+
yield
|
16
|
+
rescue => e
|
17
|
+
strategy.process
|
18
|
+
raise e
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def open?
|
23
|
+
strategy.open?
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize_strategy(options)
|
27
|
+
strategy_options = options.dup.merge(service: self.service)
|
28
|
+
|
29
|
+
if options[:strategy].respond_to?(:open)
|
30
|
+
return options[:strategy].new(strategy_options)
|
31
|
+
end
|
32
|
+
|
33
|
+
case options[:strategy]
|
34
|
+
when nil, :rolling_window
|
35
|
+
CB2::RollingWindow.new(strategy_options)
|
36
|
+
when nil, :stub
|
37
|
+
CB2::Stub.new(strategy_options)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/cb2.rb
ADDED
data/lib/error.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
class CB2::RollingWindow
|
2
|
+
attr_accessor :service, :duration, :threshold, :reenable_after, :redis
|
3
|
+
|
4
|
+
def initialize(options)
|
5
|
+
@service = options.fetch(:service)
|
6
|
+
@duration = options.fetch(:duration)
|
7
|
+
@threshold = options.fetch(:threshold)
|
8
|
+
@reenable_after = options.fetch(:reenable_after)
|
9
|
+
@redis = Redis.current
|
10
|
+
end
|
11
|
+
|
12
|
+
def open?
|
13
|
+
redis.exists(cache_key)
|
14
|
+
end
|
15
|
+
|
16
|
+
def open!
|
17
|
+
redis.setex(cache_key, reenable_after, 1)
|
18
|
+
end
|
19
|
+
|
20
|
+
def process
|
21
|
+
key = "circuit-breaker-count-#{service}"
|
22
|
+
t = Time.now.to_i
|
23
|
+
pipeline = redis.pipelined do
|
24
|
+
# keep the sorted set clean
|
25
|
+
redis.zremrangebyscore(key, "-inf", t - duration)
|
26
|
+
# add as a random uuid because sorted sets won't take duplicate items:
|
27
|
+
redis.zadd(key, t, SecureRandom.uuid)
|
28
|
+
# just count how many errors are left in the set
|
29
|
+
redis.zcard(key)
|
30
|
+
end
|
31
|
+
if pipeline.last >= threshold
|
32
|
+
open!
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def cache_key
|
39
|
+
"circuit-breaker-#{service}"
|
40
|
+
end
|
41
|
+
end
|
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cb2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Pedro Belo
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-11-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: redis
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ! '>'
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ! '>'
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.1'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.1'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: timecop
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.7'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.7'
|
69
|
+
description: Implementation of the circuit breaker pattern in Ruby
|
70
|
+
email: pedrobelo@gmail.com
|
71
|
+
executables: []
|
72
|
+
extensions: []
|
73
|
+
extra_rdoc_files: []
|
74
|
+
files:
|
75
|
+
- Gemfile
|
76
|
+
- Gemfile.lock
|
77
|
+
- lib/breaker.rb
|
78
|
+
- lib/cb2.rb
|
79
|
+
- lib/error.rb
|
80
|
+
- lib/strategies/rolling_window.rb
|
81
|
+
- lib/strategies/stub.rb
|
82
|
+
homepage: http://github.com/pedro/cb2
|
83
|
+
licenses: []
|
84
|
+
metadata: {}
|
85
|
+
post_install_message:
|
86
|
+
rdoc_options: []
|
87
|
+
require_paths:
|
88
|
+
- lib
|
89
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
requirements: []
|
100
|
+
rubyforge_project:
|
101
|
+
rubygems_version: 2.2.2
|
102
|
+
signing_key:
|
103
|
+
specification_version: 4
|
104
|
+
summary: Circuit breaker
|
105
|
+
test_files: []
|
106
|
+
has_rdoc:
|