em_aws 0.2.4 → 0.2.5

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.
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