rcb 0.1.0 → 0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 61b7b710d6681c43cbe7b7d538d0eeda7199ee7e7c892e3aa2b0ddd1455a5a08
4
- data.tar.gz: 18449ecc9021e6dace52a8b07834544564234d1fe06170d81830a0c36aca5021
3
+ metadata.gz: '029e8ceda425ad3aea544142ab9307fd74ebff19fa98e359d791d820528f5638'
4
+ data.tar.gz: daf71c637318058ef6647531544c4fbe77404e08e0e705778ea77623f53d461d
5
5
  SHA512:
6
- metadata.gz: 263813bdacad4713d2cf411aa6f5caae798166290142e96aabce52c2b1bd95220fd008fbbd46188afd3f59834c58edcacc43d0537865cd0e7e0b90260829966f
7
- data.tar.gz: 95c4afc987cef799fbf40dbb29bbcaf08a94110d5b7996d076560951430975894bb2f35fa29a69b1cc24a6022ca54ff25f4587ff39e0d7b525cfff055651f67a
6
+ metadata.gz: 79cf1a6056c40f5abf501905ea0a3ac12e98eaaafd86a45e537b4db66ce343b6bc7c759c5ba74a7c7a0f1c7d66ec4e4c4f881c8e02f6627cbb89acab426fba29
7
+ data.tar.gz: b268096b37b3a3d13f7a7367ad5491b02dd65bbf21aa47637caa7f7afb67586470917b984913cf016e23d0d0c8020cddc0a4dbce16067189a2a79b95b4bc8df3
@@ -0,0 +1,22 @@
1
+ name: test
2
+ on: [push, pull_request]
3
+
4
+ jobs:
5
+ build:
6
+ runs-on: ubuntu-latest
7
+
8
+ steps:
9
+ - uses: actions/checkout@v1
10
+
11
+ - name: Set up Ruby 2.7
12
+ uses: clupprich/ruby-build-action@master
13
+ with:
14
+ ruby-version: 2.7.0
15
+
16
+ - name: Bundle install
17
+ run: |
18
+ bundle -j 4 --path vendor/bundle
19
+
20
+ - name: Run Tests
21
+ run: |
22
+ bundle exec rake test
data/README.md CHANGED
@@ -1,10 +1,13 @@
1
1
  # Rcb - Ruby Circuit Breaker
2
2
 
3
+ [![rcb](https://badge.fury.io/rb/rcb.svg)](https://badge.fury.io/rb/rcb)
4
+ [![Actions Status](https://github.com/petitviolet/rcb/workflows/test/badge.svg)](https://github.com/petitviolet/rcb/actions)
5
+
3
6
  [Circuit Breaker](https://martinfowler.com/bliki/CircuitBreaker.html) implementation for/by Ruby.
4
7
  CircuitBreaker is a great pattern to build robust system consists of bunch of microservices.
5
8
 
6
9
  - Close
7
- - A operational state
10
+ - An operational state
8
11
  - Open
9
12
  - A not operational state
10
13
  - Half Open
data/lib/rcb.rb CHANGED
@@ -3,9 +3,9 @@ require_relative "./rcb/configuration"
3
3
 
4
4
  module Rcb
5
5
  module ClassMethods
6
- def for(tag, max_failure_count: nil, reset_timeout_msec: nil)
6
+ def for(tag, open_condition: nil, reset_timeout_msec: nil)
7
7
  config = Rcb::Configurations.for(tag,
8
- max_failure_count: max_failure_count,
8
+ open_condition: open_condition,
9
9
  reset_timeout_msec: reset_timeout_msec)
10
10
  Instance.new(config)
11
11
  end
@@ -1,53 +1,83 @@
1
1
  require 'logger'
2
+ require 'rstructural'
2
3
 
3
4
  module Rcb
4
- Config = Struct.new(:tag, :max_failure_count, :reset_timeout_msec)do
5
- MAX_FAILURE_COUNT = 0.freeze
6
- RESET_TIMEOUT_MSEC = 0.freeze
5
+ OpenCondition = Rstruct.new(:max_failure_count, :window_msec) do
6
+ self::DEFAULT = new(3, 1000).freeze
7
+ end
8
+
9
+ Config = Rstruct.new(:tag, :open_condition, :reset_timeout_msec) do
10
+ self::RESET_TIMEOUT_MSEC = 1000.freeze
7
11
 
8
12
  @logger = Logger.new($stderr)
9
13
 
10
- def self.create(tag, max_failure_count: nil, reset_timeout_msec: nil)
14
+ def self.create(tag, open_condition: nil, reset_timeout_msec: nil)
11
15
  raise 'Rcb tag must not be nil' if tag.nil?
12
16
 
13
- if max_failure_count.nil? && reset_timeout_msec.nil?
17
+ if open_condition.nil? && reset_timeout_msec.nil?
14
18
  @logger.warn("Rcb for '#{tag}' is not configured!")
15
19
  end
16
20
 
17
21
  Config.new(
18
22
  tag.to_s.to_sym,
19
- max_failure_count || MAX_FAILURE_COUNT,
20
- reset_timeout_msec || RESET_TIMEOUT_MSEC
23
+ open_condition || OpenCondition::DEFAULT,
24
+ reset_timeout_msec || Config::RESET_TIMEOUT_MSEC
21
25
  )
22
26
  end
23
27
  end
24
28
 
25
- class ConfigBuilder
26
- def initialize(tag)
27
- @tag = tag
28
- @max_failure_count = nil
29
- @reset_timeout_msec = nil
30
- end
29
+ module DSL
30
+ class OpenConditionBuilder
31
+ def initialize
32
+ @max_failure_count = nil
33
+ @window_msec = nil
34
+ end
31
35
 
32
- def max_failure_count(num)
33
- @max_failure_count = num
34
- end
36
+ def max_failure_count(count)
37
+ @max_failure_count = count
38
+ end
39
+
40
+ def window_msec(msec)
41
+ @window_msec = msec
42
+ end
35
43
 
36
- def reset_timeout_msec(msec)
37
- @reset_timeout_msec = msec
44
+ def build
45
+ Rcb::OpenCondition.new(@max_failure_count, @window_msec)
46
+ end
38
47
  end
39
48
 
40
- def build
41
- Config.create(
42
- @tag,
43
- max_failure_count:@max_failure_count,
44
- reset_timeout_msec: @reset_timeout_msec
45
- ).freeze
49
+ class ConfigBuilder
50
+ def initialize(tag)
51
+ @tag = tag
52
+ @open_condition_builder = OpenConditionBuilder.new
53
+ @reset_timeout_msec = nil
54
+ end
55
+
56
+ def open_condition(hash = nil)
57
+ if hash
58
+ @open_condition_builder.max_failure_count hash[:max_failure_count]
59
+ @open_condition_builder.window_msec hash[:window_msec]
60
+ else
61
+ @open_condition_builder
62
+ end
63
+ end
64
+
65
+ def reset_timeout_msec(msec)
66
+ @reset_timeout_msec = msec
67
+ end
68
+
69
+ def build
70
+ Rcb::Config.create(
71
+ @tag,
72
+ open_condition: @open_condition_builder.build,
73
+ reset_timeout_msec: @reset_timeout_msec
74
+ ).freeze
75
+ end
46
76
  end
47
77
  end
48
78
 
49
79
  def Rcb.configure(tag, &block)
50
- c = ConfigBuilder.new(tag.to_s.to_sym)
80
+ c = DSL::ConfigBuilder.new(tag.to_s.to_sym)
51
81
  .tap { |cb| block.call(cb) }
52
82
  .build
53
83
 
@@ -57,9 +87,9 @@ module Rcb
57
87
  module Configurations
58
88
  @configs = {}
59
89
 
60
- def self.for(tag, max_failure_count: nil, reset_timeout_msec: nil)
90
+ def self.for(tag, open_condition: nil, reset_timeout_msec: nil)
61
91
  @configs[tag.to_s.to_sym] || Config.create(tag,
62
- max_failure_count: max_failure_count,
92
+ open_condition: open_condition,
63
93
  reset_timeout_msec: reset_timeout_msec)
64
94
  end
65
95
 
@@ -1,4 +1,3 @@
1
- require 'byebug'
2
1
  require 'rstructural'
3
2
  require_relative './state'
4
3
  require_relative './configuration'
@@ -5,18 +5,20 @@ require_relative './error'
5
5
  module Rcb::State
6
6
  extend ADT
7
7
 
8
- Close = data :failure_count do
9
- def self.create(failure_count = 0)
10
- new(failure_count)
8
+ Close = data :failure_times do
9
+ def self.create
10
+ new([])
11
11
  end
12
12
 
13
- def run(config, &block)
13
+ def run(config, now: Time.now.utc, &block)
14
14
  case try_call(&block)
15
15
  in Either::Right[result]
16
16
  Rcb::Result::Ok.new(self, result)
17
17
  in Either::Left[e]
18
- if config.max_failure_count > failure_count
19
- Rcb::Result::Ng.new(Close.create(failure_count + 1), e)
18
+ old_limit = now - (config.open_condition.window_msec / 1000.0)
19
+ refreshed_failure_times = failure_times.filter { |ft| old_limit <= ft } + [now]
20
+ if refreshed_failure_times.size < config.open_condition.max_failure_count
21
+ Rcb::Result::Ng.new(Close.new(refreshed_failure_times), e)
20
22
  else
21
23
  Rcb::Result::Ng.new(Open.create, e)
22
24
  end
@@ -1,8 +1,6 @@
1
- require_relative 'lib/rcb/version'
2
-
3
1
  Gem::Specification.new do |spec|
4
2
  spec.name = "rcb"
5
- spec.version = Rcb::VERSION
3
+ spec.version = '0.2.0'
6
4
  spec.authors = ["petitviolet"]
7
5
  spec.email = ["violethero0820@gmail.com"]
8
6
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rcb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - petitviolet
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-02-22 00:00:00.000000000 Z
11
+ date: 2020-02-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rstructural
@@ -73,6 +73,7 @@ executables: []
73
73
  extensions: []
74
74
  extra_rdoc_files: []
75
75
  files:
76
+ - ".github/workflows/action.yaml"
76
77
  - ".gitignore"
77
78
  - CODE_OF_CONDUCT.md
78
79
  - Gemfile
@@ -87,7 +88,6 @@ files:
87
88
  - lib/rcb/instance.rb
88
89
  - lib/rcb/result.rb
89
90
  - lib/rcb/state.rb
90
- - lib/rcb/version.rb
91
91
  - rcb.gemspec
92
92
  homepage: https://github.com/petitviolet/rcb
93
93
  licenses:
@@ -1,3 +0,0 @@
1
- module Rcb
2
- VERSION = "0.1.0"
3
- end