excon-middleware-aws-exponential_backoff 0.0.1 → 0.0.2
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/README.md +5 -0
- data/excon-middleware-aws-exponential_backoff.gemspec +2 -0
- data/lib/excon/middleware/aws/exponential_backoff.rb +2 -2
- data/lib/excon/middleware/aws/exponential_backoff/version.rb +1 -1
- data/spec/exponential_backoff_spec.rb +45 -0
- data/spec/servers/aws.rb +43 -0
- data/spec/spec_helper.rb +15 -29
- data/spec/support/aws_error_helper.rb +29 -0
- data/spec/support/server_helper.rb +23 -0
- metadata +36 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2f924a60b2a1e3a03602c89a3129db0cda2e1551
|
4
|
+
data.tar.gz: 9a5086a9e03df332d549f8867ce86efdde285cf2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 38b0e9021987f793758bac30bec08c3ad17873476930f385fc2ceffda2916784a0dd2f6c364b6f63ec634d366733cdbaf6c506213693bace823e5d6d4a176c8c
|
7
|
+
data.tar.gz: 7c2d1a1a72a86a761a054d9919cca21f81d7603f2d7792169d0f97f562673b18d6d3b777d6106ff736b1c69517de4e8eb6c060ec258d545ad9aa76fdd71cc78f
|
data/README.md
CHANGED
@@ -36,3 +36,8 @@ end
|
|
36
36
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
37
37
|
4. Push to the branch (`git push origin my-new-feature`)
|
38
38
|
5. Create a new Pull Request
|
39
|
+
|
40
|
+
## Inspiration
|
41
|
+
|
42
|
+
* http://docs.aws.amazon.com/general/latest/gr/api-retries.html
|
43
|
+
* https://github.com/aws/aws-sdk-ruby/blob/master/lib/aws/core/client.rb
|
@@ -20,5 +20,7 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.add_development_dependency "bundler", "~> 1.6"
|
21
21
|
spec.add_development_dependency "rake"
|
22
22
|
spec.add_development_dependency "rspec"
|
23
|
+
spec.add_development_dependency "open4"
|
24
|
+
spec.add_development_dependency "sinatra"
|
23
25
|
spec.add_dependency "excon"
|
24
26
|
end
|
@@ -29,8 +29,8 @@ module Excon
|
|
29
29
|
def error_call(datum)
|
30
30
|
datum[:backoff] ||= {}
|
31
31
|
datum[:backoff][:max_retries] ||= 0
|
32
|
-
datum[:backoff][:max_delay]
|
33
|
-
datum[:backoff][:retry_count]
|
32
|
+
datum[:backoff][:max_delay] ||= 30
|
33
|
+
datum[:backoff][:retry_count] ||= 0
|
34
34
|
|
35
35
|
if (throttle?(datum) || server_error?(datum)) && should_retry?(datum)
|
36
36
|
do_backoff(datum)
|
@@ -6,6 +6,13 @@ class Stack
|
|
6
6
|
def response_call(datum); end
|
7
7
|
end
|
8
8
|
|
9
|
+
class Instrumentor
|
10
|
+
def instrument(name, datum, &block)
|
11
|
+
return unless block
|
12
|
+
block.call
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
9
16
|
RSpec.describe Excon::Middleware::AWS::ExponentialBackoff do
|
10
17
|
let(:stack) { Stack.new }
|
11
18
|
subject { Excon::Middleware::AWS::ExponentialBackoff.new(stack) }
|
@@ -70,6 +77,23 @@ RSpec.describe Excon::Middleware::AWS::ExponentialBackoff do
|
|
70
77
|
subject.do_handoff(datum)
|
71
78
|
end
|
72
79
|
|
80
|
+
it "can be instrumented" do
|
81
|
+
instrumentor = Instrumentor.new
|
82
|
+
datum = {
|
83
|
+
instrumentor: instrumentor,
|
84
|
+
instrumentor_name: "test"
|
85
|
+
}
|
86
|
+
|
87
|
+
expect(instrumentor).to receive(:instrument).with("test.backoff", datum).and_call_original
|
88
|
+
expect_any_instance_of(Kernel).to receive(:sleep)
|
89
|
+
subject.do_sleep(0, datum)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "works when not instrumented" do
|
93
|
+
expect_any_instance_of(Kernel).to receive(:sleep)
|
94
|
+
subject.do_sleep(0, {})
|
95
|
+
end
|
96
|
+
|
73
97
|
context :do_backoff do
|
74
98
|
let(:connection) { double("connection") }
|
75
99
|
let(:datum) {
|
@@ -103,4 +127,25 @@ RSpec.describe Excon::Middleware::AWS::ExponentialBackoff do
|
|
103
127
|
subject.do_backoff(datum)
|
104
128
|
end
|
105
129
|
end
|
130
|
+
|
131
|
+
it "should work against a real server" do
|
132
|
+
Excon.defaults[:mock] = false
|
133
|
+
Excon.defaults[:middlewares] << Excon::Middleware::AWS::ExponentialBackoff
|
134
|
+
|
135
|
+
datum = {
|
136
|
+
instrumentor: Instrumentor.new,
|
137
|
+
instrumentor_name: "test",
|
138
|
+
expects: [200],
|
139
|
+
backoff: {
|
140
|
+
max_retries: 3,
|
141
|
+
max_delay: 0
|
142
|
+
}
|
143
|
+
}
|
144
|
+
|
145
|
+
allow(Excon).to receive(:display_warning) # keep rspec output tidy even with unsupported request key :backoff
|
146
|
+
|
147
|
+
ServerHelper.with_server("aws") do
|
148
|
+
expect(Excon.get('http://127.0.0.1:9292/throttle/3', datum).body).to eq "OK"
|
149
|
+
end
|
150
|
+
end
|
106
151
|
end
|
data/spec/servers/aws.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "sinatra/base"
|
4
|
+
|
5
|
+
class PathRequestCounter
|
6
|
+
def initialize(app)
|
7
|
+
@app = app
|
8
|
+
@counter = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
path_info = env['PATH_INFO']
|
13
|
+
@counter[path_info] ||= 1
|
14
|
+
env['path_info.request.counter'] = @counter[path_info]
|
15
|
+
|
16
|
+
@app.call(env).tap do
|
17
|
+
@counter[path_info] += 1
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class AWS < Sinatra::Base
|
23
|
+
configure do
|
24
|
+
set :port, 9292
|
25
|
+
end
|
26
|
+
|
27
|
+
use PathRequestCounter
|
28
|
+
|
29
|
+
get '/throttle/:count' do
|
30
|
+
count = request.env['path_info.request.counter']
|
31
|
+
if count <= Integer(params[:count] || 0)
|
32
|
+
[400, {}, ["<Code>Throttling</Code>"]]
|
33
|
+
else
|
34
|
+
[200, {}, "OK"]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
if app_file == $0
|
39
|
+
start! do
|
40
|
+
$stderr.puts "ready"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,34 +1,6 @@
|
|
1
1
|
require "excon/middleware/aws/exponential_backoff"
|
2
2
|
|
3
|
-
|
4
|
-
def throttling_response
|
5
|
-
body = %(
|
6
|
-
<ErrorResponse xmlns="http://some-service.amazonaws.com/doc/2010-05-15/">
|
7
|
-
<Error>
|
8
|
-
<Type>Sender</Type>
|
9
|
-
<Code>Throttling</Code>
|
10
|
-
<Message>Rate exceeded</Message>
|
11
|
-
</Error>
|
12
|
-
</ErrorResponse>
|
13
|
-
)
|
14
|
-
|
15
|
-
Excon::Response.new(status: 400, body: body)
|
16
|
-
end
|
17
|
-
|
18
|
-
def request_time_too_skewed_response
|
19
|
-
body = %(
|
20
|
-
<Error>
|
21
|
-
<Code>RequestTimeTooSkewed</Code>
|
22
|
-
<Message>The difference between the request time and the current time is too large.</Message>
|
23
|
-
<ServerTime>2006-11-10T13:43:55Z</ServerTime>
|
24
|
-
<MaxAllowedSkewMilliseconds>900000</MaxAllowedSkewMilliseconds>
|
25
|
-
<RequestTime>Fri, 10 Nov 2006 13:28:46 GMT</RequestTime>
|
26
|
-
</Error>
|
27
|
-
)
|
28
|
-
|
29
|
-
Excon::Response.new(status: 400, body: body)
|
30
|
-
end
|
31
|
-
end
|
3
|
+
Dir[File.join(File.expand_path("../support", __FILE__), "**/*.rb")].each {|f| require f}
|
32
4
|
|
33
5
|
RSpec.configure do |config|
|
34
6
|
config.expect_with :rspec do |expectations|
|
@@ -46,4 +18,18 @@ RSpec.configure do |config|
|
|
46
18
|
Kernel.srand config.seed
|
47
19
|
|
48
20
|
config.include AWSErrorHelper
|
21
|
+
|
22
|
+
config.around(:each) do |example|
|
23
|
+
excon_defaults = Excon.defaults
|
24
|
+
Excon.defaults[:mock] = true
|
25
|
+
|
26
|
+
example.run
|
27
|
+
|
28
|
+
Excon.defaults = excon_defaults
|
29
|
+
Excon.stubs.clear
|
30
|
+
end
|
31
|
+
|
32
|
+
config.before(:all) do
|
33
|
+
Excon.stub({}, {:body => 'Fallback', :status => 200})
|
34
|
+
end
|
49
35
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module AWSErrorHelper
|
2
|
+
def throttling_response
|
3
|
+
body = %(
|
4
|
+
<ErrorResponse xmlns="http://some-service.amazonaws.com/doc/2010-05-15/">
|
5
|
+
<Error>
|
6
|
+
<Type>Sender</Type>
|
7
|
+
<Code>Throttling</Code>
|
8
|
+
<Message>Rate exceeded</Message>
|
9
|
+
</Error>
|
10
|
+
</ErrorResponse>
|
11
|
+
)
|
12
|
+
|
13
|
+
Excon::Response.new(status: 400, body: body)
|
14
|
+
end
|
15
|
+
|
16
|
+
def request_time_too_skewed_response
|
17
|
+
body = %(
|
18
|
+
<Error>
|
19
|
+
<Code>RequestTimeTooSkewed</Code>
|
20
|
+
<Message>The difference between the request time and the current time is too large.</Message>
|
21
|
+
<ServerTime>2006-11-10T13:43:55Z</ServerTime>
|
22
|
+
<MaxAllowedSkewMilliseconds>900000</MaxAllowedSkewMilliseconds>
|
23
|
+
<RequestTime>Fri, 10 Nov 2006 13:28:46 GMT</RequestTime>
|
24
|
+
</Error>
|
25
|
+
)
|
26
|
+
|
27
|
+
Excon::Response.new(status: 400, body: body)
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Adapted from excon's tests/test_helper.rb
|
2
|
+
module ServerHelper
|
3
|
+
|
4
|
+
extend self
|
5
|
+
|
6
|
+
def server_path(*parts)
|
7
|
+
File.expand_path(File.join(File.dirname(__FILE__), "..", "servers", *parts))
|
8
|
+
end
|
9
|
+
|
10
|
+
def with_server(name)
|
11
|
+
require "open4"
|
12
|
+
pid, w, r, e = Open4.popen4(server_path("#{name}.rb"))
|
13
|
+
|
14
|
+
until val = e.gets; val =~ /ready/ || val.nil?
|
15
|
+
puts val
|
16
|
+
end
|
17
|
+
|
18
|
+
yield
|
19
|
+
ensure
|
20
|
+
Process.kill(9, pid)
|
21
|
+
Process.wait(pid)
|
22
|
+
end
|
23
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: excon-middleware-aws-exponential_backoff
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Hale
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-09-
|
11
|
+
date: 2014-09-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,6 +52,34 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: open4
|
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: sinatra
|
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'
|
55
83
|
- !ruby/object:Gem::Dependency
|
56
84
|
name: excon
|
57
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -84,7 +112,10 @@ files:
|
|
84
112
|
- lib/excon/middleware/aws/exponential_backoff/include.rb
|
85
113
|
- lib/excon/middleware/aws/exponential_backoff/version.rb
|
86
114
|
- spec/exponential_backoff_spec.rb
|
115
|
+
- spec/servers/aws.rb
|
87
116
|
- spec/spec_helper.rb
|
117
|
+
- spec/support/aws_error_helper.rb
|
118
|
+
- spec/support/server_helper.rb
|
88
119
|
homepage: https://github.com/mikehale/excon-middleware-aws-exponential_backoff
|
89
120
|
licenses:
|
90
121
|
- MIT
|
@@ -112,4 +143,7 @@ summary: Excon middleware to exponentially backoff calling AWS APIs when throttl
|
|
112
143
|
or experiencing errors.
|
113
144
|
test_files:
|
114
145
|
- spec/exponential_backoff_spec.rb
|
146
|
+
- spec/servers/aws.rb
|
115
147
|
- spec/spec_helper.rb
|
148
|
+
- spec/support/aws_error_helper.rb
|
149
|
+
- spec/support/server_helper.rb
|