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/benchmarks/hot_tub.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
-
require 'benchmark'
|
2
|
+
require 'benchmark/ips'
|
3
3
|
require 'hot_tub'
|
4
4
|
|
5
5
|
class MocClient
|
@@ -18,26 +18,37 @@ end
|
|
18
18
|
|
19
19
|
puts `ruby -v`
|
20
20
|
|
21
|
-
|
21
|
+
s1 = HotTub::Pool.new(:size => 1, :max_size => 1, :clean => lambda {|clnt| clnt.clean}) { MocClient.new }
|
22
|
+
s5 = HotTub::Pool.new(:size => 5, :max_size => 5, :clean => lambda {|clnt| clnt.clean}) { MocClient.new }
|
23
|
+
s10 = HotTub::Pool.new(:size => 5, :max_size => 10, :clean => lambda {|clnt| clnt.clean}) { MocClient.new }
|
24
|
+
s0 = HotTub::Pool.new(:size => 5, :clean => lambda {|clnt| clnt.clean}) { MocClient.new }
|
22
25
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
26
|
+
url = 'http://foo.com'
|
27
|
+
HotTub.add(url, {:size => 5, :clean => lambda {|clnt| clnt.clean}}) { MocClient.new }
|
28
|
+
|
29
|
+
Benchmark.ips do |b|
|
30
|
+
|
31
|
+
b.report("blocking") do
|
32
|
+
threads = []
|
33
|
+
20.times do
|
34
|
+
threads << Thread.new do
|
35
|
+
s1.run do |conn|
|
36
|
+
conn.get
|
37
|
+
end
|
28
38
|
end
|
29
39
|
end
|
40
|
+
threads.each do |t|
|
41
|
+
t.join
|
42
|
+
end
|
30
43
|
end
|
31
44
|
|
32
|
-
b.report("
|
33
|
-
hot_tub = HotTub.new(:size => 5, :max_size => 5, :clean => lambda {|clnt| clnt.clean}) { MocClient.new }
|
45
|
+
b.report("max 5") do
|
34
46
|
threads = []
|
35
|
-
|
47
|
+
20.times do
|
36
48
|
threads << Thread.new do
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
49
|
+
|
50
|
+
s5.run do |conn|
|
51
|
+
conn.get
|
41
52
|
end
|
42
53
|
end
|
43
54
|
end
|
@@ -46,15 +57,12 @@ Benchmark.bmbm do |b|
|
|
46
57
|
end
|
47
58
|
end
|
48
59
|
|
49
|
-
b.report("
|
50
|
-
hot_tub = HotTub.new(:size => 5, :max_size => 10, :clean => lambda {|clnt| clnt.clean}) { MocClient.new }
|
60
|
+
b.report("max 10") do
|
51
61
|
threads = []
|
52
|
-
|
62
|
+
20.times do
|
53
63
|
threads << Thread.new do
|
54
|
-
|
55
|
-
|
56
|
-
conn.get
|
57
|
-
end
|
64
|
+
s10.run do |conn|
|
65
|
+
conn.get
|
58
66
|
end
|
59
67
|
end
|
60
68
|
end
|
@@ -63,15 +71,12 @@ Benchmark.bmbm do |b|
|
|
63
71
|
end
|
64
72
|
end
|
65
73
|
|
66
|
-
b.report("
|
67
|
-
hot_tub = HotTub.new(:size => 5, :clean => lambda {|clnt| clnt.clean}) { MocClient.new }
|
74
|
+
b.report("no max") do
|
68
75
|
threads = []
|
69
|
-
|
76
|
+
20.times do
|
70
77
|
threads << Thread.new do
|
71
|
-
|
72
|
-
|
73
|
-
conn.get
|
74
|
-
end
|
78
|
+
s0.run do |conn|
|
79
|
+
conn.get
|
75
80
|
end
|
76
81
|
end
|
77
82
|
end
|
@@ -80,21 +85,12 @@ Benchmark.bmbm do |b|
|
|
80
85
|
end
|
81
86
|
end
|
82
87
|
|
83
|
-
|
84
|
-
b.report("threaded, HotTub.run ") do
|
85
|
-
urls = ['http://foo.com','http://bar.com','http://zap.com']
|
86
|
-
urls.each do |url|
|
87
|
-
HotTub.add(url, {:clean => lambda {|clnt| clnt.clean}}) { MocClient.new }
|
88
|
-
end
|
88
|
+
b.report("HotTub.run") do
|
89
89
|
threads = []
|
90
|
-
|
90
|
+
20.times do
|
91
91
|
threads << Thread.new do
|
92
|
-
|
93
|
-
|
94
|
-
HotTub.run(url) do |conn|
|
95
|
-
conn.get
|
96
|
-
end
|
97
|
-
end
|
92
|
+
HotTub.run(url) do |conn|
|
93
|
+
conn.get
|
98
94
|
end
|
99
95
|
end
|
100
96
|
end
|
@@ -103,54 +99,70 @@ Benchmark.bmbm do |b|
|
|
103
99
|
end
|
104
100
|
end
|
105
101
|
|
102
|
+
b.compare!
|
106
103
|
end
|
107
104
|
|
108
105
|
# ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-darwin14]
|
109
|
-
#
|
110
|
-
#
|
111
|
-
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
#
|
115
|
-
#
|
116
|
-
|
117
|
-
#
|
118
|
-
#
|
119
|
-
#
|
120
|
-
#
|
121
|
-
|
122
|
-
#
|
106
|
+
# Calculating -------------------------------------
|
107
|
+
# blocking 1.000 i/100ms
|
108
|
+
# max 5 2.000 i/100ms
|
109
|
+
# max 10 4.000 i/100ms
|
110
|
+
# no max 8.000 i/100ms
|
111
|
+
# HotTub.run 8.000 i/100ms
|
112
|
+
# -------------------------------------------------
|
113
|
+
# blocking 4.605 (± 0.0%) i/s - 24.000
|
114
|
+
# max 5 22.610 (± 0.0%) i/s - 114.000
|
115
|
+
# max 10 43.922 (± 0.0%) i/s - 220.000
|
116
|
+
# no max 83.448 (± 1.2%) i/s - 424.000
|
117
|
+
# HotTub.run 82.757 (± 2.4%) i/s - 416.000
|
118
|
+
|
119
|
+
# Comparison:
|
120
|
+
# no max: 83.4 i/s
|
121
|
+
# HotTub.run: 82.8 i/s - 1.01x slower
|
122
|
+
# max 10: 43.9 i/s - 1.90x slower
|
123
|
+
# max 5: 22.6 i/s - 3.69x slower
|
124
|
+
# blocking: 4.6 i/s - 18.12x slower
|
123
125
|
|
124
126
|
|
125
127
|
# rubinius 2.5.8 (2.1.0 bef51ae3 2015-07-14 3.5.1 JI) [x86_64-darwin14.4.0]
|
126
|
-
#
|
127
|
-
#
|
128
|
-
#
|
129
|
-
#
|
130
|
-
#
|
131
|
-
#
|
132
|
-
#
|
133
|
-
|
134
|
-
#
|
135
|
-
#
|
136
|
-
#
|
137
|
-
#
|
138
|
-
|
139
|
-
#
|
128
|
+
# Calculating -------------------------------------
|
129
|
+
# blocking 1.000 i/100ms
|
130
|
+
# max 5 2.000 i/100ms
|
131
|
+
# max 10 4.000 i/100ms
|
132
|
+
# no max 8.000 i/100ms
|
133
|
+
# HotTub.run 8.000 i/100ms
|
134
|
+
# -------------------------------------------------
|
135
|
+
# blocking 4.619 (± 0.0%) i/s - 24.000
|
136
|
+
# max 5 22.758 (± 0.0%) i/s - 114.000
|
137
|
+
# max 10 44.336 (± 2.3%) i/s - 224.000
|
138
|
+
# no max 85.267 (± 3.5%) i/s - 432.000
|
139
|
+
# HotTub.run 85.012 (± 3.5%) i/s - 424.000
|
140
|
+
|
141
|
+
# Comparison:
|
142
|
+
# no max: 85.3 i/s
|
143
|
+
# HotTub.run: 85.0 i/s - 1.00x slower
|
144
|
+
# max 10: 44.3 i/s - 1.92x slower
|
145
|
+
# max 5: 22.8 i/s - 3.75x slower
|
146
|
+
# blocking: 4.6 i/s - 18.46x slower
|
140
147
|
|
141
148
|
|
142
149
|
# jruby 9.0.3.0 (2.2.2) 2015-10-21 633c9aa Java HotSpot(TM) 64-Bit Server VM 23.5-b02 on 1.7.0_09-b05 +jit [darwin-x86_64]
|
143
|
-
#
|
144
|
-
#
|
145
|
-
#
|
146
|
-
#
|
147
|
-
#
|
148
|
-
#
|
149
|
-
#
|
150
|
-
|
151
|
-
#
|
152
|
-
#
|
153
|
-
#
|
154
|
-
#
|
155
|
-
|
156
|
-
#
|
150
|
+
# Calculating -------------------------------------
|
151
|
+
# blocking 1.000 i/100ms
|
152
|
+
# max 5 2.000 i/100ms
|
153
|
+
# max 10 4.000 i/100ms
|
154
|
+
# no max 6.000 i/100ms
|
155
|
+
# HotTub.run 7.000 i/100ms
|
156
|
+
# -------------------------------------------------
|
157
|
+
# blocking 4.580 (± 0.0%) i/s - 23.000
|
158
|
+
# max 5 22.514 (± 4.4%) i/s - 114.000
|
159
|
+
# max 10 43.620 (± 2.3%) i/s - 220.000
|
160
|
+
# no max 72.260 (± 6.9%) i/s - 360.000
|
161
|
+
# HotTub.run 66.509 (±10.5%) i/s - 329.000
|
162
|
+
|
163
|
+
# Comparison:
|
164
|
+
# no max: 72.3 i/s
|
165
|
+
# HotTub.run: 66.5 i/s - 1.09x slower
|
166
|
+
# max 10: 43.6 i/s - 1.66x slower
|
167
|
+
# max 5: 22.5 i/s - 3.21x slower
|
168
|
+
# blocking: 4.6 i/s - 15.78x slower
|
data/lib/hot_tub.rb
CHANGED
@@ -64,16 +64,22 @@ module HotTub
|
|
64
64
|
GLOBAL_SESSIONS.get_or_set(url, opts, &client_block)
|
65
65
|
end
|
66
66
|
|
67
|
+
# Sets a options for new pool for lazy loading
|
68
|
+
def self.stage(url,opts={}, &client_block)
|
69
|
+
GLOBAL_SESSIONS.stage(url, opts, &client_block)
|
70
|
+
end
|
71
|
+
|
67
72
|
def self.add(url,opts={}, &client_block)
|
68
73
|
self.get_or_set(url,opts, &client_block)
|
69
74
|
end
|
70
75
|
|
71
76
|
def self.run(url ,&run_block)
|
72
77
|
pool = GLOBAL_SESSIONS.fetch(url)
|
73
|
-
pool.run
|
78
|
+
pool.run(&run_block)
|
74
79
|
end
|
75
80
|
|
76
81
|
def self.new(opts={}, &client_block)
|
82
|
+
warn "[DEPRECATION] `HotTub.new` is deprecated. Please use `HotTub::Pool.new` instead."
|
77
83
|
Pool.new(opts,&client_block)
|
78
84
|
end
|
79
85
|
end
|
data/lib/hot_tub/pool.rb
CHANGED
@@ -11,7 +11,6 @@ module HotTub
|
|
11
11
|
# pool = HotTub::Pool.new(:size => 10) {
|
12
12
|
# uri = URI.parse("http://somewebservice.com")
|
13
13
|
# http = Net::HTTP.new(uri.host, uri.port)
|
14
|
-
# http.use_ssl = false
|
15
14
|
# http.start
|
16
15
|
# http
|
17
16
|
# }
|
@@ -44,7 +43,7 @@ module HotTub
|
|
44
43
|
# begin
|
45
44
|
# pool.run { |clnt| s clnt.head('/').code }
|
46
45
|
# rescue HotTub::Pool::Timeout => e
|
47
|
-
# puts "Waited too long for a client: {e}"
|
46
|
+
# puts "Waited too long for a client: #{e}"
|
48
47
|
# end
|
49
48
|
#
|
50
49
|
#
|
@@ -110,12 +109,14 @@ module HotTub
|
|
110
109
|
@cond = ConditionVariable.new
|
111
110
|
|
112
111
|
@shutdown = false
|
113
|
-
|
114
|
-
@
|
112
|
+
|
113
|
+
@sessions_key = opts[:sessions_key]
|
114
|
+
@blocking_reap = (opts[:reaper] == false && !@sessions_key)
|
115
|
+
@reaper = ((@sessions_key || (opts[:reaper] == false)) ? false : spawn_reaper)
|
115
116
|
|
116
117
|
@never_block = (@max_size == 0)
|
117
118
|
|
118
|
-
at_exit {shutdown!} unless
|
119
|
+
at_exit {shutdown!} unless @sessions_key
|
119
120
|
end
|
120
121
|
|
121
122
|
# Preform an operations with a client/connection.
|
@@ -297,9 +298,13 @@ module HotTub
|
|
297
298
|
# Returns a new client if its allowed.
|
298
299
|
# _add is volatile; and may cause threading issues
|
299
300
|
# if called outside @mutex.synchronize {}
|
300
|
-
def _fetch_new
|
301
|
+
def _fetch_new(&client_block)
|
301
302
|
if (@never_block || (_total_current_size < @max_size))
|
302
|
-
|
303
|
+
if client_block.arity == 0
|
304
|
+
nc = yield
|
305
|
+
else
|
306
|
+
nc = yield @sessions_key
|
307
|
+
end
|
303
308
|
HotTub.logger.info "[HotTub] Adding client: #{nc.class.name} to #{@name}." if HotTub.log_trace?
|
304
309
|
nc
|
305
310
|
end
|
data/lib/hot_tub/reaper.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
module HotTub
|
2
2
|
class Reaper
|
3
|
+
attr_reader :thread
|
4
|
+
|
5
|
+
def self.spawn(obj)
|
6
|
+
self.new(obj)
|
7
|
+
end
|
3
8
|
|
4
9
|
# Creates a new Reaper thread for work.
|
5
10
|
# Expects an object that responses to: :reap!
|
@@ -7,8 +12,8 @@ module HotTub
|
|
7
12
|
# Threads swallow exceptions until they are joined,
|
8
13
|
# so we rescue, log, and kill the reaper when an exception occurs
|
9
14
|
# https://bugs.ruby-lang.org/issues/6647
|
10
|
-
def
|
11
|
-
|
15
|
+
def initialize(obj)
|
16
|
+
@thread = Thread.new {
|
12
17
|
loop do
|
13
18
|
begin
|
14
19
|
break if obj.shutdown
|
@@ -21,21 +26,38 @@ module HotTub
|
|
21
26
|
end
|
22
27
|
end
|
23
28
|
}
|
24
|
-
|
25
|
-
|
26
|
-
|
29
|
+
@thread[:name] = "HotTub::Reaper"
|
30
|
+
@thread.abort_on_exception = true
|
31
|
+
@thread
|
32
|
+
end
|
33
|
+
|
34
|
+
def status
|
35
|
+
@thread.status
|
36
|
+
end
|
37
|
+
|
38
|
+
def wakeup
|
39
|
+
@thread.wakeup
|
40
|
+
end
|
41
|
+
|
42
|
+
def shutdown
|
43
|
+
@thread.kill
|
44
|
+
@thread.join
|
45
|
+
end
|
46
|
+
|
47
|
+
def alive?
|
48
|
+
@thread.alive?
|
27
49
|
end
|
28
50
|
|
29
51
|
# Mixin to dry up Reaper usage
|
30
52
|
module Mixin
|
31
53
|
attr_reader :reap_timeout, :shutdown, :reaper
|
32
54
|
|
33
|
-
# Setting reaper kills the current reaper.
|
55
|
+
# Setting reaper kills the current reaper.
|
34
56
|
# If the values is truthy a new HotTub::Reaper
|
35
57
|
# is created.
|
36
58
|
def reaper=reaper
|
37
59
|
kill_reaper
|
38
|
-
if reaper
|
60
|
+
if reaper
|
39
61
|
@reaper = HotTub::Reaper.new(self)
|
40
62
|
else
|
41
63
|
@reaper = false
|
@@ -48,8 +70,7 @@ module HotTub
|
|
48
70
|
|
49
71
|
def kill_reaper
|
50
72
|
if @reaper
|
51
|
-
@reaper.
|
52
|
-
@reaper.join
|
73
|
+
@reaper.shutdown
|
53
74
|
@reaper = nil if @shutdown
|
54
75
|
end
|
55
76
|
end
|
data/lib/hot_tub/sessions.rb
CHANGED
@@ -3,72 +3,141 @@ module HotTub
|
|
3
3
|
class Sessions
|
4
4
|
include HotTub::KnownClients
|
5
5
|
include HotTub::Reaper::Mixin
|
6
|
-
attr_accessor :name
|
6
|
+
attr_accessor :name,
|
7
|
+
:default_client
|
7
8
|
|
8
9
|
# HotTub::Sessions simplifies managing multiple Pools in a single object
|
9
10
|
# and using a single Reaper.
|
10
11
|
#
|
11
12
|
# == Example:
|
12
13
|
#
|
13
|
-
#
|
14
|
-
# url2 = "http://somewebservice2.com"
|
15
|
-
#
|
16
|
-
# sessions = HotTub::Sessions
|
17
|
-
# sessions.add(url,{:size => 12}) {
|
14
|
+
# sessions = HotTub::Sessions(:size => 10) do |url|
|
18
15
|
# uri = URI.parse(url)
|
19
16
|
# http = Net::HTTP.new(uri.host, uri.port)
|
20
|
-
# http.use_ssl = false
|
21
17
|
# http.start
|
22
18
|
# http
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# # Every time we pass a url that lacks a entry in our
|
22
|
+
# # sessions, a new HotTub::Pool is added for that url
|
23
|
+
# # using the &default_client.
|
24
|
+
# #
|
25
|
+
# sessions.run("https://www.google.com"") do |conn|
|
26
|
+
# p conn.get('/').code
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# sessions.run("https://www.yahoo.com"") do |conn|
|
30
|
+
# p conn.get('/').code
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# # Lazy load a non-default connection
|
34
|
+
#
|
35
|
+
# excon_url = "http://somewebservice2.com"
|
36
|
+
#
|
37
|
+
# sessions.stage(excon_url,{:size => 5}) {
|
38
|
+
# Excon.new(excon_url, :thread_safe_socket => false)
|
26
39
|
# }
|
27
40
|
#
|
28
|
-
#
|
29
|
-
#
|
41
|
+
# # Excon connection is created on the first call to `.run`
|
42
|
+
# sessions.run(excon_url) do |conn|
|
43
|
+
# p conn.head.code
|
30
44
|
# end
|
31
45
|
#
|
32
|
-
#
|
33
|
-
#
|
46
|
+
#
|
47
|
+
# # Add a connection, which returns a HotTub::Pool instance
|
48
|
+
#
|
49
|
+
# excon_url2 = "http://somewebservice2.com"
|
50
|
+
#
|
51
|
+
# MY_CON = sessions.add(excon_url2,{:size => 5}) {
|
52
|
+
# Excon.new(excon_url2, :thread_safe_socket => false)
|
53
|
+
# }
|
54
|
+
#
|
55
|
+
# # Uses Excon
|
56
|
+
# MY_CON.run(excon_url) do |conn|
|
57
|
+
# p conn.head.code
|
34
58
|
# end
|
35
59
|
#
|
36
60
|
# === OPTIONS
|
61
|
+
#
|
62
|
+
# &default_client
|
63
|
+
# An optional block for a default client for your pools. If your block accepts a
|
64
|
+
# parameters, they session key is passed to the block. Your default client
|
65
|
+
# block will be overridden if you pass a client block to get_or_set
|
66
|
+
#
|
67
|
+
# [:pool_options]
|
68
|
+
# Default options for your HotTub::Pools. If you pass options to #get_or_set those options
|
69
|
+
# override :pool_options.
|
70
|
+
#
|
37
71
|
# [:name]
|
38
72
|
# A string representing the name of your sessions used for logging.
|
39
73
|
#
|
40
74
|
# [:reaper]
|
41
|
-
# If set to false prevents a HotTub::Reaper from initializing.
|
75
|
+
# If set to false prevents a HotTub::Reaper from initializing for these sessions.
|
42
76
|
#
|
43
77
|
# [:reap_timeout]
|
44
78
|
# Default is 600 seconds. An integer that represents the timeout for reaping the pool in seconds.
|
45
79
|
#
|
46
|
-
def initialize(opts={})
|
47
|
-
@name
|
48
|
-
@reaper
|
49
|
-
@reap_timeout
|
80
|
+
def initialize(opts={}, &default_client)
|
81
|
+
@name = (opts[:name] || self.class.name)
|
82
|
+
@reaper = opts[:reaper]
|
83
|
+
@reap_timeout = (opts[:reap_timeout] || 600)
|
84
|
+
@default_client = default_client
|
85
|
+
@pool_options = (opts[:pool_options] || {})
|
86
|
+
|
87
|
+
@_staged = {}
|
88
|
+
@_staged.taint
|
89
|
+
|
90
|
+
@_sessions = {}
|
91
|
+
@_sessions.taint
|
50
92
|
|
51
|
-
@
|
52
|
-
@
|
53
|
-
@shutdown = false
|
93
|
+
@mutex = Mutex.new
|
94
|
+
@shutdown = false
|
54
95
|
|
55
96
|
at_exit {shutdown!}
|
56
97
|
end
|
57
98
|
|
58
|
-
#
|
59
|
-
#
|
60
|
-
def
|
61
|
-
raise ArgumentError, 'a block that initializes a new client is required.' unless block_given?
|
62
|
-
pool = nil
|
63
|
-
return pool if pool = @_sessions[key]
|
64
|
-
pool_options[:sessions] = true
|
65
|
-
pool_options[:name] = "#{@name} - #{key}"
|
99
|
+
# Sets arguments / settings for a session that will be
|
100
|
+
# lazy loaded, returns nil because pool is not created
|
101
|
+
def stage(key, pool_options={}, &client_block)
|
66
102
|
@mutex.synchronize do
|
67
|
-
@
|
68
|
-
|
103
|
+
@_staged[key] = [pool_options,client_block]
|
104
|
+
end
|
105
|
+
nil
|
106
|
+
end
|
107
|
+
|
108
|
+
# Returns a HotTub::Pool for the given key. If a session
|
109
|
+
# is not found and the is a default_client set, a session will
|
110
|
+
# be created for the key using the default_client.
|
111
|
+
def get(key)
|
112
|
+
pool = @_sessions[key]
|
113
|
+
unless pool
|
114
|
+
@mutex.synchronize do
|
115
|
+
unless @shutdown
|
116
|
+
@reaper = spawn_reaper if @reaper.nil?
|
117
|
+
unless pool = @_sessions[key]
|
118
|
+
settings = @_staged[key]
|
119
|
+
clnt_blk = (settings[1] || @default_client)
|
120
|
+
op = @pool_options.merge(settings[0])
|
121
|
+
op[:sessions_key] = key
|
122
|
+
op[:name] = "#{@name} - #{key}"
|
123
|
+
pool = @_sessions[key] = HotTub::Pool.new(op, &clnt_blk)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
69
127
|
end
|
70
128
|
pool
|
71
129
|
end
|
130
|
+
|
131
|
+
# Adds session unless it already exists and returns
|
132
|
+
# the session
|
133
|
+
def get_or_set(key, pool_options={}, &client_block)
|
134
|
+
unless @_staged[key]
|
135
|
+
@mutex.synchronize do
|
136
|
+
@_staged[key] ||= [pool_options,client_block]
|
137
|
+
end
|
138
|
+
end
|
139
|
+
get(key)
|
140
|
+
end
|
72
141
|
alias :add :get_or_set
|
73
142
|
|
74
143
|
# Deletes and shutdowns the pool if its found.
|
@@ -79,7 +148,7 @@ module HotTub
|
|
79
148
|
pool = @_sessions.delete(key)
|
80
149
|
end
|
81
150
|
if pool
|
82
|
-
pool.
|
151
|
+
pool.shutdown!
|
83
152
|
deleted = true
|
84
153
|
HotTub.logger.info "[HotTub] #{key} was deleted from #{@name}." if HotTub.logger
|
85
154
|
end
|
@@ -87,8 +156,9 @@ module HotTub
|
|
87
156
|
end
|
88
157
|
|
89
158
|
def fetch(key)
|
90
|
-
pool =
|
91
|
-
|
159
|
+
unless pool = get(key, &@default_client)
|
160
|
+
raise MissingSession, "A session could not be found for #{key.inspect} #{@name}"
|
161
|
+
end
|
92
162
|
pool
|
93
163
|
end
|
94
164
|
|
@@ -96,7 +166,7 @@ module HotTub
|
|
96
166
|
|
97
167
|
def run(key, &run_block)
|
98
168
|
pool = fetch(key)
|
99
|
-
pool.run
|
169
|
+
pool.run(&run_block)
|
100
170
|
end
|
101
171
|
|
102
172
|
def clean!
|