em_aws 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -4,5 +4,6 @@ source "http://rubygems.org"
4
4
  gemspec
5
5
 
6
6
  group :test do
7
- gem 'ZenTest', '4.8.2'
7
+ gem 'ZenTest', '~> 4.8.2'
8
+ gem 'eventmachine_httpserver', :require => 'evma_httpserver'
8
9
  end
data/Gemfile.lock CHANGED
@@ -9,15 +9,15 @@ PATH
9
9
  GEM
10
10
  remote: http://rubygems.org/
11
11
  specs:
12
- ZenTest (4.8.2)
13
- addressable (2.3.2)
14
- aws-sdk (1.8.1.2)
12
+ ZenTest (4.8.4)
13
+ addressable (2.3.3)
14
+ aws-sdk (1.8.3.1)
15
15
  json (~> 1.4)
16
16
  nokogiri (>= 1.4.4)
17
17
  uuidtools (~> 2.1)
18
- builder (3.1.4)
18
+ builder (3.2.0)
19
19
  cookiejar (0.3.0)
20
- diff-lcs (1.1.3)
20
+ diff-lcs (1.2.1)
21
21
  em-http-request (1.0.3)
22
22
  addressable (>= 2.2.3)
23
23
  cookiejar
@@ -30,20 +30,21 @@ GEM
30
30
  eventmachine (>= 1.0.0.beta.1)
31
31
  eventmachine (1.0.0)
32
32
  eventmachine (1.0.0-java)
33
+ eventmachine_httpserver (0.2.1)
33
34
  http_parser.rb (0.5.3)
34
35
  http_parser.rb (0.5.3-java)
35
- json (1.7.6)
36
- json (1.7.6-java)
36
+ json (1.7.7)
37
+ json (1.7.7-java)
37
38
  nokogiri (1.5.6)
38
39
  nokogiri (1.5.6-java)
39
- rspec (2.12.0)
40
- rspec-core (~> 2.12.0)
41
- rspec-expectations (~> 2.12.0)
42
- rspec-mocks (~> 2.12.0)
43
- rspec-core (2.12.2)
44
- rspec-expectations (2.12.1)
45
- diff-lcs (~> 1.1.3)
46
- rspec-mocks (2.12.2)
40
+ rspec (2.13.0)
41
+ rspec-core (~> 2.13.0)
42
+ rspec-expectations (~> 2.13.0)
43
+ rspec-mocks (~> 2.13.0)
44
+ rspec-core (2.13.0)
45
+ rspec-expectations (2.13.0)
46
+ diff-lcs (>= 1.1.3, < 2.0)
47
+ rspec-mocks (2.13.0)
47
48
  uuidtools (2.1.3)
48
49
 
49
50
  PLATFORMS
@@ -51,7 +52,8 @@ PLATFORMS
51
52
  ruby
52
53
 
53
54
  DEPENDENCIES
54
- ZenTest (= 4.8.2)
55
+ ZenTest (~> 4.8.2)
55
56
  builder
56
57
  em_aws!
58
+ eventmachine_httpserver
57
59
  rspec
data/HISTORY.md ADDED
@@ -0,0 +1,11 @@
1
+ EmAws Changelog
2
+ =====================
3
+
4
+ HEAD
5
+ =======
6
+
7
+ 0.2.5
8
+ =======
9
+
10
+ - For non-pooled request set em-http-request inactivity_timeout from aws request.read_timeout object. Remove retries based on status 0 [joshmckin, michalf, #13]
11
+ - Fetch port from request object [michalf, #13]
@@ -33,7 +33,6 @@ module AWS
33
33
  ]
34
34
  # @return [Hash] The default options to send to EM-Synchrony on each request.
35
35
  attr_reader :default_request_options
36
- attr_accessor :status_0_retries
37
36
 
38
37
  # Constructs a new HTTP handler using EM-Synchrony.
39
38
  # @param [Hash] options Default options to send to EM-Synchrony on
@@ -46,7 +45,6 @@ module AWS
46
45
  def initialize options = {}
47
46
  @default_request_options = options
48
47
  @pool = EMConnectionPool.new(options) if options[:pool_size].to_i > 0
49
- @status_0_retries = 2 # set to 0 for no retries
50
48
  end
51
49
 
52
50
  def handle(request,response,&read_block)
@@ -86,13 +84,7 @@ module AWS
86
84
  private
87
85
 
88
86
  def fetch_url(request)
89
- url = nil
90
- if request.use_ssl?
91
- url = "https://#{request.host}:443"
92
- else
93
- url = "http://#{request.host}"
94
- end
95
- url
87
+ "#{(request.use_ssl? ? "https" : "http")}://#{request.host}:#{request.port}"
96
88
  end
97
89
 
98
90
  def fetch_headers(request)
@@ -135,7 +127,9 @@ module AWS
135
127
  opts
136
128
  end
137
129
 
138
- def fetch_response(url,method,opts={},&read_block)
130
+ def fetch_response(request,opts={},&read_block)
131
+ method = "a#{request.http_method}".downcase.to_sym # aget, apost, aput, adelete, ahead
132
+ url = fetch_url(request)
139
133
  if @pool
140
134
  @pool.run(url) do |connection|
141
135
  req = connection.send(method, {:keepalive => true}.merge(opts))
@@ -143,7 +137,8 @@ module AWS
143
137
  return EM::Synchrony.sync req unless opts[:async]
144
138
  end
145
139
  else
146
- req = EM::HttpRequest.new(url).send(method,opts)
140
+ req = EM::HttpRequest.new(url,
141
+ :inactivity_timeout => request.read_timeout).send(method,opts)
147
142
  req.stream &read_block if block_given?
148
143
  return EM::Synchrony.sync req unless opts[:async]
149
144
  end
@@ -167,28 +162,19 @@ module AWS
167
162
  end
168
163
 
169
164
  # Builds and attempts the request. Occasionally under load em-http-request
170
- # returns a status of 0 with nil for header and body, in such situations
171
- # we retry as many times as status_0_retries is set. If our retries exceed
172
- # status_0_retries we assume there is a network error
173
- def process_request(request,response,async=false,retries=0,&read_block)
174
- method = "a#{request.http_method}".downcase.to_sym # aget, apost, aput, adelete, ahead
165
+ # em-http-request returns a status of 0 for various http timeouts, see:
166
+ # https://github.com/igrigorik/em-http-request/issues/76
167
+ # https://github.com/eventmachine/eventmachine/issues/175
168
+ def process_request(request,response,async=false,&read_block)
175
169
  opts = fetch_request_options(request)
176
170
  opts[:async] = (async || opts[:async])
177
- url = fetch_url(request)
178
171
  begin
179
- http_response = fetch_response(url,method,opts,&read_block)
172
+ http_response = fetch_response(request,opts,&read_block)
180
173
  unless opts[:async]
181
174
  response.status = http_response.response_header.status.to_i
182
- if response.status == 0
183
- if retries <= status_0_retries.to_i
184
- process_request(request,response,(retries + 1),&read_block)
185
- else
186
- response.network_error = true
187
- end
188
- else
189
- response.headers = fetch_response_headers(http_response)
190
- response.body = http_response.response
191
- end
175
+ raise Timeout::Error if response.status == 0
176
+ response.headers = fetch_response_headers(http_response)
177
+ response.body = http_response.response
192
178
  end
193
179
  rescue Timeout::Error => error
194
180
  response.network_error = error
@@ -1,3 +1,3 @@
1
1
  module EmAws
2
- VERSION = "0.2.4"
2
+ VERSION = "0.2.5"
3
3
  end
@@ -12,6 +12,8 @@
12
12
  # language governing permissions and limitations under the License.
13
13
 
14
14
  require 'spec_helper'
15
+ require 'eventmachine'
16
+ require 'evma_httpserver'
15
17
  module AWS::Core
16
18
  module Http
17
19
  class EMFooIO
@@ -19,8 +21,25 @@ module AWS::Core
19
21
  "/my_path/test.text"
20
22
  end
21
23
  end
24
+
25
+ # A slow server for testing timeout,
26
+ # borrowed from: http://www.igvita.com/2008/05/27/ruby-eventmachine-the-speed-demon/
27
+ class SlowServer < EventMachine::Connection
28
+ include EventMachine::HttpServer
29
+
30
+ def process_http_request
31
+ resp = EventMachine::DelegatedHttpResponse.new( self )
32
+
33
+ sleep 2 # Simulate a long running request
34
+
35
+ resp.status = 200
36
+ resp.content = "Hello World!"
37
+ resp.send_response
38
+ end
39
+ end
40
+
22
41
  describe EMHttpHandler do
23
-
42
+
24
43
  let(:handler) { EMHttpHandler.new(default_request_options) }
25
44
 
26
45
  let(:default_request_options) { {} }
@@ -40,16 +59,16 @@ module AWS::Core
40
59
  EMHttpHandler.should_receive(:fetch_response).with do |url, method,opts|
41
60
  options = opts
42
61
  double("http response",
43
- :response => "<foo/>",
44
- :code => 200,
45
- :to_hash => {})
62
+ :response => "<foo/>",
63
+ :code => 200,
64
+ :to_hash => {})
46
65
  end
47
66
  handler.handle(req, resp)
48
67
  options
49
68
  end
50
-
69
+
51
70
  it 'should be accessible from AWS as well as AWS::Core' do
52
- AWS::Http::EMHttpHandler.new.should
71
+ AWS::Http::EMHttpHandler.new.should
53
72
  be_an(AWS::Core::Http::EMHttpHandler)
54
73
  end
55
74
 
@@ -80,7 +99,7 @@ module AWS::Core
80
99
  context 'default request options' do
81
100
  before(:each) do
82
101
  handler.stub(:default_request_options).and_return({ :foo => "BAR",
83
- :private_key_file => "blarg" })
102
+ :private_key_file => "blarg" })
84
103
  end
85
104
 
86
105
  it 'passes extra options through to synchrony' do
@@ -90,32 +109,20 @@ module AWS::Core
90
109
  it 'uses the default when the request option is not set' do
91
110
  #puts handler.default_request_options
92
111
  handler.default_request_options[:private_key_file].should == "blarg"
93
- end
94
- end
95
- end
96
- describe '#process_request' do
97
- context 'too many retries' do
98
- it "should have network error" do
99
- EM.synchrony do
100
- resp.stub(:status).and_return(0)
101
- handler.send(:process_request,(req),(resp),false,3)
102
- resp.network_error?.should be_true
103
- EM.stop
104
- end
105
112
  end
106
113
  end
107
114
  end
115
+
108
116
  describe '#fetch_request_options' do
109
-
110
117
  it "should set :query and :body to request.querystring" do
111
118
  opts = handler.send(:fetch_request_options,(req))
112
119
  opts[:query].should eql(req.querystring)
113
120
  end
114
-
121
+
115
122
  it "should set :path to request.path" do
116
123
  opts = handler.send(:fetch_request_options,(req))
117
124
  opts[:path].should eql(req.path)
118
- end
125
+ end
119
126
  context "request.body_stream is a StringIO" do
120
127
  it "should set :body to request.body_stream" do
121
128
  opts = handler.send(:fetch_request_options,(req))
@@ -139,7 +146,7 @@ module AWS::Core
139
146
  handler.send(:fetch_proxy,(req))[:proxy][:port].should == 443
140
147
  end
141
148
  end
142
-
149
+
143
150
  describe '#fetch_ssl' do
144
151
  it 'prefers the request option when set' do
145
152
  req.use_ssl = true
@@ -148,7 +155,7 @@ module AWS::Core
148
155
  handler.send(:fetch_ssl,(req))[:private_key_file].should == "something"
149
156
  handler.send(:fetch_ssl,(req))[:cert_chain_file].should == "something"
150
157
  end
151
-
158
+
152
159
  context 'CA cert path' do
153
160
  context 'use_ssl? is true' do
154
161
 
@@ -164,7 +171,7 @@ module AWS::Core
164
171
  it 'should use the ssl_ca_file attribute of the request' do
165
172
  handler.send(:fetch_ssl,(req))[:private_key_file].should == "foobar.txt"
166
173
  end
167
-
174
+
168
175
  it 'should use the ssl_ca_file attribute of the request' do
169
176
  handler.send(:fetch_ssl,(req))[:cert_chain_file].should == "foobar.txt"
170
177
  end
@@ -179,8 +186,47 @@ module AWS::Core
179
186
  handler.send(:fetch_ssl,(req)).should_not include(:private_key_file)
180
187
  end
181
188
  end
182
- end
183
- end
189
+ end
190
+ end
191
+
192
+ it "should not timeout" do
193
+ EM.synchrony {
194
+ response = Http::Response.new
195
+ request = Http::Request.new
196
+ request.host = "127.0.0.1"
197
+ request.port = "8081"
198
+ request.uri = "/"
199
+ request.body_stream = StringIO.new("myStringIO")
200
+ # turn on our test server
201
+ EventMachine::run {
202
+ EventMachine::start_server request.host, request.port, SlowServer
203
+ }
204
+ handler.stub(:fetch_url).and_return("http://127.0.0.1:8081")
205
+ handler.handle(request,response)
206
+ response.network_error.should be_nil
207
+ EM.stop
208
+ }
209
+ end
210
+ it "should timeout after 0.1 seconds" do
211
+ EM.synchrony {
212
+ response = Http::Response.new
213
+ request = Http::Request.new
214
+ request.host = "127.0.0.1"
215
+ request.port = "8081"
216
+ request.uri = "/"
217
+ request.body_stream = StringIO.new("myStringIO")
218
+ # turn on our test server
219
+ EventMachine::run {
220
+ EventMachine::start_server request.host, request.port, SlowServer
221
+ }
222
+ handler.stub(:fetch_url).and_return("http://127.0.0.1:8081")
223
+ request.stub(:read_timeout).and_return(0.01)
224
+ handler.stub(:connect_timeout).and_return(1) #just to speed up the test
225
+ handler.handle(request,response)
226
+ response.network_error.should be_a(Timeout::Error)
227
+ EM.stop
228
+ }
229
+ end
184
230
  end
185
231
  end
186
- end
232
+ end
data/spec/spec_helper.rb CHANGED
@@ -5,8 +5,7 @@ require 'aws/core/http/em_http_handler'
5
5
  require 'rspec'
6
6
  require 'bundler/setup'
7
7
  require 'logger'
8
-
9
-
8
+ require 'em-http'
10
9
 
11
10
  # Requires supporting files with custom matchers and macros, etc,
12
11
  # in ./support/ and its subdirectories.
@@ -17,8 +16,6 @@ class StubLogger
17
16
  end
18
17
  end
19
18
  AWS.config(:logger => StubLogger.new)
20
- RSpec.configure do |config|
21
-
22
-
23
- end
24
19
 
20
+ RSpec.configure do |config|
21
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: em_aws
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.2.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-08 00:00:00.000000000 Z
12
+ date: 2013-03-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: aws-sdk
@@ -102,6 +102,7 @@ files:
102
102
  - .rspec
103
103
  - Gemfile
104
104
  - Gemfile.lock
105
+ - HISTORY.md
105
106
  - LICENSE.txt
106
107
  - README.md
107
108
  - Rakefile