em_aws 0.1.10 → 0.2.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.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- em_aws (0.1.7)
4
+ em_aws (0.2.0)
5
5
  aws-sdk
6
6
  em-http-request
7
7
  em-synchrony
@@ -9,47 +9,47 @@ PATH
9
9
  GEM
10
10
  remote: http://rubygems.org/
11
11
  specs:
12
- addressable (2.2.8)
13
- aws-sdk (1.5.5)
12
+ addressable (2.3.2)
13
+ aws-sdk (1.8.0)
14
14
  httparty (~> 0.7)
15
15
  json (~> 1.4)
16
16
  nokogiri (>= 1.4.4)
17
17
  uuidtools (~> 2.1)
18
- builder (3.0.0)
18
+ builder (3.1.4)
19
19
  cookiejar (0.3.0)
20
20
  diff-lcs (1.1.3)
21
- em-http-request (1.0.2)
21
+ em-http-request (1.0.3)
22
22
  addressable (>= 2.2.3)
23
23
  cookiejar
24
24
  em-socksify
25
25
  eventmachine (>= 1.0.0.beta.4)
26
26
  http_parser.rb (>= 0.5.3)
27
- em-socksify (0.2.0)
27
+ em-socksify (0.2.1)
28
28
  eventmachine (>= 1.0.0.beta.4)
29
29
  em-synchrony (1.0.2)
30
30
  eventmachine (>= 1.0.0.beta.1)
31
- eventmachine (1.0.0.rc.4)
32
- eventmachine (1.0.0.rc.4-java)
31
+ eventmachine (1.0.0)
32
+ eventmachine (1.0.0-java)
33
33
  http_parser.rb (0.5.3)
34
34
  http_parser.rb (0.5.3-java)
35
- httparty (0.8.3)
35
+ httparty (0.9.0)
36
36
  multi_json (~> 1.0)
37
37
  multi_xml
38
- json (1.7.3)
39
- json (1.7.3-java)
40
- multi_json (1.3.6)
38
+ json (1.7.6)
39
+ json (1.7.6-java)
40
+ multi_json (1.5.0)
41
41
  multi_xml (0.5.1)
42
- nokogiri (1.5.5)
43
- nokogiri (1.5.5-java)
44
- rspec (2.10.0)
45
- rspec-core (~> 2.10.0)
46
- rspec-expectations (~> 2.10.0)
47
- rspec-mocks (~> 2.10.0)
48
- rspec-core (2.10.1)
49
- rspec-expectations (2.10.0)
42
+ nokogiri (1.5.6)
43
+ nokogiri (1.5.6-java)
44
+ rspec (2.12.0)
45
+ rspec-core (~> 2.12.0)
46
+ rspec-expectations (~> 2.12.0)
47
+ rspec-mocks (~> 2.12.0)
48
+ rspec-core (2.12.2)
49
+ rspec-expectations (2.12.1)
50
50
  diff-lcs (~> 1.1.3)
51
- rspec-mocks (2.10.1)
52
- uuidtools (2.1.2)
51
+ rspec-mocks (2.12.1)
52
+ uuidtools (2.1.3)
53
53
 
54
54
  PLATFORMS
55
55
  java
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010-2012 Joshua T. Mckinney
1
+ Copyright (c) 2010-2013 Joshua T. Mckinney
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # EmAws
2
- An EM-Synchrony handler for Ruby [AWS-SDK](https://github.com/amazonwebservices/aws-sdk-for-ruby/)
2
+ An EM-Synchrony handler for Ruby [AWS-SDK-Ruby](https://github.com/aws/aws-sdk-ruby)
3
3
 
4
4
  ## Installation
5
5
 
@@ -8,7 +8,7 @@ em_aws is available through [Rubygems](https://rubygems.org/gems/em_aws) and can
8
8
  $ gem install em_aws
9
9
 
10
10
  ## Rails 3 setup (no rails 2 sorry)
11
- Setup [AWS-SKD](https://github.com/amazonwebservices/aws-sdk-for-ruby/blob/master/README.rdoc) as you would normally.
11
+ Setup [AWS-SDK-Ruby](https://github.com/aws/aws-sdk-ruby/blob/master/README.rdoc) as you would normally.
12
12
 
13
13
  Assuming you've already setup async-rails, add em_aws to you gemfile:
14
14
 
@@ -25,16 +25,57 @@ In your environments files add:
25
25
  AWS.eager_autoload! # AWS lazyloading is not threadsafe
26
26
  AWS.config(
27
27
  :http_handler => AWS::Http::EMHttpHandler.new(
28
- :proxy => {:host => "http://myproxy.com", :port => 80}
29
- ))
28
+ :proxy => {:host => "http://myproxy.com", :port => 80}))
29
+ :pool_size => 0 # by default connection pooling is off
30
+ :async => false # if set to true all requests for this client will be asynchronous
30
31
 
31
32
  Your done.
32
33
 
33
- All requests to AWS will use EM-Synchrony's implementation of em-http-request for non-block HTTP request and fiber management.
34
+ All requests to AWS will use EM-Synchrony's implementation of em-http-request for non-block HTTP requests and fiber management.
35
+
36
+ ## Connection Pooling (keep-alive)
37
+ To enable connection pooling set the :pool_size to anything greater than 0. By default :inactivity_timeout is set
38
+ to 0 which will leave the connection open for as long as the client allows. Connects
39
+ are created lazy, so pools grow until they meet the set pool size.
40
+
41
+ require 'aws-sdk'
42
+ require 'aws/core/http/em_http_handler'
43
+ AWS.config(
44
+ :http_handler => AWS::Http::EMHttpHandler.new({
45
+ :pool_size => 20,
46
+ :inactivity_timeout => 0, # number of seconds to timeout stale connections in the pool,
47
+ :never_block => true, # if we run out of connections, create a new one
48
+ :proxy => {:host => "http://myproxy.com",:port => 80})
49
+ )
50
+
51
+ ## Streaming
52
+ Requires [AWS-SKD-Ruby >= 1.6.3] (http://aws.amazon.com/releasenotes/Ruby/5728376747252106)
53
+ EM.synchrony do
54
+ s3 = AWS::S3.new
55
+ file = File.open("path_to_file")
56
+ s3.buckets['bucket_name'].objects["foo.txt"].write(file)
57
+ EM.stop
58
+ end
59
+
60
+ ## Asynchronous Requests
61
+ Requests can be set to perform asynchronously, returning nil initially and performing
62
+ the actions in the background. If the request option :async are set to true that only
63
+ that request request will handled asynchronously. If the client option :async all requests will
64
+ be handled asynchronously.
65
+
66
+ EM.synchrony do
67
+ s3 = AWS::S3.new
68
+ s3.buckets['bucket-name'].objects["foo"].write('test', :async => true) # => nil
69
+ EM::Synchrony.sleep(2) # Let the pending fibers run
70
+ s3.buckets['bucket-name'].objects["foo"].read # => # 'test'
71
+ s3.buckets['bucket-name'].objects["foo"].delete(:async => true) # => nil
72
+ EM::Synchrony.sleep(2) # Let the pending fibers run
73
+ EM.stop
74
+ end
34
75
 
35
76
  ## References
36
77
 
37
- [aws-sdk](https://github.com/amazonwebservices/aws-sdk-for-ruby)
78
+ [AWS-SDK-Ruby](https://github.com/aws/aws-sdk-ruby)
38
79
 
39
80
  [Async-Rails](https://github.com/igrigorik/async-rails)
40
81
 
@@ -52,9 +93,9 @@ All requests to AWS will use EM-Synchrony's implementation of em-http-request fo
52
93
 
53
94
  ## Thanks
54
95
 
55
- Code based on HTTParty Hander in [aws-sdk](https://github.com/amazonwebservices/aws-sdk-for-ruby/blob/master/README.rdoc)
96
+ Code based on HTTP Handers in [AWS-SDK-Ruby](https://github.com/aws/aws-sdk-ruby/blob/master/README.rdoc)
56
97
 
57
98
  ## License
58
99
 
59
100
  EmAws [license](https://github.com/JoshMcKin/em_aws/blob/master/LICENSE.txt)
60
- AWS-SDK [license](https://github.com/amazonwebservices/aws-sdk-for-ruby/blob/master/LICENSE.txt)
101
+ AWS-SDK-Ruby [license](https://github.com/aws/aws-sdk-for-ruby/blob/master/LICENSE.txt)
@@ -0,0 +1,120 @@
1
+ require 'thread'
2
+ require "em-synchrony/em-http"
3
+ require 'em-synchrony/thread'
4
+
5
+ module AWS
6
+ module Core
7
+ module Http
8
+ class EMConnectionPool
9
+ # Since AWS connections may be to any number of urls, the connection
10
+ # pool is a hash of connection arrays, instead of a simple array like
11
+ # most connection pools
12
+ # Stores data concerning pools, like current size, last fetched
13
+ #
14
+ # Options:
15
+ # * :pool_size - number of connections for each pool
16
+ # * :inactivity_timeout - number of seconds to wait before disconnecting,
17
+ # setting to 0 means the connection will not be closed
18
+ # * :pool_timeout - the amount of seconds to block waiting for an available connection,
19
+ # because this is blocking it should be an extremely short amount of
20
+ # time default to 0.5 seconds, if you need more consider enlarging your pool
21
+ # instead of raising this number
22
+ # :never_block - if set to true, a connection will always be returned
23
+ def initialize(options={})
24
+ options[:never_block] ||= true
25
+ @pools = {}
26
+ @pool_data = {}
27
+ @pool_size = (options[:pool_size] || 5)
28
+ @never_block = (options[:never_block])
29
+ @inactivity_timeout = (options[:inactivity_timeout].to_i)
30
+ @pool_timeout = (options[:pool_timeout] || 0.5)
31
+ end
32
+
33
+ # A fiber safe mutex
34
+ def _fiber_mutex
35
+ @fibered_mutex ||= EM::Synchrony::Thread::Mutex.new
36
+ end
37
+
38
+ # Returns a pool for the associated url
39
+ def available_pools(url)
40
+ _fiber_mutex.synchronize do
41
+ add_connection(url) if add_connection?(url)
42
+ @pools[url]
43
+ end
44
+ end
45
+
46
+ def add_connection?(url)
47
+ (@pool_data[url].nil? || (@pools[url].length == 0 && (@pool_data[url][:current_size] < @pool_size)))
48
+ end
49
+
50
+ def add_connection(url)
51
+ AWS.config.logger.info "Adding AWS connection to #{url}"
52
+ add_connection_data(url)
53
+ @pools[url] ||= []
54
+ @pools[url] << new_connection(url)
55
+ @pools[url]
56
+ end
57
+
58
+ def add_connection_data(url)
59
+ @pool_data[url] ||= {:current_size => 0}
60
+ @pool_data[url][:current_size] += 1
61
+ end
62
+
63
+ def new_connection(url)
64
+ EM::HttpRequest.new(url, :inactivity_timeout => @inactivity_timeout)
65
+ end
66
+
67
+ # Run the block on the retrieved connection, then return the connection
68
+ # back to the pool.
69
+ def run(url, &block)
70
+ connection = santize_connection(fetch_connection(url))
71
+ block.call(connection)
72
+ ensure
73
+ return_connection(url,connection)
74
+ end
75
+
76
+ # Fetch an available connection or raise an error
77
+ def fetch_connection(url)
78
+ connection = nil
79
+ alarm = (Time.now + @pool_timeout)
80
+ # block until we get an available connection or Timeout::Error
81
+ while connection.nil?
82
+ if alarm <= Time.now
83
+ message = "Could not fetch a free connection in time. Consider increasing your connection pool for em_aws or setting :never_block to true."
84
+ AWS.config.logger.error message
85
+ raise Timeout::Error, message
86
+ end
87
+ connection = available_pools(url).shift
88
+ if connection.nil? && (@never_block)
89
+ AWS.config.logger.info "Adding AWS connection to #{url} for never_block, will not be returned to pool."
90
+ connection = new_connection(url)
91
+ end
92
+ end
93
+ connection
94
+ end
95
+
96
+ # Make sure we have a good connection.
97
+ def santize_connection(connection)
98
+ if connection.conn && connection.conn.error?
99
+ AWS.config.logger.info "Reconnecting to AWS: #{EventMachine::report_connection_error_status(connection.conn.instance_variable_get(:@signature))}"
100
+ connection.conn.close_connection
101
+ connection.instance_variable_set(:@deferred, true)
102
+ end
103
+ connection
104
+ end
105
+
106
+ # Return connections to pool if allowed, otherwise closes connection
107
+ def return_connection(url,connection)
108
+ _fiber_mutex.synchronize do
109
+ if (@pools[url].nil? || (@pools[url].length == @pool_size))
110
+ connection.conn.close_connection if connection.conn
111
+ else
112
+ @pools[url] << connection
113
+ end
114
+ @pools[url]
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
@@ -3,7 +3,6 @@ require "em-synchrony"
3
3
  require "em-synchrony/em-http"
4
4
  require 'em-synchrony/thread'
5
5
  module AWS
6
-
7
6
  module Core
8
7
  module Http
9
8
 
@@ -17,18 +16,19 @@ module AWS
17
16
  # require 'aws-sdk'
18
17
  # require 'aws/core/http/em_http_handler'
19
18
  # AWS.config(
20
- # :http_handler => AWS::Http::EMHttpHandler.new(
21
- # :proxy => {:host => "http://myproxy.com",:port => 80}
22
- # )
23
- # )
24
- #
19
+ # :http_handler => AWS::Http::EMHttpHandler.new(
20
+ # :proxy => {:host => "http://myproxy.com",
21
+ # :port => 80,
22
+ # :pool_size => 20, # not set by default which disables connection pooling
23
+ # :async => false # if set to true all requests are handle asynchronously and initially return nil
24
+ # }))
25
25
  class EMHttpHandler
26
- # @return [Hash] The default options to send to EM-Synchrony on each
27
- # request.
26
+
27
+ # @return [Hash] The default options to send to EM-Synchrony on each request.
28
28
  attr_reader :default_request_options
29
-
29
+ attr_accessor :status_0_retries
30
+
30
31
  # Constructs a new HTTP handler using EM-Synchrony.
31
- #
32
32
  # @param [Hash] options Default options to send to EM-Synchrony on
33
33
  # each request. These options will be sent to +get+, +post+,
34
34
  # +head+, +put+, or +delete+ when a request is made. Note
@@ -36,12 +36,48 @@ module AWS
36
36
  # ignored. If you need to set the CA file, you should use the
37
37
  # +:ssl_ca_file+ option to {AWS.config} or
38
38
  # {AWS::Configuration} instead.
39
- # Defaults pool_size to 5
40
39
  def initialize options = {}
41
- #puts "Using EM-Synchrony for AWS requests"
42
40
  @default_request_options = options
41
+ @pool = EMConnectionPool.new(options) if options[:pool_size].to_i > 0
42
+ @status_0_retries = 2 # set to 0 for no retries
43
+ end
44
+
45
+ def handle(request,response,&read_block)
46
+ if EM::reactor_running?
47
+ process_request(request,response,&read_block)
48
+ else
49
+ EM.synchrony do
50
+ process_request(request,response,&read_block)
51
+ EM.stop
52
+ end
53
+ end
54
+ end
55
+
56
+ # If the request option :async are set to true that request will handled
57
+ # asynchronously returning nil initially and processing in the background
58
+ # managed by EM-Synchrony. If the client option :async all requests will
59
+ # be handled asynchronously.
60
+ # EX:
61
+ # EM.synchrony do
62
+ # s3 = AWS::S3.new
63
+ # s3.obj.write('test', :async => true) => nil
64
+ # EM::Synchrony.sleep(2)
65
+ # s3.obj.read => # 'test'
66
+ # EM.stop
67
+ # end
68
+ def handle_async(request,response,handle,&read_block)
69
+ if EM::reactor_running?
70
+ process_request(request,response,true,&read_block)
71
+ else
72
+ EM.synchrony do
73
+ process_request(request,response,true,&read_block)
74
+ EM.stop
75
+ end
76
+ end
43
77
  end
44
78
 
79
+ private
80
+
45
81
  def fetch_url(request)
46
82
  url = nil
47
83
  if request.use_ssl?
@@ -53,15 +89,10 @@ module AWS
53
89
  end
54
90
 
55
91
  def fetch_headers(request)
56
- # Net::HTTP adds this header for us when the body is
57
- # provided, but it messes up signing
58
92
  headers = { 'content-type' => '' }
59
-
60
- # headers must have string values (net http calls .strip on them)
61
93
  request.headers.each_pair do |key,value|
62
94
  headers[key] = value.to_s
63
95
  end
64
-
65
96
  {:head => headers}
66
97
  end
67
98
 
@@ -82,51 +113,38 @@ module AWS
82
113
  opts
83
114
  end
84
115
 
85
- def request_options(request)
86
- fetch_headers(request).
87
- merge(fetch_proxy(request)).
88
- merge(fetch_ssl(request))
89
- end
90
-
91
- def fetch_response(url,method,opts={})
92
- return EM::HttpRequest.new("#{url}").send(method, opts)
93
- end
94
-
95
- def handle(request,response)
96
- if EM::reactor_running?
97
- handle_it(request, response)
98
- else
99
- EM.synchrony do
100
- handle_it(request, response)
101
- EM.stop
102
- end
103
- end
104
- end
105
-
106
- def handle_it(request, response)
107
- #puts "Using EM!!!!"
108
- # get, post, put, delete, head
109
- method = request.http_method.downcase.to_sym
110
- opts = default_request_options.merge(request_options(request))
116
+ def fetch_request_options(request,method)
117
+ opts = default_request_options.
118
+ merge(fetch_headers(request).
119
+ merge(fetch_proxy(request)).
120
+ merge(fetch_ssl(request)))
111
121
  if (method == :get)
112
122
  opts[:query] = request.body
113
123
  else
114
124
  opts[:body] = request.body
115
125
  end
116
- url = fetch_url(request)
117
- begin
118
- http_response = fetch_response(url,method,opts)
119
- response.status = http_response.response_header.status.to_i
120
- response.headers = to_aws_headers(http_response.response_header.raw.to_hash)
121
- response.body = http_response.response if response.status < 300
122
- rescue *AWS::Core::Http::NetHttpHandler::NETWORK_ERRORS
123
- response.network_error = true
126
+ opts
127
+ end
128
+
129
+ def fetch_response(url,method,opts={},&read_block)
130
+ if @pool
131
+ @pool.run(url) do |connection|
132
+ req = connection.send(method, {:keepalive => true}.merge(opts))
133
+ req.stream &read_block if block_given?
134
+ return EM::Synchrony.sync req unless opts[:async]
135
+ end
136
+ else
137
+ req = EM::HttpRequest.new(url).send(method,opts)
138
+ req.stream &read_block if block_given?
139
+ return EM::Synchrony.sync req unless opts[:async]
124
140
  end
141
+ nil
125
142
  end
126
143
 
127
144
  # AWS needs all headers downcased, and for some reason x-amz-expiration and
128
145
  # x-amz-restore need to be arrays
129
- def to_aws_headers(response_headers)
146
+ def fetch_response_headers(response)
147
+ response_headers = response.response_header.raw.to_hash
130
148
  aws_headers = {}
131
149
  response_headers.each_pair do |k,v|
132
150
  key = k.downcase
@@ -138,6 +156,35 @@ module AWS
138
156
  end
139
157
  response_headers.merge(aws_headers)
140
158
  end
159
+
160
+ # Builds and attempts the request. Occasionally under load em-http-request
161
+ # returns a status of 0 with nil for header and body, in such situations
162
+ # we retry as many times as status_0_retries is set. If our retries exceed
163
+ # status_0_retries we assume there is a network error
164
+ def process_request(request,response,async=false,retries=0,&read_block)
165
+ method = "a#{request.http_method}".downcase.to_sym # aget, apost, aput, adelete, ahead
166
+ opts = fetch_request_options(request,method)
167
+ opts[:async] = (async || opts[:async])
168
+ url = fetch_url(request)
169
+ begin
170
+ http_response = fetch_response(url,method,opts,&read_block)
171
+ unless opts[:async]
172
+ response.status = http_response.response_header.status.to_i
173
+ if response.status == 0
174
+ if retries <= status_0_retries.to_i
175
+ process_request(request,response,(retries + 1),&read_block)
176
+ else
177
+ response.network_error = true
178
+ end
179
+ else
180
+ response.headers = fetch_response_headers(http_response)
181
+ response.body = http_response.response
182
+ end
183
+ end
184
+ rescue *AWS::Core::Http::NetHttpHandler::NETWORK_ERRORS
185
+ response.network_error = true
186
+ end
187
+ end
141
188
  end
142
189
  end
143
190
  end
@@ -5,6 +5,8 @@ require 'em-http'
5
5
  require 'em-synchrony'
6
6
  require 'em-synchrony/em-http'
7
7
  require 'aws/core/autoloader'
8
+ require 'aws/core/http/em_connection_pool'
9
+ require 'aws/core/http/em_http_handler'
8
10
 
9
11
  AWS.eager_autoload! # lazy load isn't thread safe
10
- module EmAws;end
12
+ module EmAws;end
@@ -1,3 +1,3 @@
1
1
  module EmAws
2
- VERSION = "0.1.10"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -0,0 +1,103 @@
1
+ # To change this template, choose Tools | Templates
2
+ # and open the template in the editor.
3
+ require 'thread'
4
+ require "em-synchrony"
5
+ require "em-synchrony/em-http"
6
+ require 'spec_helper'
7
+ module AWS
8
+ module Core
9
+ module Http
10
+ describe EMConnectionPool do
11
+ before(:each) do
12
+ @em_connection_pool = EMConnectionPool.new
13
+ end
14
+
15
+ context 'default configuration' do
16
+ it "should have @pool_size of 5" do
17
+ @em_connection_pool.instance_variable_get(:@pool_size).should eql(5)
18
+ end
19
+
20
+ it "should have @inactivity_timeout of 0" do
21
+ @em_connection_pool.instance_variable_get(:@inactivity_timeout).should eql(0)
22
+ end
23
+
24
+ it "should have @pool_timeout of 0" do
25
+ @em_connection_pool.instance_variable_get(:@pool_timeout).should eql(0.5)
26
+ end
27
+ end
28
+
29
+ describe '#add_connection?' do
30
+ it "should be true if @pool_data does not have data for the url"do
31
+ @em_connection_pool.add_connection?("http://www.testurl123.com/").should be_true
32
+ end
33
+
34
+ it "should be true if @pool_data has data but the number of connnections has not reached the pool_size" do
35
+ @em_connection_pool.instance_variable_set(:@pools,{"http://www.testurl123.com/" => ["connection"]})
36
+ @em_connection_pool.add_connection?("http://www.testurl123.com/").should be_true
37
+ end
38
+
39
+ it "should be false pool has reached pool_size" do
40
+ @em_connection_pool.instance_variable_set(:@pools,
41
+ {"http://www.testurl123.com/" => ["connection","connection","connection","connection","connection"]})
42
+ @em_connection_pool.add_connection?("http://www.testurl123.com/").should be_true
43
+ end
44
+ end
45
+
46
+ describe '#add_connection' do
47
+ it "should add connections for supplied url"do
48
+ @em_connection_pool.add_connection("http://www.testurl123.com/")
49
+ @em_connection_pool.instance_variable_get(:@pools)["http://www.testurl123.com/"].should_not be_nil
50
+ end
51
+ end
52
+
53
+ describe '#fetch_connection' do
54
+ it "should raise Timeout::Error if an available is not found in time"do
55
+ @em_connection_pool.stub(:available_pools).and_return([])
56
+ @em_connection_pool.instance_variable_set(:@never_block, false)
57
+ lambda { @em_connection_pool.fetch_connection('http://some_url.com')}.should raise_error(Timeout::Error)
58
+ end
59
+ end
60
+
61
+ context 'integration test with parallel requests' do
62
+ # 10 parallel requests
63
+
64
+ it "should work" do
65
+ @requests_made = []
66
+ EM.synchrony do
67
+ @em_connection_pool.instance_variable_set(:@never_block, true)
68
+ fibers = []
69
+ 10.times do
70
+ fibers << Fiber.new do
71
+ @em_connection_pool.run "http://www.testurl123.com/" do |connection|
72
+ @requests_made << connection.get(:keepalive => true).response_header.status
73
+ end
74
+ end
75
+ end
76
+
77
+ fibers.each do |f|
78
+ f.resume
79
+ end
80
+
81
+ loop do
82
+ done = true
83
+ fibers.each do |f|
84
+ done = false if f.alive?
85
+ end
86
+ if done
87
+ break
88
+ else
89
+ EM::Synchrony.sleep(0.01)
90
+ end
91
+ end
92
+
93
+ @requests_made.length.should eql(10)
94
+ @em_connection_pool.instance_variable_get(:@pools)["http://www.testurl123.com/"].length.should eql(@em_connection_pool.instance_variable_get(:@pool_size))
95
+
96
+ EM.stop
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -46,17 +46,8 @@ module AWS::Core
46
46
  be_an(AWS::Core::Http::EMHttpHandler)
47
47
  end
48
48
 
49
- describe '#initialize' do
50
- it 'should set the default request options' do
51
- described_class.new(:foo => "BAR").default_request_options.
52
- should == { :foo => "BAR" }
53
- end
54
- end
55
-
56
49
  describe '#handle' do
57
-
58
50
  context 'timeouts' do
59
-
60
51
  it 'should rescue Timeout::Error' do
61
52
  handler.stub(:fetch_response).
62
53
  and_raise(Timeout::Error)
@@ -71,13 +62,12 @@ module AWS::Core
71
62
  should_not raise_error
72
63
  end
73
64
 
74
- it 'should indicate that there was a timeout' do
65
+ it 'should indicate that there was a network_error' do
75
66
  handler.stub(:fetch_response).
76
67
  and_raise(Errno::ETIMEDOUT)
77
68
  handler.handle(req, resp)
78
- resp.timeout?.should be_true
69
+ resp.network_error?.should be_true
79
70
  end
80
-
81
71
  end
82
72
 
83
73
  context 'default request options' do
@@ -93,19 +83,27 @@ module AWS::Core
93
83
  it 'uses the default when the request option is not set' do
94
84
  #puts handler.default_request_options
95
85
  handler.default_request_options[:private_key_file].should == "blarg"
86
+ end
87
+ end
88
+ end
89
+ describe '#process_request' do
90
+ context 'too many retries' do
91
+ it "should have network error" do
92
+ EM.synchrony do
93
+ handler.send(:process_request,(req),(resp),3)
94
+ resp.network_error?.should be_true
95
+ EM.stop
96
+ end
96
97
  end
97
-
98
98
  end
99
-
100
99
  end
101
100
  describe '#fetch_proxy' do
102
101
  context ':proxy_uri' do
103
102
  it 'passes proxy address and port from the request' do
104
103
  req.proxy_uri = URI.parse('https://user:pass@proxy.com:443/path?query')
105
- handler.fetch_proxy(req)[:proxy][:host].should == 'proxy.com'
106
- handler.fetch_proxy(req)[:proxy][:port].should == 443
104
+ handler.send(:fetch_proxy,(req))[:proxy][:host].should == 'proxy.com'
105
+ handler.send(:fetch_proxy,(req))[:proxy][:port].should == 443
107
106
  end
108
-
109
107
  end
110
108
 
111
109
  describe '#fetch_ssl' do
@@ -113,12 +111,11 @@ module AWS::Core
113
111
  req.use_ssl = true
114
112
  req.ssl_verify_peer = true
115
113
  req.ssl_ca_file = "something"
116
- handler.fetch_ssl(req)[:private_key_file].should == "something"
117
- handler.fetch_ssl(req)[:cert_chain_file].should == "something"
114
+ handler.send(:fetch_ssl,(req))[:private_key_file].should == "something"
115
+ handler.send(:fetch_ssl,(req))[:cert_chain_file].should == "something"
118
116
  end
119
117
 
120
118
  context 'CA cert path' do
121
-
122
119
  context 'use_ssl? is true' do
123
120
 
124
121
  before(:each) { req.use_ssl = true }
@@ -131,21 +128,21 @@ module AWS::Core
131
128
  end
132
129
 
133
130
  it 'should use the ssl_ca_file attribute of the request' do
134
- handler.fetch_ssl(req)[:private_key_file].should == "foobar.txt"
131
+ handler.send(:fetch_ssl,(req))[:private_key_file].should == "foobar.txt"
135
132
  end
136
133
 
137
134
  it 'should use the ssl_ca_file attribute of the request' do
138
- handler.fetch_ssl(req)[:cert_chain_file].should == "foobar.txt"
135
+ handler.send(:fetch_ssl,(req))[:cert_chain_file].should == "foobar.txt"
139
136
  end
140
137
  end
141
138
 
142
139
  it 'should not set the ssl_ca_file option without ssl_verify_peer?' do
143
- handler.fetch_ssl(req).should_not include(:private_key_file)
140
+ handler.send(:fetch_ssl,(req)).should_not include(:private_key_file)
144
141
  end
145
142
  end
146
143
 
147
144
  it 'should not set the ssl_ca_file option without use_ssl?' do
148
- handler.fetch_ssl(req).should_not include(:private_key_file)
145
+ handler.send(:fetch_ssl,(req)).should_not include(:private_key_file)
149
146
  end
150
147
  end
151
148
  end
@@ -4,14 +4,19 @@ require 'em_aws'
4
4
  require 'aws/core/http/em_http_handler'
5
5
  require 'rspec'
6
6
  require 'bundler/setup'
7
+ require 'logger'
7
8
 
8
9
 
9
10
 
10
11
  # Requires supporting files with custom matchers and macros, etc,
11
12
  # in ./support/ and its subdirectories.
12
13
  #Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
13
-
14
-
14
+ class StubLogger
15
+ def method_missing(method, *args)
16
+ #we don't care
17
+ end
18
+ end
19
+ AWS.config(:logger => StubLogger.new)
15
20
  RSpec.configure do |config|
16
21
 
17
22
 
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.1.10
4
+ version: 0.2.0
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-01-03 00:00:00.000000000 Z
12
+ date: 2013-01-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: aws-sdk
@@ -106,10 +106,12 @@ files:
106
106
  - README.md
107
107
  - Rakefile
108
108
  - em_aws.gemspec
109
+ - lib/aws/core/http/em_connection_pool.rb
109
110
  - lib/aws/core/http/em_http_handler.rb
110
111
  - lib/em_aws.rb
111
112
  - lib/em_aws/patches.rb
112
113
  - lib/em_aws/version.rb
114
+ - spec/em_connection_pool_spec.rb
113
115
  - spec/em_http_handler_spec.rb
114
116
  - spec/patches_spec.rb
115
117
  - spec/spec_helper.rb
@@ -138,6 +140,7 @@ signing_key:
138
140
  specification_version: 3
139
141
  summary: Adds EM-Synchrony support to AWS-SDK gem
140
142
  test_files:
143
+ - spec/em_connection_pool_spec.rb
141
144
  - spec/em_http_handler_spec.rb
142
145
  - spec/patches_spec.rb
143
146
  - spec/spec_helper.rb