net-http-pool 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.
- data/Gemfile +4 -0
- data/README.md +24 -0
- data/Rakefile +12 -0
- data/SPEC.md +3 -0
- data/lib/net/http/pool.rb +84 -0
- data/net-http-pool.gemspec +17 -0
- data/test/connections.rb +9 -0
- data/test/pool.rb +68 -0
- metadata +110 -0
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# Net::HTTP::Pool
|
2
|
+
|
3
|
+

|
4
|
+
|
5
|
+
Act like a database pool but for HTTP.
|
6
|
+
|
7
|
+
It will attenmpt to open (default: 5) persistent connections to a given server.
|
8
|
+
Then you can make your requests as you want and the pool get recycled.
|
9
|
+
The implementation it's made throght actors (celluloid) so the behaviour in the
|
10
|
+
verb block it's async.
|
11
|
+
|
12
|
+
The target of the lib it's to provide DB-like pool to handle information
|
13
|
+
exchange.
|
14
|
+
|
15
|
+
## Example
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
require 'net/http/pool'
|
19
|
+
|
20
|
+
pool = Net::HTTP::Pool.new("http://elcuervo.co")
|
21
|
+
pool.get("/humans.txt") do |response|
|
22
|
+
File.open('nevermore.txt', 'w') { |f| f << response.body } if response.code == "200"
|
23
|
+
end
|
24
|
+
```
|
data/Rakefile
ADDED
data/SPEC.md
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'celluloid'
|
2
|
+
require 'net/http/persistent'
|
3
|
+
|
4
|
+
# Public: The Pool itself
|
5
|
+
#
|
6
|
+
# host - The string of the host.
|
7
|
+
class Net::HTTP::Pool
|
8
|
+
include Celluloid
|
9
|
+
|
10
|
+
# Private: Custom Error for a missing block in the call.
|
11
|
+
class MissingBlock < StandardError
|
12
|
+
def message
|
13
|
+
"You must pass a block"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Public: The Connection Pool.
|
18
|
+
#
|
19
|
+
# host - The string of the host.
|
20
|
+
# options - The hash of options (default: {}).
|
21
|
+
# :size - The integer size of the pool (default: 5)
|
22
|
+
class Connections
|
23
|
+
include Celluloid
|
24
|
+
|
25
|
+
attr_reader :pool
|
26
|
+
|
27
|
+
def initialize(host, options = {})
|
28
|
+
@current_index = 0
|
29
|
+
@pool = Array.new(options.fetch(:size, 5)) do
|
30
|
+
connection = Net::HTTP::Persistent.new(host)
|
31
|
+
connection.idle_timeout = nil
|
32
|
+
connection
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Private: Round robin one of the connections
|
37
|
+
#
|
38
|
+
# &block - The block to be called passing the current connection
|
39
|
+
def round_robin(&block)
|
40
|
+
raise MissingBlock unless block
|
41
|
+
@current_index = @current_index > @pool.size ? 0 : @current_index + 1
|
42
|
+
yield @pool[@current_index] if block
|
43
|
+
end
|
44
|
+
|
45
|
+
# Public: Helper to access the connection asynchronous
|
46
|
+
#
|
47
|
+
# &block - The block to be called passing the current connection
|
48
|
+
def with(&block)
|
49
|
+
round_robin! &block
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def initialize(host, options = {})
|
54
|
+
@pool = Connections.new(host, options)
|
55
|
+
@uri = URI(host)
|
56
|
+
end
|
57
|
+
|
58
|
+
def get(path, headers = {}, &block)
|
59
|
+
request!(path, Net::HTTP::Get, nil, headers, &block)
|
60
|
+
end
|
61
|
+
|
62
|
+
def post(path, body = nil, headers = {}, &block)
|
63
|
+
request!(path, Net::HTTP::Post, body, headers, &block)
|
64
|
+
end
|
65
|
+
|
66
|
+
def put(path, body = nil, headers = {}, &block)
|
67
|
+
request!(path, Net::HTTP::Put, body, headers, &block)
|
68
|
+
end
|
69
|
+
|
70
|
+
def delete(path, headers = {}, &block)
|
71
|
+
request!(path, Net::HTTP::Delete, headers, &block)
|
72
|
+
end
|
73
|
+
|
74
|
+
def request(path, type, body = nil, headers = {}, &block)
|
75
|
+
raise MissingBlock unless block
|
76
|
+
@pool.with do |connection|
|
77
|
+
request = type.new(path)
|
78
|
+
request.body = body if body
|
79
|
+
headers.each { |key, value| request.add_field(key, value) }
|
80
|
+
request['Content-Length'] = body && body.length || 0
|
81
|
+
yield connection.request(@uri, request) if block
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "net-http-pool"
|
3
|
+
s.version = "0.0.2"
|
4
|
+
s.summary = "Persistent pool of HTTP connections"
|
5
|
+
s.authors = ["elcuervo"]
|
6
|
+
s.email = ["yo@brunoaguirre.com"]
|
7
|
+
s.homepage = "http://github.com/elcuervo/net-http-pool"
|
8
|
+
s.files = `git ls-files`.split("\n")
|
9
|
+
s.test_files = `git ls-files test`.split("\n")
|
10
|
+
|
11
|
+
s.add_dependency("net-http-persistent", ">= 2.6")
|
12
|
+
s.add_dependency("celluloid", "~> 0.9.0")
|
13
|
+
|
14
|
+
s.add_development_dependency("cutest", "~> 1.1.3")
|
15
|
+
s.add_development_dependency("capybara", "~> 1.1.2")
|
16
|
+
s.add_development_dependency("mock-server", "~> 0.1.2")
|
17
|
+
end
|
data/test/connections.rb
ADDED
data/test/pool.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'cutest'
|
2
|
+
require 'mock_server'
|
3
|
+
require_relative '../lib/net/http/pool'
|
4
|
+
|
5
|
+
extend MockServer::Methods
|
6
|
+
|
7
|
+
mock_server {
|
8
|
+
get '/' do
|
9
|
+
'What is up dog!'
|
10
|
+
end
|
11
|
+
|
12
|
+
get '/marco' do
|
13
|
+
'polo'
|
14
|
+
end
|
15
|
+
|
16
|
+
post '/post' do
|
17
|
+
params[:test] ? 'this is a test' : 'the post'
|
18
|
+
end
|
19
|
+
|
20
|
+
put '/put' do
|
21
|
+
params[:run] || 'the put'
|
22
|
+
end
|
23
|
+
|
24
|
+
get '/wait' do
|
25
|
+
sleep 5
|
26
|
+
"Finally!"
|
27
|
+
end
|
28
|
+
|
29
|
+
delete('/delete') {}
|
30
|
+
}
|
31
|
+
|
32
|
+
scope do
|
33
|
+
setup do
|
34
|
+
@pool = Net::HTTP::Pool.new("http://localhost:4000/")
|
35
|
+
end
|
36
|
+
|
37
|
+
test "check that the HTTP verbs do work" do
|
38
|
+
@pool.get("/") do |res|
|
39
|
+
assert_equal "200", res.code
|
40
|
+
assert_equal 'What is up dog!', res.body
|
41
|
+
end
|
42
|
+
|
43
|
+
@pool.get("/marco") do |res|
|
44
|
+
assert_equal "200", res.code
|
45
|
+
assert_equal 'polo', res.body
|
46
|
+
end
|
47
|
+
|
48
|
+
@pool.post("/post", 'test=yes', {'X-Fancy-Header' => 'Sometimes'}) do |res|
|
49
|
+
assert_equal "200", res.code
|
50
|
+
assert_equal 'this is a test', res.body
|
51
|
+
end
|
52
|
+
|
53
|
+
@pool.put("/put", 'run=fast') do |res|
|
54
|
+
assert_equal "200", res.code
|
55
|
+
assert_equal 'fast', res.body
|
56
|
+
end
|
57
|
+
|
58
|
+
@pool.delete("/delete") do |res|
|
59
|
+
assert_equal "200", res.code
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
test "do not block main thread when resource is slow" do
|
64
|
+
start = Time.now
|
65
|
+
5.times { @pool.get("/wait") {} }
|
66
|
+
assert Time.now - start < 20
|
67
|
+
end
|
68
|
+
end
|
metadata
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: net-http-pool
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- elcuervo
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-04-12 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: net-http-persistent
|
16
|
+
requirement: &70302928111800 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '2.6'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70302928111800
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: celluloid
|
27
|
+
requirement: &70302928111020 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.9.0
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70302928111020
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: cutest
|
38
|
+
requirement: &70302928110440 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.1.3
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70302928110440
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: capybara
|
49
|
+
requirement: &70302928109860 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.1.2
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70302928109860
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: mock-server
|
60
|
+
requirement: &70302928109300 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ~>
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 0.1.2
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70302928109300
|
69
|
+
description:
|
70
|
+
email:
|
71
|
+
- yo@brunoaguirre.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- Gemfile
|
77
|
+
- README.md
|
78
|
+
- Rakefile
|
79
|
+
- SPEC.md
|
80
|
+
- lib/net/http/pool.rb
|
81
|
+
- net-http-pool.gemspec
|
82
|
+
- test/connections.rb
|
83
|
+
- test/pool.rb
|
84
|
+
homepage: http://github.com/elcuervo/net-http-pool
|
85
|
+
licenses: []
|
86
|
+
post_install_message:
|
87
|
+
rdoc_options: []
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ! '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
requirements: []
|
103
|
+
rubyforge_project:
|
104
|
+
rubygems_version: 1.8.15
|
105
|
+
signing_key:
|
106
|
+
specification_version: 3
|
107
|
+
summary: Persistent pool of HTTP connections
|
108
|
+
test_files:
|
109
|
+
- test/connections.rb
|
110
|
+
- test/pool.rb
|