hot_tub 0.5.3 → 1.0.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.
- checksums.yaml +4 -4
- data/.travis.yml +3 -3
- data/HISTORY.md +8 -1
- data/README.md +44 -52
- data/benchmarks/block_passing.rb +55 -51
- data/benchmarks/compare_concurrent.rb +99 -0
- data/benchmarks/compare_serial.rb +60 -0
- data/benchmarks/hot_tub.rb +95 -83
- data/lib/hot_tub.rb +7 -1
- data/lib/hot_tub/pool.rb +12 -7
- data/lib/hot_tub/reaper.rb +30 -9
- data/lib/hot_tub/sessions.rb +106 -36
- data/lib/hot_tub/version.rb +1 -1
- data/spec/helpers/moc_pool.rb +26 -6
- data/spec/hot_tub/integration/excon_spec.rb +4 -33
- data/spec/hot_tub/integration/net_http_spec.rb +3 -3
- data/spec/hot_tub/pool_spec.rb +2 -4
- data/spec/hot_tub/reaper_spec.rb +8 -14
- data/spec/hot_tub/sessions_spec.rb +46 -16
- data/spec/hot_tub_spec.rb +1 -1
- data/spec/spec_helper.rb +5 -0
- metadata +22 -20
data/lib/hot_tub/version.rb
CHANGED
data/spec/helpers/moc_pool.rb
CHANGED
@@ -6,19 +6,39 @@ class MocPool < MocMixinPool
|
|
6
6
|
attr_accessor :reaped, :lets_reap
|
7
7
|
|
8
8
|
def initialize
|
9
|
-
|
10
|
-
|
9
|
+
@reaped = false
|
10
|
+
@lets_reap = false
|
11
11
|
end
|
12
12
|
|
13
13
|
def reap!
|
14
|
-
|
14
|
+
@reaped = true if @lets_reap
|
15
|
+
@lets_reap = false
|
15
16
|
end
|
16
17
|
end
|
17
18
|
|
18
19
|
class MocReaperPool < MocPool
|
20
|
+
attr_accessor :mx, :cv, :reaped
|
19
21
|
def initialize
|
20
|
-
|
21
|
-
@reap_timeout =
|
22
|
+
super
|
23
|
+
@reap_timeout = 0.01
|
24
|
+
|
25
|
+
@mx = Mutex.new
|
26
|
+
@cv = ConditionVariable.new
|
27
|
+
@reaped = false
|
28
|
+
|
22
29
|
@reaper = HotTub::Reaper.spawn(self)
|
23
30
|
end
|
24
|
-
|
31
|
+
|
32
|
+
def wait_for_reap
|
33
|
+
@mx.synchronize do
|
34
|
+
@cv.wait(@mx)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def reap!
|
39
|
+
@mx.synchronize do
|
40
|
+
@reaped = true
|
41
|
+
@cv.signal
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -1,10 +1,9 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
|
3
2
|
describe HotTub do
|
4
3
|
|
5
4
|
context "blocking (size equals max_size)" do
|
6
5
|
let(:pool) do
|
7
|
-
HotTub.new(:size => 4, :max_size => 4) {
|
6
|
+
HotTub::Pool.new(:size => 4, :max_size => 4) {
|
8
7
|
Excon.new(HotTub::Server.url, :thread_safe_sockets => false)
|
9
8
|
}
|
10
9
|
end
|
@@ -33,7 +32,7 @@ describe HotTub do
|
|
33
32
|
|
34
33
|
context "with larger max" do
|
35
34
|
let(:pool) do
|
36
|
-
HotTub.new(:size => 4, :max_size => 8) {
|
35
|
+
HotTub::Pool.new(:size => 4, :max_size => 8) {
|
37
36
|
Excon.new(HotTub::Server.url, :thread_safe_sockets => false)
|
38
37
|
}
|
39
38
|
end
|
@@ -52,7 +51,7 @@ describe HotTub do
|
|
52
51
|
|
53
52
|
it "should reap" do
|
54
53
|
pool.reap!
|
55
|
-
expect(pool.current_size).to be <= 4
|
54
|
+
expect(pool.current_size).to be <= 4
|
56
55
|
end
|
57
56
|
|
58
57
|
it "should work" do
|
@@ -64,7 +63,7 @@ describe HotTub do
|
|
64
63
|
|
65
64
|
context "sized without max" do
|
66
65
|
let(:pool) do
|
67
|
-
HotTub.new(:size => 4) {
|
66
|
+
HotTub::Pool.new(:size => 4) {
|
68
67
|
Excon.new(HotTub::Server.url, :thread_safe_sockets => false)
|
69
68
|
}
|
70
69
|
end
|
@@ -90,34 +89,6 @@ describe HotTub do
|
|
90
89
|
expect(results.uniq).to eql([200])
|
91
90
|
end
|
92
91
|
end
|
93
|
-
|
94
|
-
context "shutdown with slow client" do
|
95
|
-
let(:pool) do
|
96
|
-
HotTub.new(:size => 1) {
|
97
|
-
Excon.new(HotTub::Server.slow_url, :thread_safe_sockets => false, :read_timeout => 2)
|
98
|
-
}
|
99
|
-
end
|
100
|
-
|
101
|
-
it "should work" do
|
102
|
-
begin
|
103
|
-
th = Thread.new do
|
104
|
-
uri = URI.parse(HotTub::Server.slow_url)
|
105
|
-
pool.run do |connection|
|
106
|
-
connection.get(:path => uri.path).status
|
107
|
-
end
|
108
|
-
end
|
109
|
-
sleep(0.01)
|
110
|
-
pool.shutdown!
|
111
|
-
th.join
|
112
|
-
rescue => e
|
113
|
-
puts e.message
|
114
|
-
end
|
115
|
-
|
116
|
-
expect(pool.shutdown).to eql(true)
|
117
|
-
expect(pool.current_size).to eql(0)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
92
|
end
|
122
93
|
|
123
94
|
def excon_thread_work(pool,thread_count=0, threads=[])
|
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
describe HotTub do
|
4
4
|
context "blocking (size equals max_size)" do
|
5
5
|
let(:pool) do
|
6
|
-
HotTub.new(:size => 4, :max_size => 4) {
|
6
|
+
HotTub::Pool.new(:size => 4, :max_size => 4) {
|
7
7
|
uri = URI.parse(HotTub::Server.url)
|
8
8
|
http = Net::HTTP.new(uri.host, uri.port)
|
9
9
|
http.use_ssl = false
|
@@ -36,7 +36,7 @@ describe HotTub do
|
|
36
36
|
|
37
37
|
context "with larger max" do
|
38
38
|
let(:pool) do
|
39
|
-
HotTub.new(:size => 4, :max_size => 8) {
|
39
|
+
HotTub::Pool.new(:size => 4, :max_size => 8) {
|
40
40
|
uri = URI.parse(HotTub::Server.url)
|
41
41
|
http = Net::HTTP.new(uri.host, uri.port)
|
42
42
|
http.use_ssl = false
|
@@ -64,7 +64,7 @@ describe HotTub do
|
|
64
64
|
|
65
65
|
context "sized without max" do
|
66
66
|
let(:pool) do
|
67
|
-
HotTub.new(:size => 4) {
|
67
|
+
HotTub::Pool.new(:size => 4) {
|
68
68
|
uri = URI.parse(HotTub::Server.url)
|
69
69
|
http = Net::HTTP.new(uri.host, uri.port)
|
70
70
|
http.use_ssl = false
|
data/spec/hot_tub/pool_spec.rb
CHANGED
@@ -21,7 +21,7 @@ describe HotTub::Pool do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
it "should have a HotTub::Reaper" do
|
24
|
-
expect(pool.reaper).to be_a(
|
24
|
+
expect(pool.reaper).to be_a(HotTub::Reaper)
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
@@ -210,14 +210,12 @@ describe HotTub::Pool do
|
|
210
210
|
context 'thread safety' do
|
211
211
|
it "should grow" do
|
212
212
|
pool = HotTub::Pool.new({:size => 4}) { MocClient.new }
|
213
|
-
failed = false
|
214
213
|
threads = []
|
215
214
|
20.times.each do
|
216
215
|
threads << Thread.new do
|
217
|
-
pool.run{|connection| connection.get }
|
216
|
+
pool.run { |connection| connection.get }
|
218
217
|
end
|
219
218
|
end
|
220
|
-
sleep(0.01)
|
221
219
|
threads.each do |t|
|
222
220
|
t.join
|
223
221
|
end
|
data/spec/hot_tub/reaper_spec.rb
CHANGED
@@ -1,27 +1,21 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe HotTub::Reaper do
|
4
|
-
|
5
|
-
let(:pool)
|
6
|
-
let(:reaper)
|
4
|
+
|
5
|
+
let(:pool) { MocReaperPool.new }
|
6
|
+
let(:reaper) { pool.reaper }
|
7
7
|
|
8
8
|
it "should be a HotTub::Reaper Thread" do
|
9
|
-
expect(reaper).to be_a(Thread)
|
9
|
+
expect(reaper.thread).to be_a(Thread)
|
10
10
|
end
|
11
11
|
|
12
12
|
it "should reap!" do
|
13
|
-
|
14
|
-
pool.lets_reap = true
|
15
|
-
reaper.wakeup
|
16
|
-
sleep(0.01)
|
13
|
+
pool.wait_for_reap
|
17
14
|
expect(pool.reaped).to eql(true)
|
18
15
|
end
|
19
16
|
|
20
|
-
it "should
|
21
|
-
|
22
|
-
|
23
|
-
reaper.wakeup
|
24
|
-
sleep(0.01)
|
25
|
-
expect(reaper.status).to eql('sleep')
|
17
|
+
it "should still be alive" do
|
18
|
+
pool.wait_for_reap
|
19
|
+
expect(reaper).to be_alive
|
26
20
|
end
|
27
21
|
end
|
@@ -2,23 +2,53 @@ require 'spec_helper'
|
|
2
2
|
require 'hot_tub/sessions'
|
3
3
|
require 'uri'
|
4
4
|
require 'time'
|
5
|
-
describe HotTub::Sessions do
|
6
|
-
|
7
5
|
|
8
|
-
|
6
|
+
describe HotTub::Sessions do
|
9
7
|
|
8
|
+
describe '#stage' do
|
10
9
|
let(:key) { "https://www.somewebsite.com" }
|
11
10
|
|
12
11
|
let(:sessions) { HotTub::Sessions.new }
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
13
|
+
it { expect(sessions.stage(key) { MocClient.new }).to be_nil }
|
14
|
+
|
15
|
+
it "should lazy load pool" do
|
16
|
+
sessions.stage(key) { MocClient.new }
|
17
|
+
expect(sessions.fetch(key)).to be_a(HotTub::Pool)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
describe '#get_or_set' do
|
23
|
+
|
24
|
+
context "with &default_client" do
|
25
|
+
let(:key) { "https://www.somewebsite.com" }
|
26
|
+
|
27
|
+
let(:sessions) do
|
28
|
+
sns = HotTub::Sessions.new #{ MocClient.new }
|
29
|
+
sns.default_client = lambda { |url| MocClient.new(url) }
|
30
|
+
sns
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should add a new pool for the key" do
|
34
|
+
pool = sessions.get_or_set(key)
|
35
|
+
expect(pool).to be_a(HotTub::Pool)
|
36
|
+
pool.run do |clnt|
|
37
|
+
expect(clnt).to be_a(MocClient)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "with &client_block" do
|
43
|
+
let(:key) { "https://www.somewebsite.com" }
|
44
|
+
|
45
|
+
let(:sessions) { HotTub::Sessions.new }
|
46
|
+
|
47
|
+
it "should add a new client for the key" do
|
48
|
+
pool = sessions.get_or_set(key) { MocClient.new }
|
49
|
+
expect(pool).to be_a(HotTub::Pool)
|
50
|
+
pool.run do |clnt|
|
51
|
+
expect(clnt).to be_a(MocClient)
|
22
52
|
end
|
23
53
|
end
|
24
54
|
end
|
@@ -31,14 +61,14 @@ describe HotTub::Sessions do
|
|
31
61
|
|
32
62
|
it "should start reaper after add" do
|
33
63
|
expect(sessions.reaper).to be_nil
|
34
|
-
sessions.get_or_set("https://www.somewebsite.com") { MocClient.new }
|
35
|
-
expect(sessions.reaper).to be_a(
|
64
|
+
sessions.get_or_set("https://www.somewebsite.com") { MocClient.new }
|
65
|
+
expect(sessions.reaper).to be_a(HotTub::Reaper)
|
36
66
|
end
|
37
67
|
|
38
68
|
it "should disable pool based reaper" do
|
39
|
-
sessions.get_or_set("https://www.somewebsite.com") { MocClient.new }
|
40
|
-
sessions.get_or_set("https://www.someOtherwebsite.com") { MocClient.new }
|
41
|
-
sessions.get_or_set("https://www.someOtherwebsiteToo.com") { MocClient.new }
|
69
|
+
sessions.get_or_set("https://www.somewebsite.com") { MocClient.new }
|
70
|
+
sessions.get_or_set("https://www.someOtherwebsite.com") { MocClient.new }
|
71
|
+
sessions.get_or_set("https://www.someOtherwebsiteToo.com") { MocClient.new }
|
42
72
|
session = sessions.instance_variable_get(:@_sessions)
|
43
73
|
session.each_value {|v| expect(v.reaper).to eql(false)}
|
44
74
|
end
|
data/spec/hot_tub_spec.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,95 +1,95 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hot_tub
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joshua Mckinney
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-12-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
15
16
|
requirements:
|
16
17
|
- - ">="
|
17
18
|
- !ruby/object:Gem::Version
|
18
19
|
version: '0'
|
19
|
-
name: rspec
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
|
-
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
|
28
|
+
name: rspec-autotest
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
29
30
|
requirements:
|
30
31
|
- - ">="
|
31
32
|
- !ruby/object:Gem::Version
|
32
33
|
version: '0'
|
33
|
-
name: rspec-autotest
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
|
-
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
|
42
|
+
name: autotest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
43
44
|
requirements:
|
44
45
|
- - ">="
|
45
46
|
- !ruby/object:Gem::Version
|
46
47
|
version: '0'
|
47
|
-
name: autotest
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
|
-
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
|
56
|
+
name: sinatra
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
57
58
|
requirements:
|
58
59
|
- - ">="
|
59
60
|
- !ruby/object:Gem::Version
|
60
61
|
version: '0'
|
61
|
-
name: sinatra
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
|
-
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
|
70
|
+
name: puma
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
71
72
|
requirements:
|
72
73
|
- - "~>"
|
73
74
|
- !ruby/object:Gem::Version
|
74
75
|
version: '2.0'
|
75
|
-
name: puma
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
|
-
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '2.0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
|
84
|
+
name: excon
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
85
86
|
requirements:
|
86
87
|
- - ">="
|
87
88
|
- !ruby/object:Gem::Version
|
88
89
|
version: '0'
|
89
|
-
name: excon
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
|
-
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
@@ -110,6 +110,8 @@ files:
|
|
110
110
|
- README.md
|
111
111
|
- Rakefile
|
112
112
|
- benchmarks/block_passing.rb
|
113
|
+
- benchmarks/compare_concurrent.rb
|
114
|
+
- benchmarks/compare_serial.rb
|
113
115
|
- benchmarks/hot_tub.rb
|
114
116
|
- hot_tub.gemspec
|
115
117
|
- lib/hot_tub.rb
|