circuitbox 0.7.0 → 0.8.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
  SHA1:
3
- metadata.gz: 00e479410c5dfdf8769c828dfbfdcae074ee524c
4
- data.tar.gz: c2f06d9ceaa7ca95c6837a7abc01e79a93ecb81c
3
+ metadata.gz: a837fae089566b81f6ccd58a7b89b4c119f122d4
4
+ data.tar.gz: e78c6f2bf1437d2e5cd4495d106b8c822dbbd896
5
5
  SHA512:
6
- metadata.gz: d43fff58af3f25b93be58ecaac16d7b8a815ac275d4337ff6cbf65833c9e72c3c4b1ddd930165c1393df426fa0f9250b29585e987288a4af798b951073073dcf
7
- data.tar.gz: a1913c31ddc136a114ea659fe602f8358f6fecb7076cb2af6d954d04f014c70f9685c1fe871963b6cdd180e62701b9fd968aa4b5f70f5cc20ccd5e6ee8d79982
6
+ metadata.gz: bcd00fa6cb16dbb3a7ea62d912049a1b6c1d676b4c484f1e42e8ae65b060b215e673e3ec0ccb0ff2f15cce6ceff60c0b62e0ab1bc752a4b9d65674a74edf6afe
7
+ data.tar.gz: f066a4d85503ed0db075a0df074f9eacd5dd9740cc2a5af5fbb289c07b48a287cea07a64c75eb3ced6b37f06a410608f657a24ce9688cf49c0fae31171b9bb9f
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1
6
+ - 2.2
data/Gemfile CHANGED
@@ -3,16 +3,3 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in circuitbox.gemspec
4
4
  gemspec
5
5
 
6
- gem 'activesupport'
7
- gem 'logger'
8
- gem 'faraday'
9
-
10
- group :test do
11
- gem 'timecop'
12
- gem 'mocha'
13
- gem 'minitest'
14
- gem 'guard-minitest'
15
- gem 'gimme'
16
- gem 'terminal-notifier-guard'
17
- end
18
-
data/README.md CHANGED
@@ -1,3 +1,4 @@
1
+ ![Build Status](https://travis-ci.org/yammer/circuitbox.svg)
1
2
 
2
3
  # Circuitbox
3
4
 
@@ -69,7 +70,62 @@ You can also run `rake circuits:stats SERVICE={service_name}` to see successes,
69
70
  Add `PARTITION={partition_key}` to see the circuit for a particular partition.
70
71
  The stats are aggregated into 1 minute intervals.
71
72
 
72
- ## Faraday (Caveat: Open circuits return a nil response object)
73
+ ## Notifications
74
+
75
+ circuitbox use ActiveSupport Notifications.
76
+
77
+ Usage example:
78
+
79
+ **Log on circuit open/close:**
80
+
81
+ ```ruby
82
+ class CircuitOpenException < StandardError ; end
83
+
84
+ ActiveSupport::Notifications.subscribe('circuit_open') do |name, start, finish, id, payload|
85
+ circuit_name = payload[:circuit]
86
+ Rails.logger.warning("Open circuit for: #{circuit_name}")
87
+ end
88
+ ActiveSupport::Notifications.subscribe('circuit_close') do |name, start, finish, id, payload|
89
+ circuit_name = payload[:circuit]
90
+ Rails.logger.info("Close circuit for: #{circuit_name}")
91
+ end
92
+ ````
93
+
94
+ **generate metrics:**
95
+
96
+ ```ruby
97
+ $statsd = Statsd.new 'localhost', 9125
98
+
99
+ ActiveSupport::Notifications.subscribe('circuit_gauge') do |name, start, finish, id, payload|
100
+ circuit_name = payload[:circuit]
101
+ gauge = payload[:gauge]
102
+ value = payload[:value]
103
+ metrics_key = "circuitbox.circuit.#{circuit_name}.#{gauge}"
104
+
105
+ $statsd.gauge(metrics_key, value)
106
+ end
107
+ ```
108
+
109
+ `payload[:gauge]` can be:
110
+
111
+ - `failure_count`
112
+ - `success_count`
113
+ - `error_rate`
114
+
115
+ **warnings:**
116
+ in case of misconfiguration, circuitbox will fire a circuitbox_warning
117
+ notification.
118
+
119
+ ```ruby
120
+ ActiveSupport::Notifications.subscribe('circuit_warning') do |name, start, finish, id, payload|
121
+ circuit_name = payload[:circuit]
122
+ warning = payload[:message]
123
+ Rails.logger.warning("#{circuit_name} - #{warning}")
124
+ end
125
+
126
+ ```
127
+
128
+ ## Faraday
73
129
 
74
130
  Circuitbox ships with [Faraday HTTP client](https://github.com/lostisland/faraday) middleware.
75
131
 
@@ -77,19 +133,60 @@ Circuitbox ships with [Faraday HTTP client](https://github.com/lostisland/farada
77
133
  require 'faraday'
78
134
  require 'circuitbox/faraday_middleware'
79
135
 
80
- conn = Faraday::Connection.new(:url => "http://example.com") do |builder|
81
- builder.use Circuitbox::FaradayMiddleware
136
+ conn = Faraday.new(:url => "http://example.com") do |c|
137
+ c.use Circuitbox::FaradayMiddleware
82
138
  end
83
139
 
84
- if response = conn.get("/api")
140
+ response = conn.get("/api")
141
+ if response.success?
85
142
  # success
86
143
  else
87
144
  # failure or open circuit
88
145
  end
89
146
  ```
90
147
 
148
+ By default the Faraday middleware returns a `503` response when the circuit is
149
+ open, but this as many other things can be configured via middleware options
150
+
151
+ * `exceptions` pass a list of exceptions for the Circuitbreaker to catch,
152
+ defaults to Timeout and Request failures
153
+
154
+ ```ruby
155
+ c.use Circuitbox::FaradayMiddleware, exceptions: [Faraday::Error::TimeoutError]
156
+ ```
157
+
158
+ * `default_value` value to return for open circuits, defaults to 503 response
159
+ wrapping the original response given by the service and stored as
160
+ `original_response` property of the returned 503, this can be overwritten
161
+ either with a static value or a `lambda` which is passed the
162
+ original_response.
163
+
164
+ ```ruby
165
+ c.use Circuitbox::FaradayMiddleware, default_value: lambda { |response| ... }
166
+ ```
167
+
168
+ * `identifier` circuit id, defaults to request url
169
+
170
+ ```ruby
171
+ c.use Circuitbox::FaradayMiddleware, identifier: "service_name_circuit"
172
+ ```
173
+
174
+ * `circuit_breaker_run_options` options passed to the circuit run method, see
175
+ the main circuitbreaker for those.
176
+
177
+ ```ruby
178
+ conn.get("/api", circuit_breaker_run_options: {})
179
+ ```
180
+
181
+ * `circuit_breaker_options` options to initialize the circuit with defaults to
182
+ `{ volume_threshold: 10, exceptions: Circuitbox::FaradayMiddleware::DEFAULT_EXCEPTIONS }`
183
+
184
+ ```ruby
185
+ c.use Circuitbox::FaradayMiddleware, circuit_breaker_options: {}
186
+ ```
187
+
91
188
  ## TODO
92
- * Fix Faraday integration to return a Faraday response object
189
+ * ~~Fix Faraday integration to return a Faraday response object~~
93
190
  * Split stats into it's own repository
94
191
  * Circuit Breaker should raise an exception by default instead of returning nil
95
192
  * Refactor to use single state variable
data/circuitbox.gemspec CHANGED
@@ -18,9 +18,18 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_development_dependency "bundler", "~> 1.4"
21
+ spec.add_development_dependency "bundler"
22
22
  spec.add_development_dependency "rake"
23
- spec.add_development_dependency 'bundler-gem_version_tasks'
23
+ spec.add_development_dependency "rack"
24
+ spec.add_development_dependency "guard-minitest"
25
+ spec.add_development_dependency "guard"
26
+ spec.add_development_dependency "gimme"
27
+ spec.add_development_dependency "minitest"
28
+ spec.add_development_dependency "mocha"
29
+ spec.add_development_dependency "timecop"
30
+ spec.add_development_dependency "faraday"
31
+ spec.add_development_dependency "logger"
32
+ spec.add_development_dependency "bundler-gem_version_tasks"
24
33
 
25
34
  spec.add_dependency "activesupport"
26
35
  end
@@ -2,30 +2,90 @@ require 'faraday'
2
2
  require 'circuitbox'
3
3
 
4
4
  class Circuitbox
5
- class RequestError < StandardError; end
5
+ class FaradayMiddleware < Faraday::Middleware
6
+ class RequestFailed < StandardError; end
6
7
 
7
- class FaradayMiddleware < Faraday::Response::Middleware
8
+ DEFAULT_EXCEPTIONS = [
9
+ Faraday::Error::TimeoutError,
10
+ RequestFailed,
11
+ ]
8
12
 
9
- attr_accessor :identifier, :exceptions
13
+ class NullResponse < Faraday::Response
14
+ attr_reader :original_response
15
+ def initialize(response = nil)
16
+ @original_response = response
17
+ super(status: 503, response_headers: {})
18
+ end
19
+ end
20
+
21
+ attr_reader :opts
10
22
 
11
- def initialize(app, opts={})
12
- @identifier = opts.fetch(:identifier) { ->(env) { env.url }}
13
- @exceptions = opts.fetch(:exceptions) { [Faraday::Error::TimeoutError] }
23
+ def initialize(app, opts = {})
24
+ @app = app
25
+ @opts = opts
14
26
  super(app)
15
27
  end
16
28
 
17
- def call(env)
18
- id = identifier.respond_to?(:call) ? identifier.call(env) : identifier
19
- circuit = Circuitbox.circuit id, :exceptions => exceptions
20
- circuit.run do
21
- super(env)
29
+ def call(request_env)
30
+ service_response = nil
31
+ response = circuit(request_env).run(run_options(request_env)) do
32
+ service_response = @app.call(request_env)
33
+ raise RequestFailed unless service_response.success?
34
+ service_response
22
35
  end
36
+
37
+ response.nil? ? circuit_open_value(request_env, service_response) : response
38
+ end
39
+
40
+ def exceptions
41
+ circuit_breaker_options[:exceptions]
42
+ end
43
+
44
+ def identifier
45
+ @identifier ||= opts.fetch(:identifier, ->(env) { env[:url] })
46
+ end
47
+
48
+ private
49
+
50
+ def run_options(env)
51
+ env[:circuit_breaker_run_options] || {}
23
52
  end
24
53
 
25
- def on_complete(env)
26
- if !env.success?
27
- raise RequestError
54
+ def circuit_breaker_options
55
+ return @circuit_breaker_options if @current_adapter
56
+
57
+ @circuit_breaker_options = opts.fetch(:circuit_breaker_options, {})
58
+ @circuit_breaker_options.merge!(
59
+ exceptions: opts.fetch(:exceptions, DEFAULT_EXCEPTIONS),
60
+ volume_threshold: 10
61
+ )
62
+ end
63
+
64
+ def default_value
65
+ return @default_value if @default_value
66
+
67
+ default = opts.fetch(:default_value) do
68
+ lambda { |service_response| NullResponse.new(service_response) }
28
69
  end
70
+
71
+ @default_value = if default.respond_to?(:call)
72
+ default
73
+ else
74
+ lambda { |_| default }
75
+ end
76
+ end
77
+
78
+ def circuitbox
79
+ @circuitbox ||= opts.fetch(:circuitbox, Circuitbox)
80
+ end
81
+
82
+ def circuit_open_value(env, service_response)
83
+ env[:circuit_breaker_default_value] || default_value.call(service_response)
84
+ end
85
+
86
+ def circuit(env)
87
+ id = identifier.respond_to?(:call) ? identifier.call(env) : identifier
88
+ circuitbox.circuit id, circuit_breaker_options
29
89
  end
30
90
  end
31
91
  end
@@ -1,3 +1,3 @@
1
1
  class Circuitbox
2
- VERSION='0.7.0'
2
+ VERSION='0.8.0'
3
3
  end
@@ -1,5 +1,4 @@
1
1
  require 'test_helper'
2
- require 'circuitbox'
3
2
  require 'ostruct'
4
3
 
5
4
  class CircuitBreakerTest < Minitest::Test
@@ -1,5 +1,4 @@
1
1
  require 'test_helper'
2
- require 'circuitbox'
3
2
 
4
3
  class Circuitbox::ExampleStore < ActiveSupport::Cache::MemoryStore; end
5
4
 
@@ -1,41 +1,115 @@
1
1
  require 'test_helper'
2
- require_relative '../lib/circuitbox/faraday_middleware'
2
+ require 'circuitbox/faraday_middleware'
3
+
4
+ class SentialException < StandardError; end
3
5
 
4
6
  class Circuitbox
5
7
  class FaradayMiddlewareTest < Minitest::Test
6
8
 
9
+ attr_reader :app
7
10
  def setup
8
11
  @app = gimme
9
- @env = gimme
10
- give(@env).url { 'URL' }
12
+ end
13
+
14
+ def test_default_identifier
15
+ env = { url: "sential" }
16
+ assert_equal FaradayMiddleware.new(app).identifier.call(env), "sential"
17
+ end
18
+
19
+ def test_overwrite_identifier
20
+ middleware = FaradayMiddleware.new(app, identifier: "sential")
21
+ assert_equal middleware.identifier, "sential"
22
+ end
23
+
24
+ def test_overwrite_default_value_generator_lambda
25
+ stub_circuitbox
26
+ env = { url: "url" }
27
+ give(circuitbox).circuit("url", anything) { circuit }
28
+ default_value_generator = lambda { |_| :sential }
29
+ middleware = FaradayMiddleware.new(app,
30
+ circuitbox: circuitbox,
31
+ default_value: default_value_generator)
32
+ assert_equal middleware.call(env), :sential
33
+ end
11
34
 
12
- @middleware = FaradayMiddleware.new @app,
13
- :identifier => 'ID',
14
- :exceptions => [StandardError]
35
+ def test_overwrite_default_value_generator_static_value
36
+ stub_circuitbox
37
+ env = { url: "url" }
38
+ give(circuitbox).circuit("url", anything) { circuit }
39
+ middleware = FaradayMiddleware.new(app, circuitbox: circuitbox, default_value: :sential)
40
+ assert_equal middleware.call(env), :sential
15
41
  end
16
42
 
17
- def test_should_use_env_url_proc_if_not_provided_as_identifier
18
- middleware = FaradayMiddleware.new @app, :exceptions => gimme
19
- assert middleware.identifier.is_a?(Proc)
20
- assert_equal 'URL', middleware.identifier.call(@env)
43
+ def test_default_exceptions
44
+ middleware = FaradayMiddleware.new(app)
45
+ assert_includes middleware.exceptions, Faraday::Error::TimeoutError
46
+ assert_includes middleware.exceptions, FaradayMiddleware::RequestFailed
21
47
  end
22
48
 
23
- def test_should_use_request_error_if_not_provided_as_exception
24
- middleware = FaradayMiddleware.new @app, :identifier => 'ID'
25
- assert_equal [Faraday::Error::TimeoutError],
26
- middleware.exceptions
49
+ def test_overwrite_exceptions
50
+ middleware = FaradayMiddleware.new(app, exceptions: [SentialException])
51
+ assert_includes middleware.exceptions, SentialException
27
52
  end
28
53
 
29
- def test_successful_call
30
- @middleware.call(@env)
54
+ def test_pass_circuit_breaker_run_options
55
+ stub_circuitbox
56
+ give(circuit).run(:sential)
57
+ give(circuitbox).circuit("url", anything) { circuit }
58
+ env = { url: "url", circuit_breaker_run_options: :sential }
59
+ middleware = FaradayMiddleware.new(app, circuitbox: circuitbox)
60
+ middleware.call(env)
61
+ verify(circuit).run(:sential)
31
62
  end
32
63
 
33
- def test_failed_call
34
- assert_raises Circuitbox::RequestError do
35
- give(@env).success? { false }
36
- @middleware.on_complete(@env)
37
- end
64
+ def test_pass_circuit_breaker_options
65
+ stub_circuitbox
66
+ env = { url: "url" }
67
+ expected_circuit_breaker_options = {
68
+ sential: :sential,
69
+ exceptions: FaradayMiddleware::DEFAULT_EXCEPTIONS,
70
+ volume_threshold: 10
71
+ }
72
+ give(circuitbox).circuit("url", expected_circuit_breaker_options) { circuit }
73
+ options = { circuitbox: circuitbox, circuit_breaker_options: { sential: :sential } }
74
+ middleware = FaradayMiddleware.new(app, options)
75
+ middleware.call(env)
76
+
77
+ verify(circuitbox).circuit("url", expected_circuit_breaker_options)
78
+ end
79
+
80
+ def test_overwrite_circuitbreaker_default_value
81
+ stub_circuitbox
82
+ env = { url: "url", circuit_breaker_default_value: :sential }
83
+ give(circuitbox).circuit("url", anything) { circuit }
84
+ middleware = FaradayMiddleware.new(app, circuitbox: circuitbox)
85
+ assert_equal middleware.call(env), :sential
86
+ end
87
+
88
+ def test_return_value_closed_circuit
89
+ stub_circuitbox
90
+ env = { url: "url" }
91
+ give(circuit).run(anything) { :sential }
92
+ give(circuitbox).circuit("url", anything) { circuit }
93
+ middleware = FaradayMiddleware.new(app, circuitbox: circuitbox)
94
+ assert_equal middleware.call(env), :sential
95
+ end
96
+
97
+ def test_return_null_response_for_open_circuit
98
+ stub_circuitbox
99
+ env = { url: "url" }
100
+ give(circuit).run(anything) { nil }
101
+ give(circuitbox).circuit("url", anything) { circuit }
102
+ response = FaradayMiddleware.new(app, circuitbox: circuitbox).call(env)
103
+ assert_kind_of Faraday::Response, response
104
+ assert_equal response.status, 503
105
+ assert response.finished?
106
+ refute response.success?
38
107
  end
39
108
 
109
+ attr_reader :circuitbox, :circuit
110
+ def stub_circuitbox
111
+ @circuitbox = gimme
112
+ @circuit = gimme
113
+ end
40
114
  end
41
115
  end
@@ -0,0 +1,36 @@
1
+ require "integration_helper"
2
+
3
+ class Circuitbox
4
+ class FaradayMiddlewareTest < Minitest::Test
5
+ @@only_once = false
6
+ def setup
7
+ @connection = Faraday.new do |c|
8
+ c.use FaradayMiddleware
9
+ c.adapter Faraday.default_adapter
10
+ end
11
+ @success_url = "http://localhost:4711"
12
+ @failure_url = "http://localhost:4712"
13
+
14
+ if !@@only_once
15
+ FakeServer.create(4711, ['200', {'Content-Type' => 'text/plain'}, ["Success!"]])
16
+ FakeServer.create(4712, ['500', {'Content-Type' => 'text/plain'}, ["Failure!"]])
17
+ end
18
+ end
19
+
20
+ def teardown
21
+ Circuitbox.reset
22
+ end
23
+
24
+ def test_open_circuit_response
25
+ 10.times { @connection.get(@failure_url) } # make the CircuitBreaker open
26
+ open_circuit_response = @connection.get(@failure_url)
27
+ assert open_circuit_response.status, 503
28
+ assert_match open_circuit_response.original_response.body, "Failure!"
29
+ end
30
+
31
+ def test_closed_circuit_response
32
+ result = @connection.get(@success_url)
33
+ assert result.success?
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,40 @@
1
+ require "test_helper"
2
+ require "faraday"
3
+ require "circuitbox/faraday_middleware"
4
+ require "rack"
5
+
6
+ class FakeServer
7
+ def self.instance
8
+ @@instance ||= FakeServer.new
9
+ # if the FakeServer is used kill all of them after the tests are done
10
+ Minitest.after_run { FakeServer.shutdown }
11
+ @@instance
12
+ end
13
+
14
+ def initialize
15
+ @servers = []
16
+ end
17
+
18
+ def self.create(port, result)
19
+ FakeServer.instance.create(port, result)
20
+ end
21
+
22
+ def self.shutdown
23
+ FakeServer.instance.shutdown
24
+ end
25
+
26
+ def shutdown
27
+ @servers.map { |server| server.exit }
28
+ @servers = []
29
+ end
30
+
31
+ def create(port, result)
32
+ @servers << Thread.new do
33
+ Rack::Handler::WEBrick.run(Proc.new { |env| result },
34
+ Port: port,
35
+ AccessLog: [],
36
+ Logger: WEBrick::Log.new(DEV_NULL))
37
+ end
38
+ sleep 0.5 # wait for the server to spin up
39
+ end
40
+ end
data/test/test_helper.rb CHANGED
@@ -1,6 +1,15 @@
1
- require 'minitest'
2
1
  require 'minitest/autorun'
3
- require 'minitest/pride'
4
2
  require 'mocha/mini_test'
5
3
  require 'timecop'
6
4
  require 'gimme'
5
+ require 'circuitbox'
6
+
7
+ DEV_NULL = (RUBY_PLATFORM =~ /mswin|mingw/ ? "NUL" : "/dev/null")
8
+
9
+ class Circuitbox
10
+ class CircuitBreaker
11
+ def logger
12
+ @_dev_null_logger ||= Logger.new(DEV_NULL)
13
+ end
14
+ end
15
+ end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: circuitbox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fahim Ferdous
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-10 00:00:00.000000000 Z
11
+ date: 2015-03-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.4'
19
+ version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.4'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +38,132 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rack
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: guard-minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: guard
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: gimme
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: minitest
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: mocha
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: timecop
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: faraday
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: logger
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
41
167
  - !ruby/object:Gem::Dependency
42
168
  name: bundler-gem_version_tasks
43
169
  requirement: !ruby/object:Gem::Requirement
@@ -74,6 +200,7 @@ extensions: []
74
200
  extra_rdoc_files: []
75
201
  files:
76
202
  - ".gitignore"
203
+ - ".travis.yml"
77
204
  - Gemfile
78
205
  - Guardfile
79
206
  - LICENSE
@@ -91,6 +218,8 @@ files:
91
218
  - test/circuit_breaker_test.rb
92
219
  - test/circuitbox_test.rb
93
220
  - test/faraday_middleware_test.rb
221
+ - test/integration/faraday_middleware_test.rb
222
+ - test/integration_helper.rb
94
223
  - test/notifier_test.rb
95
224
  - test/test_helper.rb
96
225
  homepage: ''
@@ -121,5 +250,7 @@ test_files:
121
250
  - test/circuit_breaker_test.rb
122
251
  - test/circuitbox_test.rb
123
252
  - test/faraday_middleware_test.rb
253
+ - test/integration/faraday_middleware_test.rb
254
+ - test/integration_helper.rb
124
255
  - test/notifier_test.rb
125
256
  - test/test_helper.rb