em_aws 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,4 +1,3 @@
1
- Gemfile.lock
2
1
  pkg/*
3
2
  *.gem
4
3
  .bundle
data/Gemfile.lock ADDED
@@ -0,0 +1,54 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ em_aws (0.1.0)
5
+ aws-sdk
6
+ em-http-request
7
+ em-synchrony
8
+
9
+ GEM
10
+ remote: http://rubygems.org/
11
+ specs:
12
+ addressable (2.2.7)
13
+ aws-sdk (1.3.9)
14
+ httparty (~> 0.7)
15
+ json (~> 1.4)
16
+ nokogiri (>= 1.4.4)
17
+ uuidtools (~> 2.1)
18
+ cookiejar (0.3.0)
19
+ diff-lcs (1.1.3)
20
+ em-http-request (1.0.2)
21
+ addressable (>= 2.2.3)
22
+ cookiejar
23
+ em-socksify
24
+ eventmachine (>= 1.0.0.beta.4)
25
+ http_parser.rb (>= 0.5.3)
26
+ em-socksify (0.2.0)
27
+ eventmachine (>= 1.0.0.beta.4)
28
+ em-synchrony (1.0.0)
29
+ eventmachine (>= 1.0.0.beta.1)
30
+ eventmachine (1.0.0.beta.4)
31
+ http_parser.rb (0.5.3)
32
+ httparty (0.8.1)
33
+ multi_json
34
+ multi_xml
35
+ json (1.6.6)
36
+ multi_json (1.2.0)
37
+ multi_xml (0.4.2)
38
+ nokogiri (1.5.2)
39
+ rspec (2.9.0)
40
+ rspec-core (~> 2.9.0)
41
+ rspec-expectations (~> 2.9.0)
42
+ rspec-mocks (~> 2.9.0)
43
+ rspec-core (2.9.0)
44
+ rspec-expectations (2.9.1)
45
+ diff-lcs (~> 1.1.3)
46
+ rspec-mocks (2.9.0)
47
+ uuidtools (2.1.2)
48
+
49
+ PLATFORMS
50
+ ruby
51
+
52
+ DEPENDENCIES
53
+ em_aws!
54
+ rspec
data/README.md CHANGED
@@ -6,27 +6,55 @@ Until approval (or if it is declined) I created this gem.
6
6
 
7
7
  ## Installation
8
8
 
9
- em_aws is available through [Rubygems](http://rubygems.org/gems/simple_model) and can be installed via:
9
+ em_aws is available through [Rubygems](https://rubygems.org/gems/em_aws) and can be installed via:
10
10
 
11
11
  $ gem install em_aws
12
12
 
13
13
  ## Rails 3 setup (no rails 2 sorry)
14
14
  Setup [AWS-SKD](https://github.com/amazonwebservices/aws-sdk-for-ruby/blob/master/README.rdoc) as you would normally.
15
15
 
16
- Assuming you've already setup async-rails...
16
+ Assuming you've already setup async-rails, add em_aws to you gemfile:
17
+
18
+ gem 'em_aws'
19
+
20
+ Then run:
21
+
22
+ bundle install
17
23
 
18
24
  In your environments files add:
19
25
 
20
26
  require 'aws-sdk'
21
27
  require 'aws/core/http/em_http_handler'
22
28
  AWS.config(
23
- :http_handler => AWS::Http::EMHttpHandler.new)
29
+ :http_handler => AWS::Http::EMHttpHandler.new(
30
+ :pool_size => 5,
31
+ :proxy => {:host => "http://myproxy.com", :port => 80}
32
+ ))
24
33
 
25
34
  Your done.
26
35
 
27
36
  All requests to AWS will use EM-Synchrony's implementation of em-http-request for non-block HTTP request and fiber management.
28
37
 
29
- ### References
38
+ ## Connection Pools
39
+ v0.1+ implement connections EventMachine::Synchrony::ConnectionPool. The default pool_size is 5 but it can be
40
+ increased by in the AWS.config options. Connection pools were problematic for S3 calls that required the :path option for
41
+ em-http-request and would return AWS::S3::SignatureDoesNotMatch errors; so for now S3 calls with paths do not make use of the connection pools.
42
+
43
+ ## Heroku Gotcha
44
+ When deploying to Heroku, if you get "NameError: uninitialized constant Syck::Syck", you need to vendorize em_aws
45
+
46
+ From your apps root directory run:
47
+
48
+ gem unpack em_aws --target vendor/gems
49
+
50
+ Update you gemfile:
51
+
52
+ gem 'em_aws', :path => "vendor/gems/em_aws-0.0.3"
53
+
54
+ Finally, run bundler and make sure you check-in your new Gemfile.lock.
55
+ I'm pretty sure the Syck error is do to an outdated version of rubygems and bundler on Heroku, but as of yet have not been able to reproduce it locally.
56
+
57
+ ## References
30
58
 
31
59
  [aws-sdk](https://github.com/amazonwebservices/aws-sdk-for-ruby)
32
60
 
@@ -45,4 +73,4 @@ All requests to AWS will use EM-Synchrony's implementation of em-http-request fo
45
73
  * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
46
74
 
47
75
  ## Thanks
48
- Code based on HTTParty Hander in [AWS-SKD](https://github.com/amazonwebservices/aws-sdk-for-ruby/blob/master/README.rdoc)
76
+ Code based on HTTParty Hander in [aws-sdk](https://github.com/amazonwebservices/aws-sdk-for-ruby/blob/master/README.rdoc)
data/em_aws.gemspec CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |s|
17
17
  s.add_runtime_dependency "aws-sdk"
18
18
  s.add_runtime_dependency "em-synchrony"
19
19
  s.add_runtime_dependency "em-http-request"
20
- s.add_development_dependency "rspec" , '2.6.0'
20
+ s.add_development_dependency "rspec"
21
21
 
22
22
  s.files = `git ls-files`.split("\n")
23
23
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -1,9 +1,9 @@
1
1
  # http://docs.amazonwebservices.com/AWSRubySDK/latest/
2
-
3
2
  require "em-synchrony"
4
3
  require "em-synchrony/em-http"
5
-
4
+ require 'em-synchrony/thread'
6
5
  module AWS
6
+
7
7
  module Core
8
8
  module Http
9
9
 
@@ -18,36 +18,46 @@ module AWS
18
18
  # require 'aws/core/http/em_http_handler'
19
19
  # AWS.config(
20
20
  # :http_handler => AWS::Http::EMHttpHandler.new(
21
+ # :pool_size => 20,
21
22
  # :proxy => {:host => "http://myproxy.com",:port => 80}
22
23
  # )
23
24
  # )
24
25
  #
25
26
  class EMHttpHandler
26
-
27
27
  # @return [Hash] The default options to send to EM-Synchrony on each
28
28
  # request.
29
29
  attr_reader :default_request_options
30
-
30
+ @@pools = {}
31
+
32
+ def self.fetch_connection(url,pool_size)
33
+ @@pools[url] ||= EventMachine::Synchrony::ConnectionPool.new(size: pool_size) do
34
+ EM::HttpRequest.new(url)
35
+ end
36
+ @@pools[url]
37
+ end
38
+
31
39
  # Constructs a new HTTP handler using EM-Synchrony.
32
40
  #
33
- # @param [Hash] options Default options to send to HTTParty on
41
+ # @param [Hash] options Default options to send to EM-Synchrony on
34
42
  # each request. These options will be sent to +get+, +post+,
35
43
  # +head+, +put+, or +delete+ when a request is made. Note
36
44
  # that +:body+, +:head+, +:parser+, and +:ssl_ca_file+ are
37
45
  # ignored. If you need to set the CA file, you should use the
38
46
  # +:ssl_ca_file+ option to {AWS.config} or
39
47
  # {AWS::Configuration} instead.
48
+ # Defaults pool_size to 5
40
49
  def initialize options = {}
41
50
  #puts "Using EM-Synchrony for AWS requests"
51
+ options[:pool_size] ||= 5
42
52
  @default_request_options = options
43
53
  end
44
54
 
45
55
  def fetch_url(request)
46
56
  url = nil
47
57
  if request.use_ssl?
48
- url = "https://#{request.host}:443#{request.uri}"
58
+ url = "https://#{request.host}:443"
49
59
  else
50
- url = "http://#{request.host}#{request.uri}"
60
+ url = "http://#{request.host}"
51
61
  end
52
62
  url
53
63
  end
@@ -88,36 +98,43 @@ module AWS
88
98
  merge(fetch_ssl(request))
89
99
  end
90
100
 
101
+ # We get AWS::S3::SignatureDoesNotMatch when path is used to fetch an s3 object
102
+ # so for now we won't use the pool for requests where the path is more than just '/'
91
103
  def fetch_response(url,method,opts={})
92
- new_response = nil
104
+ return EM::HttpRequest.new("#{url}#{opts[:path]}").send(method, opts) if (@default_request_options[:pool_size] == 0 || opts[:path].to_s.length > 1)
105
+ self.class.fetch_connection(url,@default_request_options[:pool_size]).send(method, opts)
106
+ end
107
+
108
+ # Add thread safety.
109
+ def _fibered_mutex
110
+ @fibered_mutex ||= EM::Synchrony::Thread::Mutex.new
111
+ end
112
+
113
+ def handle(request,response)
93
114
  if EM::reactor_running?
94
- #puts "Reactor is running"
95
- http = EM::HttpRequest.new(url).send(method, opts)
96
- http.callback { new_response = http}
97
- http.errback { puts "#{method} to AWS failed." }
115
+ _fibered_mutex.synchronize do
116
+ handle_it(request, response)
117
+ end
98
118
  else
99
119
  EM.synchrony do
100
- #puts "WARNING: Had to start EM"
101
- http = EM::HttpRequest.new(url).send(method, opts)
102
- http.callback { new_response = http}
103
- http.errback { puts "#{method} to AWS failed." }
120
+ _fibered_mutex.synchronize do
121
+ handle_it(request, response)
122
+ end
104
123
  EM.stop
105
- end
124
+ end
106
125
  end
107
- new_response
108
126
  end
109
-
110
- def handle(request, response)
111
- #puts "Using EM!!!!"
127
+
128
+ def handle_it(request, response)
129
+ #puts "Using EM!!!!"
112
130
  opts = default_request_options.merge({
113
- :body => request.body
131
+ :body => request.body,
132
+ :path => request.uri,
133
+
114
134
  }).merge(request_options(request))
115
-
116
135
  url = fetch_url(request)
117
-
118
136
  # get, post, put, delete, head
119
137
  method = request.http_method.downcase
120
-
121
138
  begin
122
139
  http_response = fetch_response(url,method,opts)
123
140
  rescue Timeout::Error, Errno::ETIMEDOUT => e
@@ -127,7 +144,7 @@ module AWS
127
144
  response.status = http_response.response_header.status.to_i
128
145
  response.headers = http_response.response_header.to_hash
129
146
  end
130
- end
147
+ end
131
148
  end
132
149
  end
133
150
  end
@@ -138,5 +155,4 @@ module AWS
138
155
  module Http
139
156
  class EMHttpHandler < Core::Http::EMHttpHandler; end
140
157
  end
141
-
142
158
  end
@@ -1,3 +1,3 @@
1
1
  module EmAws
2
- VERSION = "0.0.3"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -16,7 +16,7 @@ require 'spec_helper'
16
16
  module AWS::Core
17
17
  module Http
18
18
  describe EMHttpHandler do
19
-
19
+
20
20
  let(:handler) { EMHttpHandler.new(default_request_options) }
21
21
 
22
22
  let(:default_request_options) { {} }
@@ -32,7 +32,6 @@ module AWS::Core
32
32
  let(:em_http_options) do
33
33
  options = nil
34
34
  EMHttpHandler.should_receive(:fetch_response).with do |url, method,opts|
35
- puts "here"
36
35
  options = opts
37
36
  double("http response",
38
37
  :response => "<foo/>",
@@ -52,7 +51,12 @@ module AWS::Core
52
51
 
53
52
  it 'should set the default request options' do
54
53
  described_class.new(:foo => "BAR").default_request_options.
55
- should == { :foo => "BAR" }
54
+ should == { :foo => "BAR", :pool_size => 5 }
55
+ end
56
+
57
+ it 'should not override supplied pool_size' do
58
+ described_class.new(:pool_size => 20).default_request_options.
59
+ should == { :pool_size => 20 }
56
60
  end
57
61
 
58
62
  end
@@ -101,61 +105,59 @@ module AWS::Core
101
105
 
102
106
  end
103
107
 
104
-
105
- describe '#fetch_proxy' do
106
- context ':proxy_uri' do
107
-
108
- it 'passes proxy address and port from the request' do
109
- req.proxy_uri = URI.parse('https://user:pass@proxy.com:443/path?query')
110
- handler.fetch_proxy(req)[:proxy][:host].should == 'proxy.com'
111
- handler.fetch_proxy(req)[:proxy][:port].should == 443
112
- end
113
-
108
+ end
109
+ describe '#fetch_proxy' do
110
+ context ':proxy_uri' do
111
+ it 'passes proxy address and port from the request' do
112
+ req.proxy_uri = URI.parse('https://user:pass@proxy.com:443/path?query')
113
+ handler.fetch_proxy(req)[:proxy][:host].should == 'proxy.com'
114
+ handler.fetch_proxy(req)[:proxy][:port].should == 443
114
115
  end
116
+
117
+ end
115
118
 
116
- describe '#fetch_ssl' do
117
- it 'prefers the request option when set' do
118
- req.use_ssl = true
119
- req.ssl_verify_peer = true
120
- req.ssl_ca_file = "something"
121
- handler.fetch_ssl(req)[:private_key_file].should == "something"
122
- handler.fetch_ssl(req)[:cert_chain_file].should == "something"
123
- end
119
+ describe '#fetch_ssl' do
120
+ it 'prefers the request option when set' do
121
+ req.use_ssl = true
122
+ req.ssl_verify_peer = true
123
+ req.ssl_ca_file = "something"
124
+ handler.fetch_ssl(req)[:private_key_file].should == "something"
125
+ handler.fetch_ssl(req)[:cert_chain_file].should == "something"
126
+ end
124
127
 
125
- context 'CA cert path' do
126
-
127
- context 'use_ssl? is true' do
128
+ context 'CA cert path' do
128
129
 
129
- before(:each) { req.use_ssl = true }
130
+ context 'use_ssl? is true' do
130
131
 
131
- context 'ssl_verify_peer? is true' do
132
+ before(:each) { req.use_ssl = true }
132
133
 
133
- before(:each) do
134
- req.ssl_verify_peer = true
135
- req.ssl_ca_file = "foobar.txt"
136
- end
134
+ context 'ssl_verify_peer? is true' do
137
135
 
138
- it 'should use the ssl_ca_file attribute of the request' do
139
- handler.fetch_ssl(req)[:private_key_file].should == "foobar.txt"
140
- end
141
-
142
- it 'should use the ssl_ca_file attribute of the request' do
143
- handler.fetch_ssl(req)[:cert_chain_file].should == "foobar.txt"
144
- end
136
+ before(:each) do
137
+ req.ssl_verify_peer = true
138
+ req.ssl_ca_file = "foobar.txt"
145
139
  end
146
140
 
147
- it 'should not set the ssl_ca_file option without ssl_verify_peer?' do
148
- handler.fetch_ssl(req).should_not include(:private_key_file)
141
+ it 'should use the ssl_ca_file attribute of the request' do
142
+ handler.fetch_ssl(req)[:private_key_file].should == "foobar.txt"
143
+ end
144
+
145
+ it 'should use the ssl_ca_file attribute of the request' do
146
+ handler.fetch_ssl(req)[:cert_chain_file].should == "foobar.txt"
149
147
  end
150
148
  end
151
149
 
152
- it 'should not set the ssl_ca_file option without use_ssl?' do
150
+ it 'should not set the ssl_ca_file option without ssl_verify_peer?' do
153
151
  handler.fetch_ssl(req).should_not include(:private_key_file)
154
152
  end
155
153
  end
156
- end
157
- end
158
- end
154
+
155
+ it 'should not set the ssl_ca_file option without use_ssl?' do
156
+ handler.fetch_ssl(req).should_not include(:private_key_file)
157
+ end
158
+ end
159
+ end
160
+ end
159
161
  end
160
162
  end
161
163
  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.0.3
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-18 00:00:00.000000000Z
12
+ date: 2012-04-11 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: aws-sdk
16
- requirement: &70365956234980 !ruby/object:Gem::Requirement
16
+ requirement: &70247639340500 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70365956234980
24
+ version_requirements: *70247639340500
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: em-synchrony
27
- requirement: &70365956234260 !ruby/object:Gem::Requirement
27
+ requirement: &70247639339960 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70365956234260
35
+ version_requirements: *70247639339960
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: em-http-request
38
- requirement: &70365956233540 !ruby/object:Gem::Requirement
38
+ requirement: &70247639339420 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,18 +43,18 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70365956233540
46
+ version_requirements: *70247639339420
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rspec
49
- requirement: &70365956232640 !ruby/object:Gem::Requirement
49
+ requirement: &70247639338880 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
- - - =
52
+ - - ! '>='
53
53
  - !ruby/object:Gem::Version
54
- version: 2.6.0
54
+ version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70365956232640
57
+ version_requirements: *70247639338880
58
58
  description: Adds EM-Synchrony support to AWS-SDK gem
59
59
  email:
60
60
  - joshmckin@gmail.com
@@ -65,6 +65,7 @@ files:
65
65
  - .gitignore
66
66
  - .rspec
67
67
  - Gemfile
68
+ - Gemfile.lock
68
69
  - LICENSE.txt
69
70
  - README.md
70
71
  - Rakefile