sequel 3.21.0 → 3.28.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.
- data/CHANGELOG +294 -0
- data/README.rdoc +20 -6
- data/Rakefile +20 -15
- data/doc/association_basics.rdoc +210 -43
- data/doc/dataset_basics.rdoc +4 -4
- data/doc/mass_assignment.rdoc +54 -0
- data/doc/migration.rdoc +15 -538
- data/doc/model_hooks.rdoc +64 -27
- data/doc/opening_databases.rdoc +37 -10
- data/doc/prepared_statements.rdoc +16 -10
- data/doc/reflection.rdoc +8 -2
- data/doc/release_notes/3.22.0.txt +39 -0
- data/doc/release_notes/3.23.0.txt +172 -0
- data/doc/release_notes/3.24.0.txt +420 -0
- data/doc/release_notes/3.25.0.txt +88 -0
- data/doc/release_notes/3.26.0.txt +88 -0
- data/doc/release_notes/3.27.0.txt +82 -0
- data/doc/release_notes/3.28.0.txt +304 -0
- data/doc/schema_modification.rdoc +547 -0
- data/doc/testing.rdoc +106 -0
- data/doc/transactions.rdoc +97 -0
- data/doc/virtual_rows.rdoc +2 -2
- data/lib/sequel/adapters/ado.rb +12 -1
- data/lib/sequel/adapters/amalgalite.rb +4 -0
- data/lib/sequel/adapters/db2.rb +95 -58
- data/lib/sequel/adapters/do.rb +12 -0
- data/lib/sequel/adapters/firebird.rb +25 -203
- data/lib/sequel/adapters/ibmdb.rb +440 -0
- data/lib/sequel/adapters/informix.rb +4 -19
- data/lib/sequel/adapters/jdbc/as400.rb +0 -7
- data/lib/sequel/adapters/jdbc/db2.rb +49 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +34 -0
- data/lib/sequel/adapters/jdbc/h2.rb +16 -5
- data/lib/sequel/adapters/jdbc/informix.rb +31 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +0 -32
- data/lib/sequel/adapters/jdbc/mysql.rb +9 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +2 -27
- data/lib/sequel/adapters/jdbc/postgresql.rb +6 -0
- data/lib/sequel/adapters/jdbc/sqlserver.rb +46 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +34 -0
- data/lib/sequel/adapters/jdbc.rb +62 -29
- data/lib/sequel/adapters/mysql.rb +22 -139
- data/lib/sequel/adapters/mysql2.rb +9 -14
- data/lib/sequel/adapters/odbc/db2.rb +21 -0
- data/lib/sequel/adapters/odbc.rb +15 -3
- data/lib/sequel/adapters/oracle.rb +17 -1
- data/lib/sequel/adapters/postgres.rb +111 -16
- data/lib/sequel/adapters/shared/access.rb +21 -0
- data/lib/sequel/adapters/shared/db2.rb +290 -0
- data/lib/sequel/adapters/shared/firebird.rb +214 -0
- data/lib/sequel/adapters/shared/informix.rb +45 -0
- data/lib/sequel/adapters/shared/mssql.rb +85 -47
- data/lib/sequel/adapters/shared/mysql.rb +50 -7
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +143 -0
- data/lib/sequel/adapters/shared/oracle.rb +0 -4
- data/lib/sequel/adapters/shared/postgres.rb +75 -43
- data/lib/sequel/adapters/shared/sqlite.rb +56 -8
- data/lib/sequel/adapters/sqlite.rb +12 -11
- data/lib/sequel/adapters/swift/mysql.rb +9 -0
- data/lib/sequel/adapters/tinytds.rb +139 -7
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +55 -0
- data/lib/sequel/ast_transformer.rb +190 -0
- data/lib/sequel/connection_pool/threaded.rb +3 -2
- data/lib/sequel/connection_pool.rb +1 -1
- data/lib/sequel/core.rb +6 -5
- data/lib/sequel/database/connecting.rb +5 -5
- data/lib/sequel/database/dataset.rb +1 -1
- data/lib/sequel/database/dataset_defaults.rb +1 -1
- data/lib/sequel/database/logging.rb +1 -1
- data/lib/sequel/database/misc.rb +38 -17
- data/lib/sequel/database/query.rb +50 -19
- data/lib/sequel/database/schema_generator.rb +8 -5
- data/lib/sequel/database/schema_methods.rb +52 -27
- data/lib/sequel/dataset/actions.rb +167 -48
- data/lib/sequel/dataset/features.rb +57 -8
- data/lib/sequel/dataset/graph.rb +1 -1
- data/lib/sequel/dataset/misc.rb +39 -20
- data/lib/sequel/dataset/mutation.rb +3 -3
- data/lib/sequel/dataset/prepared_statements.rb +29 -14
- data/lib/sequel/dataset/query.rb +182 -32
- data/lib/sequel/dataset/sql.rb +31 -58
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +61 -0
- data/lib/sequel/extensions/migration.rb +6 -4
- data/lib/sequel/extensions/to_dot.rb +95 -83
- data/lib/sequel/model/associations.rb +893 -309
- data/lib/sequel/model/base.rb +302 -105
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +5 -1
- data/lib/sequel/model.rb +13 -7
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/defaults_setter.rb +58 -0
- data/lib/sequel/plugins/identity_map.rb +113 -6
- data/lib/sequel/plugins/many_through_many.rb +67 -5
- data/lib/sequel/plugins/prepared_statements.rb +140 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
- data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
- data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
- data/lib/sequel/plugins/sharding.rb +12 -20
- data/lib/sequel/plugins/single_table_inheritance.rb +2 -0
- data/lib/sequel/plugins/update_primary_key.rb +1 -1
- data/lib/sequel/plugins/xml_serializer.rb +3 -3
- data/lib/sequel/sql.rb +107 -51
- data/lib/sequel/timezones.rb +12 -3
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/mssql_spec.rb +36 -0
- data/spec/adapters/mysql_spec.rb +36 -19
- data/spec/adapters/postgres_spec.rb +115 -28
- data/spec/adapters/spec_helper.rb +6 -0
- data/spec/adapters/sqlite_spec.rb +11 -0
- data/spec/core/connection_pool_spec.rb +62 -77
- data/spec/core/database_spec.rb +244 -287
- data/spec/core/dataset_spec.rb +383 -34
- data/spec/core/expression_filters_spec.rb +159 -41
- data/spec/core/schema_spec.rb +326 -3
- data/spec/core/spec_helper.rb +45 -0
- data/spec/extensions/association_pks_spec.rb +38 -0
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/identity_map_spec.rb +162 -0
- data/spec/extensions/many_through_many_spec.rb +195 -20
- data/spec/extensions/migration_spec.rb +17 -17
- data/spec/extensions/nested_attributes_spec.rb +1 -0
- data/spec/extensions/prepared_statements_associations_spec.rb +126 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +79 -0
- data/spec/extensions/prepared_statements_spec.rb +72 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +38 -0
- data/spec/extensions/schema_dumper_spec.rb +2 -2
- data/spec/extensions/schema_spec.rb +12 -20
- data/spec/extensions/serialization_modification_detection_spec.rb +36 -0
- data/spec/extensions/single_table_inheritance_spec.rb +11 -0
- data/spec/extensions/spec_helper.rb +3 -1
- data/spec/extensions/to_dot_spec.rb +3 -5
- data/spec/extensions/xml_serializer_spec.rb +16 -4
- data/spec/integration/associations_test.rb +405 -15
- data/spec/integration/database_test.rb +4 -2
- data/spec/integration/dataset_test.rb +240 -20
- data/spec/integration/plugin_test.rb +142 -5
- data/spec/integration/prepared_statement_test.rb +174 -95
- data/spec/integration/schema_test.rb +128 -16
- data/spec/integration/spec_helper.rb +15 -0
- data/spec/integration/transaction_test.rb +40 -0
- data/spec/integration/type_test.rb +16 -2
- data/spec/model/association_reflection_spec.rb +91 -0
- data/spec/model/associations_spec.rb +476 -5
- data/spec/model/base_spec.rb +91 -1
- data/spec/model/eager_loading_spec.rb +519 -31
- data/spec/model/hooks_spec.rb +161 -0
- data/spec/model/model_spec.rb +89 -2
- data/spec/model/plugins_spec.rb +17 -0
- data/spec/model/record_spec.rb +184 -12
- data/spec/model/spec_helper.rb +5 -0
- data/spec/model/validations_spec.rb +11 -0
- metadata +85 -34
|
@@ -84,7 +84,9 @@ describe "A connection pool handling connections" do
|
|
|
84
84
|
end
|
|
85
85
|
|
|
86
86
|
specify "#make_new should not make more than max_size connections" do
|
|
87
|
-
|
|
87
|
+
q = Queue.new
|
|
88
|
+
50.times{Thread.new{@cpool.hold{q.pop}}}
|
|
89
|
+
50.times{q.push nil}
|
|
88
90
|
@cpool.created_count.should <= @max_size
|
|
89
91
|
end
|
|
90
92
|
|
|
@@ -96,7 +98,8 @@ describe "A connection pool handling connections" do
|
|
|
96
98
|
|
|
97
99
|
specify "#hold should remove the connection if a DatabaseDisconnectError is raised" do
|
|
98
100
|
@cpool.created_count.should == 0
|
|
99
|
-
|
|
101
|
+
q, q1 = Queue.new, Queue.new
|
|
102
|
+
@cpool.hold{Thread.new{@cpool.hold{q1.pop; q.push nil}; q1.pop; q.push nil}; q1.push nil; q.pop; q1.push nil; q.pop}
|
|
100
103
|
@cpool.created_count.should == 2
|
|
101
104
|
proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.should raise_error(Sequel::DatabaseDisconnectError)
|
|
102
105
|
@cpool.created_count.should == 1
|
|
@@ -166,15 +169,14 @@ describe "A connection pool with a max size of 1" do
|
|
|
166
169
|
|
|
167
170
|
specify "should let only one thread access the connection at any time" do
|
|
168
171
|
cc,c1, c2 = nil
|
|
169
|
-
|
|
172
|
+
q, q1 = Queue.new, Queue.new
|
|
170
173
|
|
|
171
|
-
t1 = Thread.new {@pool.hold {|c| cc = c; c1 = c.dup;
|
|
172
|
-
|
|
174
|
+
t1 = Thread.new {@pool.hold {|c| cc = c; c1 = c.dup; q1.push nil; q.pop}}
|
|
175
|
+
q1.pop
|
|
173
176
|
cc.should == 'herro'
|
|
174
177
|
c1.should == 'herro'
|
|
175
178
|
|
|
176
|
-
t2 = Thread.new {@pool.hold {|c| c2 = c.dup;
|
|
177
|
-
sleep 0.02 * m
|
|
179
|
+
t2 = Thread.new {@pool.hold {|c| c2 = c.dup; q1.push nil; q.pop;}}
|
|
178
180
|
|
|
179
181
|
# connection held by t1
|
|
180
182
|
t1.should be_alive
|
|
@@ -186,26 +188,22 @@ describe "A connection pool with a max size of 1" do
|
|
|
186
188
|
|
|
187
189
|
@pool.available_connections.should be_empty
|
|
188
190
|
@pool.allocated.should == {t1=>cc}
|
|
189
|
-
|
|
191
|
+
|
|
190
192
|
cc.gsub!('rr', 'll')
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
193
|
+
q.push nil
|
|
194
|
+
q1.pop
|
|
195
|
+
|
|
194
196
|
t1.should_not be_alive
|
|
195
197
|
t2.should be_alive
|
|
196
|
-
|
|
198
|
+
|
|
197
199
|
c2.should == 'hello'
|
|
198
200
|
|
|
199
201
|
@pool.available_connections.should be_empty
|
|
200
202
|
@pool.allocated.should == {t2=>cc}
|
|
201
203
|
|
|
202
|
-
cc.gsub!('ll', 'rr')
|
|
203
|
-
sleep 0.05 * m
|
|
204
|
-
|
|
205
204
|
#connection released
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
cc.should == 'herro'
|
|
205
|
+
q.push nil
|
|
206
|
+
t2.join
|
|
209
207
|
|
|
210
208
|
@invoked_count.should == 1
|
|
211
209
|
@pool.size.should == 1
|
|
@@ -236,34 +234,42 @@ describe "A connection pool with a max size of 1" do
|
|
|
236
234
|
end
|
|
237
235
|
|
|
238
236
|
shared_examples_for "A threaded connection pool" do
|
|
237
|
+
specify "should raise a PoolTimeout error if a connection couldn't be acquired before timeout" do
|
|
238
|
+
x = nil
|
|
239
|
+
q, q1 = Queue.new, Queue.new
|
|
240
|
+
pool = Sequel::ConnectionPool.get_pool(@cp_opts.merge(:max_connections=>1, :pool_timeout=>0)) {@invoked_count += 1}
|
|
241
|
+
t = Thread.new{pool.hold{|c| q1.push nil; q.pop}}
|
|
242
|
+
q1.pop
|
|
243
|
+
proc{pool.hold{|c|}}.should raise_error(Sequel::PoolTimeout)
|
|
244
|
+
q.push nil
|
|
245
|
+
t.join
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
it "should not add a disconnected connection back to the pool if the disconnection_proc raises an error" do
|
|
249
|
+
pool = Sequel::ConnectionPool.get_pool(@cp_opts.merge(:max_connections=>1, :pool_timeout=>0, :disconnection_proc=>proc{|c| raise Sequel::Error})) {@invoked_count += 1}
|
|
250
|
+
proc{pool.hold{raise Sequel::DatabaseDisconnectError}}.should raise_error(Sequel::Error)
|
|
251
|
+
pool.available_connections.length.should == 0
|
|
252
|
+
end
|
|
253
|
+
|
|
239
254
|
specify "should let five threads simultaneously access separate connections" do
|
|
240
255
|
cc = {}
|
|
241
256
|
threads = []
|
|
242
|
-
|
|
257
|
+
q, q1, q2 = Queue.new, Queue.new, Queue.new
|
|
243
258
|
|
|
244
|
-
5.times
|
|
245
|
-
sleep 0.04
|
|
259
|
+
5.times{|i| threads << Thread.new{@pool.hold{|c| q.pop; cc[i] = c; q1.push nil; q2.pop}}; q.push nil; q1.pop}
|
|
246
260
|
threads.each {|t| t.should be_alive}
|
|
247
261
|
cc.size.should == 5
|
|
248
262
|
@invoked_count.should == 5
|
|
249
263
|
@pool.size.should == 5
|
|
250
264
|
@pool.available_connections.should be_empty
|
|
251
|
-
|
|
265
|
+
|
|
252
266
|
h = {}
|
|
267
|
+
i = 0
|
|
253
268
|
threads.each{|t| h[t] = (i+=1)}
|
|
254
269
|
@pool.allocated.should == h
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
threads[3].raise "your'e dead too"
|
|
259
|
-
|
|
260
|
-
sleep 0.02
|
|
261
|
-
|
|
262
|
-
@pool.available_connections.should == [1, 4]
|
|
263
|
-
@pool.allocated.should == {threads[1]=>2, threads[2]=>3, threads[4]=>5}
|
|
264
|
-
|
|
265
|
-
stop = true
|
|
266
|
-
sleep 0.04
|
|
270
|
+
@pool.available_connections.should == []
|
|
271
|
+
5.times{q2.push nil}
|
|
272
|
+
threads.each{|t| t.join}
|
|
267
273
|
|
|
268
274
|
@pool.available_connections.size.should == 5
|
|
269
275
|
@pool.allocated.should be_empty
|
|
@@ -272,16 +278,15 @@ shared_examples_for "A threaded connection pool" do
|
|
|
272
278
|
specify "should block threads until a connection becomes available" do
|
|
273
279
|
cc = {}
|
|
274
280
|
threads = []
|
|
275
|
-
|
|
281
|
+
q, q1 = Queue.new, Queue.new
|
|
276
282
|
|
|
277
|
-
5.times
|
|
278
|
-
|
|
283
|
+
5.times{|i| threads << Thread.new{@pool.hold{|c| cc[i] = c; q1.push nil; q.pop}}}
|
|
284
|
+
5.times{q1.pop}
|
|
279
285
|
threads.each {|t| t.should be_alive}
|
|
280
286
|
@pool.available_connections.should be_empty
|
|
281
287
|
|
|
282
|
-
3.times {|i| threads << Thread.new {@pool.hold {|c| cc[i + 5] = c}}}
|
|
288
|
+
3.times {|i| threads << Thread.new {@pool.hold {|c| cc[i + 5] = c; q1.push nil}}}
|
|
283
289
|
|
|
284
|
-
sleep 0.02
|
|
285
290
|
threads[5].should be_alive
|
|
286
291
|
threads[6].should be_alive
|
|
287
292
|
threads[7].should be_alive
|
|
@@ -290,8 +295,10 @@ shared_examples_for "A threaded connection pool" do
|
|
|
290
295
|
cc[6].should be_nil
|
|
291
296
|
cc[7].should be_nil
|
|
292
297
|
|
|
293
|
-
|
|
294
|
-
|
|
298
|
+
5.times{q.push nil}
|
|
299
|
+
5.times{|i| threads[i].join}
|
|
300
|
+
3.times{q1.pop}
|
|
301
|
+
3.times{|i| threads[i+5].join}
|
|
295
302
|
|
|
296
303
|
threads.each {|t| t.should_not be_alive}
|
|
297
304
|
|
|
@@ -305,7 +312,8 @@ end
|
|
|
305
312
|
describe "Threaded Unsharded Connection Pool" do
|
|
306
313
|
before do
|
|
307
314
|
@invoked_count = 0
|
|
308
|
-
@
|
|
315
|
+
@cp_opts = CONNECTION_POOL_DEFAULTS.merge(:max_connections=>5)
|
|
316
|
+
@pool = Sequel::ConnectionPool.get_pool(@cp_opts) {@invoked_count += 1}
|
|
309
317
|
end
|
|
310
318
|
|
|
311
319
|
it_should_behave_like "A threaded connection pool"
|
|
@@ -314,7 +322,8 @@ end
|
|
|
314
322
|
describe "Threaded Sharded Connection Pool" do
|
|
315
323
|
before do
|
|
316
324
|
@invoked_count = 0
|
|
317
|
-
@
|
|
325
|
+
@cp_opts = CONNECTION_POOL_DEFAULTS.merge(:max_connections=>5, :servers=>{})
|
|
326
|
+
@pool = Sequel::ConnectionPool.get_pool(@cp_opts) {@invoked_count += 1}
|
|
318
327
|
end
|
|
319
328
|
|
|
320
329
|
it_should_behave_like "A threaded connection pool"
|
|
@@ -324,19 +333,15 @@ describe "ConnectionPool#disconnect" do
|
|
|
324
333
|
before do
|
|
325
334
|
@count = 0
|
|
326
335
|
@pool = Sequel::ConnectionPool.get_pool(CONNECTION_POOL_DEFAULTS.merge(:max_connections=>5, :servers=>{})) {{:id => @count += 1}}
|
|
336
|
+
threads = []
|
|
337
|
+
q, q1 = Queue.new, Queue.new
|
|
338
|
+
5.times {|i| threads << Thread.new {@pool.hold {|c| q1.push nil; q.pop}}}
|
|
339
|
+
5.times{q1.pop}
|
|
340
|
+
5.times{q.push nil}
|
|
341
|
+
threads.each {|t| t.join}
|
|
327
342
|
end
|
|
328
343
|
|
|
329
344
|
specify "should invoke the given block for each available connection" do
|
|
330
|
-
threads = []
|
|
331
|
-
stop = nil
|
|
332
|
-
5.times {|i| threads << Thread.new {@pool.hold {|c| while !stop;sleep 0.01;end}}; sleep 0.01}
|
|
333
|
-
while @pool.size < 5
|
|
334
|
-
sleep 0.02
|
|
335
|
-
end
|
|
336
|
-
stop = true
|
|
337
|
-
sleep 0.1
|
|
338
|
-
threads.each {|t| t.join}
|
|
339
|
-
|
|
340
345
|
@pool.size.should == 5
|
|
341
346
|
@pool.available_connections.size.should == 5
|
|
342
347
|
@pool.available_connections.each {|c| c[:id].should_not be_nil}
|
|
@@ -346,34 +351,13 @@ describe "ConnectionPool#disconnect" do
|
|
|
346
351
|
end
|
|
347
352
|
|
|
348
353
|
specify "should remove all available connections" do
|
|
349
|
-
threads = []
|
|
350
|
-
stop = nil
|
|
351
|
-
5.times {|i| threads << Thread.new {@pool.hold {|c| while !stop;sleep 0.01;end}}; sleep 0.01}
|
|
352
|
-
while @pool.size < 5
|
|
353
|
-
sleep 0.02
|
|
354
|
-
end
|
|
355
|
-
stop = true
|
|
356
|
-
sleep 0.1
|
|
357
|
-
threads.each {|t| t.join}
|
|
358
|
-
|
|
359
354
|
@pool.size.should == 5
|
|
360
355
|
@pool.disconnect
|
|
361
356
|
@pool.size.should == 0
|
|
362
357
|
end
|
|
363
358
|
|
|
364
359
|
specify "should disconnect connections in use as soon as they are no longer in use" do
|
|
365
|
-
threads = []
|
|
366
|
-
stop = nil
|
|
367
|
-
5.times {|i| threads << Thread.new {@pool.hold {|c| while !stop;sleep 0.01;end}}; sleep 0.01}
|
|
368
|
-
while @pool.size < 5
|
|
369
|
-
sleep 0.02
|
|
370
|
-
end
|
|
371
|
-
stop = true
|
|
372
|
-
sleep 0.1
|
|
373
|
-
threads.each {|t| t.join}
|
|
374
|
-
|
|
375
360
|
@pool.size.should == 5
|
|
376
|
-
|
|
377
361
|
@pool.hold do |conn|
|
|
378
362
|
@pool.available_connections.size.should == 4
|
|
379
363
|
@pool.available_connections.each {|c| c.should_not be(conn)}
|
|
@@ -556,9 +540,10 @@ describe "A connection pool with multiple servers" do
|
|
|
556
540
|
specify "#remove_servers should disconnect available connections immediately" do
|
|
557
541
|
pool = Sequel::ConnectionPool.get_pool(:max_connections=>5, :servers=>{:server1=>{}}){|s| s}
|
|
558
542
|
threads = []
|
|
559
|
-
|
|
560
|
-
5.times {|i| threads << Thread.new{pool.hold(:server1){|c|
|
|
561
|
-
|
|
543
|
+
q, q1 = Queue.new, Queue.new
|
|
544
|
+
5.times {|i| threads << Thread.new {pool.hold(:server1){|c| q1.push nil; q.pop}}}
|
|
545
|
+
5.times{q1.pop}
|
|
546
|
+
5.times{q.push nil}
|
|
562
547
|
threads.each {|t| t.join}
|
|
563
548
|
|
|
564
549
|
pool.size(:server1).should == 5
|