circuitbox 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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