viking-sequel 3.10.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 +3134 -0
- data/COPYING +19 -0
- data/README.rdoc +723 -0
- data/Rakefile +193 -0
- data/bin/sequel +196 -0
- data/doc/advanced_associations.rdoc +644 -0
- data/doc/cheat_sheet.rdoc +218 -0
- data/doc/dataset_basics.rdoc +106 -0
- data/doc/dataset_filtering.rdoc +158 -0
- data/doc/opening_databases.rdoc +296 -0
- data/doc/prepared_statements.rdoc +104 -0
- data/doc/reflection.rdoc +84 -0
- data/doc/release_notes/1.0.txt +38 -0
- data/doc/release_notes/1.1.txt +143 -0
- data/doc/release_notes/1.3.txt +101 -0
- data/doc/release_notes/1.4.0.txt +53 -0
- data/doc/release_notes/1.5.0.txt +155 -0
- data/doc/release_notes/2.0.0.txt +298 -0
- data/doc/release_notes/2.1.0.txt +271 -0
- data/doc/release_notes/2.10.0.txt +328 -0
- data/doc/release_notes/2.11.0.txt +215 -0
- data/doc/release_notes/2.12.0.txt +534 -0
- data/doc/release_notes/2.2.0.txt +253 -0
- data/doc/release_notes/2.3.0.txt +88 -0
- data/doc/release_notes/2.4.0.txt +106 -0
- data/doc/release_notes/2.5.0.txt +137 -0
- data/doc/release_notes/2.6.0.txt +157 -0
- data/doc/release_notes/2.7.0.txt +166 -0
- data/doc/release_notes/2.8.0.txt +171 -0
- data/doc/release_notes/2.9.0.txt +97 -0
- data/doc/release_notes/3.0.0.txt +221 -0
- data/doc/release_notes/3.1.0.txt +406 -0
- data/doc/release_notes/3.10.0.txt +286 -0
- data/doc/release_notes/3.2.0.txt +268 -0
- data/doc/release_notes/3.3.0.txt +192 -0
- data/doc/release_notes/3.4.0.txt +325 -0
- data/doc/release_notes/3.5.0.txt +510 -0
- data/doc/release_notes/3.6.0.txt +366 -0
- data/doc/release_notes/3.7.0.txt +179 -0
- data/doc/release_notes/3.8.0.txt +151 -0
- data/doc/release_notes/3.9.0.txt +233 -0
- data/doc/schema.rdoc +36 -0
- data/doc/sharding.rdoc +113 -0
- data/doc/virtual_rows.rdoc +205 -0
- data/lib/sequel.rb +1 -0
- data/lib/sequel/adapters/ado.rb +90 -0
- data/lib/sequel/adapters/ado/mssql.rb +30 -0
- data/lib/sequel/adapters/amalgalite.rb +176 -0
- data/lib/sequel/adapters/db2.rb +139 -0
- data/lib/sequel/adapters/dbi.rb +113 -0
- data/lib/sequel/adapters/do.rb +188 -0
- data/lib/sequel/adapters/do/mysql.rb +49 -0
- data/lib/sequel/adapters/do/postgres.rb +91 -0
- data/lib/sequel/adapters/do/sqlite.rb +40 -0
- data/lib/sequel/adapters/firebird.rb +283 -0
- data/lib/sequel/adapters/informix.rb +77 -0
- data/lib/sequel/adapters/jdbc.rb +587 -0
- data/lib/sequel/adapters/jdbc/as400.rb +58 -0
- data/lib/sequel/adapters/jdbc/h2.rb +133 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +57 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +78 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +50 -0
- data/lib/sequel/adapters/jdbc/postgresql.rb +108 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +55 -0
- data/lib/sequel/adapters/mysql.rb +421 -0
- data/lib/sequel/adapters/odbc.rb +143 -0
- data/lib/sequel/adapters/odbc/mssql.rb +42 -0
- data/lib/sequel/adapters/openbase.rb +64 -0
- data/lib/sequel/adapters/oracle.rb +131 -0
- data/lib/sequel/adapters/postgres.rb +504 -0
- data/lib/sequel/adapters/shared/mssql.rb +490 -0
- data/lib/sequel/adapters/shared/mysql.rb +498 -0
- data/lib/sequel/adapters/shared/oracle.rb +195 -0
- data/lib/sequel/adapters/shared/postgres.rb +830 -0
- data/lib/sequel/adapters/shared/progress.rb +44 -0
- data/lib/sequel/adapters/shared/sqlite.rb +389 -0
- data/lib/sequel/adapters/sqlite.rb +224 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +84 -0
- data/lib/sequel/connection_pool.rb +99 -0
- data/lib/sequel/connection_pool/sharded_single.rb +84 -0
- data/lib/sequel/connection_pool/sharded_threaded.rb +211 -0
- data/lib/sequel/connection_pool/single.rb +29 -0
- data/lib/sequel/connection_pool/threaded.rb +150 -0
- data/lib/sequel/core.rb +293 -0
- data/lib/sequel/core_sql.rb +241 -0
- data/lib/sequel/database.rb +1079 -0
- data/lib/sequel/database/schema_generator.rb +327 -0
- data/lib/sequel/database/schema_methods.rb +203 -0
- data/lib/sequel/database/schema_sql.rb +320 -0
- data/lib/sequel/dataset.rb +32 -0
- data/lib/sequel/dataset/actions.rb +441 -0
- data/lib/sequel/dataset/features.rb +86 -0
- data/lib/sequel/dataset/graph.rb +254 -0
- data/lib/sequel/dataset/misc.rb +119 -0
- data/lib/sequel/dataset/mutation.rb +64 -0
- data/lib/sequel/dataset/prepared_statements.rb +227 -0
- data/lib/sequel/dataset/query.rb +709 -0
- data/lib/sequel/dataset/sql.rb +996 -0
- data/lib/sequel/exceptions.rb +51 -0
- data/lib/sequel/extensions/blank.rb +43 -0
- data/lib/sequel/extensions/inflector.rb +242 -0
- data/lib/sequel/extensions/looser_typecasting.rb +21 -0
- data/lib/sequel/extensions/migration.rb +239 -0
- data/lib/sequel/extensions/named_timezones.rb +61 -0
- data/lib/sequel/extensions/pagination.rb +100 -0
- data/lib/sequel/extensions/pretty_table.rb +82 -0
- data/lib/sequel/extensions/query.rb +52 -0
- data/lib/sequel/extensions/schema_dumper.rb +271 -0
- data/lib/sequel/extensions/sql_expr.rb +122 -0
- data/lib/sequel/extensions/string_date_time.rb +46 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +48 -0
- data/lib/sequel/metaprogramming.rb +9 -0
- data/lib/sequel/model.rb +120 -0
- data/lib/sequel/model/associations.rb +1514 -0
- data/lib/sequel/model/base.rb +1069 -0
- data/lib/sequel/model/default_inflections.rb +45 -0
- data/lib/sequel/model/errors.rb +39 -0
- data/lib/sequel/model/exceptions.rb +21 -0
- data/lib/sequel/model/inflections.rb +162 -0
- data/lib/sequel/model/plugins.rb +70 -0
- data/lib/sequel/plugins/active_model.rb +59 -0
- data/lib/sequel/plugins/association_dependencies.rb +103 -0
- data/lib/sequel/plugins/association_proxies.rb +41 -0
- data/lib/sequel/plugins/boolean_readers.rb +53 -0
- data/lib/sequel/plugins/caching.rb +141 -0
- data/lib/sequel/plugins/class_table_inheritance.rb +214 -0
- data/lib/sequel/plugins/composition.rb +138 -0
- data/lib/sequel/plugins/force_encoding.rb +72 -0
- data/lib/sequel/plugins/hook_class_methods.rb +126 -0
- data/lib/sequel/plugins/identity_map.rb +116 -0
- data/lib/sequel/plugins/instance_filters.rb +98 -0
- data/lib/sequel/plugins/instance_hooks.rb +57 -0
- data/lib/sequel/plugins/lazy_attributes.rb +77 -0
- data/lib/sequel/plugins/many_through_many.rb +208 -0
- data/lib/sequel/plugins/nested_attributes.rb +206 -0
- data/lib/sequel/plugins/optimistic_locking.rb +81 -0
- data/lib/sequel/plugins/rcte_tree.rb +281 -0
- data/lib/sequel/plugins/schema.rb +66 -0
- data/lib/sequel/plugins/serialization.rb +166 -0
- data/lib/sequel/plugins/single_table_inheritance.rb +74 -0
- data/lib/sequel/plugins/subclasses.rb +45 -0
- data/lib/sequel/plugins/tactical_eager_loading.rb +61 -0
- data/lib/sequel/plugins/timestamps.rb +87 -0
- data/lib/sequel/plugins/touch.rb +118 -0
- data/lib/sequel/plugins/typecast_on_load.rb +72 -0
- data/lib/sequel/plugins/validation_class_methods.rb +405 -0
- data/lib/sequel/plugins/validation_helpers.rb +223 -0
- data/lib/sequel/sql.rb +1020 -0
- data/lib/sequel/timezones.rb +161 -0
- data/lib/sequel/version.rb +12 -0
- data/lib/sequel_core.rb +1 -0
- data/lib/sequel_model.rb +1 -0
- data/spec/adapters/firebird_spec.rb +407 -0
- data/spec/adapters/informix_spec.rb +97 -0
- data/spec/adapters/mssql_spec.rb +403 -0
- data/spec/adapters/mysql_spec.rb +1019 -0
- data/spec/adapters/oracle_spec.rb +286 -0
- data/spec/adapters/postgres_spec.rb +969 -0
- data/spec/adapters/spec_helper.rb +51 -0
- data/spec/adapters/sqlite_spec.rb +432 -0
- data/spec/core/connection_pool_spec.rb +808 -0
- data/spec/core/core_sql_spec.rb +417 -0
- data/spec/core/database_spec.rb +1662 -0
- data/spec/core/dataset_spec.rb +3827 -0
- data/spec/core/expression_filters_spec.rb +595 -0
- data/spec/core/object_graph_spec.rb +296 -0
- data/spec/core/schema_generator_spec.rb +159 -0
- data/spec/core/schema_spec.rb +830 -0
- data/spec/core/spec_helper.rb +56 -0
- data/spec/core/version_spec.rb +7 -0
- data/spec/extensions/active_model_spec.rb +76 -0
- data/spec/extensions/association_dependencies_spec.rb +127 -0
- data/spec/extensions/association_proxies_spec.rb +50 -0
- data/spec/extensions/blank_spec.rb +67 -0
- data/spec/extensions/boolean_readers_spec.rb +92 -0
- data/spec/extensions/caching_spec.rb +250 -0
- data/spec/extensions/class_table_inheritance_spec.rb +252 -0
- data/spec/extensions/composition_spec.rb +194 -0
- data/spec/extensions/force_encoding_spec.rb +117 -0
- data/spec/extensions/hook_class_methods_spec.rb +470 -0
- data/spec/extensions/identity_map_spec.rb +202 -0
- data/spec/extensions/inflector_spec.rb +181 -0
- data/spec/extensions/instance_filters_spec.rb +55 -0
- data/spec/extensions/instance_hooks_spec.rb +133 -0
- data/spec/extensions/lazy_attributes_spec.rb +153 -0
- data/spec/extensions/looser_typecasting_spec.rb +39 -0
- data/spec/extensions/many_through_many_spec.rb +884 -0
- data/spec/extensions/migration_spec.rb +332 -0
- data/spec/extensions/named_timezones_spec.rb +72 -0
- data/spec/extensions/nested_attributes_spec.rb +396 -0
- data/spec/extensions/optimistic_locking_spec.rb +100 -0
- data/spec/extensions/pagination_spec.rb +99 -0
- data/spec/extensions/pretty_table_spec.rb +91 -0
- data/spec/extensions/query_spec.rb +85 -0
- data/spec/extensions/rcte_tree_spec.rb +205 -0
- data/spec/extensions/schema_dumper_spec.rb +357 -0
- data/spec/extensions/schema_spec.rb +127 -0
- data/spec/extensions/serialization_spec.rb +209 -0
- data/spec/extensions/single_table_inheritance_spec.rb +96 -0
- data/spec/extensions/spec_helper.rb +91 -0
- data/spec/extensions/sql_expr_spec.rb +89 -0
- data/spec/extensions/string_date_time_spec.rb +93 -0
- data/spec/extensions/subclasses_spec.rb +52 -0
- data/spec/extensions/tactical_eager_loading_spec.rb +65 -0
- data/spec/extensions/thread_local_timezones_spec.rb +45 -0
- data/spec/extensions/timestamps_spec.rb +150 -0
- data/spec/extensions/touch_spec.rb +155 -0
- data/spec/extensions/typecast_on_load_spec.rb +69 -0
- data/spec/extensions/validation_class_methods_spec.rb +984 -0
- data/spec/extensions/validation_helpers_spec.rb +438 -0
- data/spec/integration/associations_test.rb +281 -0
- data/spec/integration/database_test.rb +26 -0
- data/spec/integration/dataset_test.rb +963 -0
- data/spec/integration/eager_loader_test.rb +734 -0
- data/spec/integration/model_test.rb +130 -0
- data/spec/integration/plugin_test.rb +814 -0
- data/spec/integration/prepared_statement_test.rb +213 -0
- data/spec/integration/schema_test.rb +361 -0
- data/spec/integration/spec_helper.rb +73 -0
- data/spec/integration/timezone_test.rb +55 -0
- data/spec/integration/transaction_test.rb +122 -0
- data/spec/integration/type_test.rb +96 -0
- data/spec/model/association_reflection_spec.rb +175 -0
- data/spec/model/associations_spec.rb +2633 -0
- data/spec/model/base_spec.rb +418 -0
- data/spec/model/dataset_methods_spec.rb +78 -0
- data/spec/model/eager_loading_spec.rb +1391 -0
- data/spec/model/hooks_spec.rb +240 -0
- data/spec/model/inflector_spec.rb +26 -0
- data/spec/model/model_spec.rb +593 -0
- data/spec/model/plugins_spec.rb +236 -0
- data/spec/model/record_spec.rb +1500 -0
- data/spec/model/spec_helper.rb +97 -0
- data/spec/model/validations_spec.rb +153 -0
- data/spec/rcov.opts +6 -0
- data/spec/spec_config.rb.example +10 -0
- metadata +346 -0
@@ -0,0 +1,808 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
CONNECTION_POOL_DEFAULTS = {:pool_timeout=>5, :pool_sleep_time=>0.001, :max_connections=>4}
|
3
|
+
|
4
|
+
context "An empty ConnectionPool" do
|
5
|
+
before do
|
6
|
+
@cpool = Sequel::ConnectionPool.get_pool(CONNECTION_POOL_DEFAULTS){}
|
7
|
+
end
|
8
|
+
|
9
|
+
specify "should have no available connections" do
|
10
|
+
@cpool.available_connections.should == []
|
11
|
+
end
|
12
|
+
|
13
|
+
specify "should have no allocated connections" do
|
14
|
+
@cpool.allocated.should == {}
|
15
|
+
end
|
16
|
+
|
17
|
+
specify "should have a created_count of zero" do
|
18
|
+
@cpool.created_count.should == 0
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "ConnectionPool options" do
|
23
|
+
specify "should support string option values" do
|
24
|
+
cpool = Sequel::ConnectionPool.get_pool({:max_connections=>'5', :pool_timeout=>'3', :pool_sleep_time=>'0.01'}){}
|
25
|
+
cpool.max_size.should == 5
|
26
|
+
cpool.instance_variable_get(:@timeout).should == 3
|
27
|
+
cpool.instance_variable_get(:@sleep_time).should == 0.01
|
28
|
+
end
|
29
|
+
|
30
|
+
specify "should raise an error unless size is positive" do
|
31
|
+
lambda{Sequel::ConnectionPool.get_pool(:max_connections=>0)}.should raise_error(Sequel::Error)
|
32
|
+
lambda{Sequel::ConnectionPool.get_pool(:max_connections=>-10)}.should raise_error(Sequel::Error)
|
33
|
+
lambda{Sequel::ConnectionPool.get_pool(:max_connections=>'-10')}.should raise_error(Sequel::Error)
|
34
|
+
lambda{Sequel::ConnectionPool.get_pool(:max_connections=>'0')}.should raise_error(Sequel::Error)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "A connection pool handling connections" do
|
39
|
+
before do
|
40
|
+
@max_size = 2
|
41
|
+
@cpool = Sequel::ConnectionPool.get_pool(CONNECTION_POOL_DEFAULTS.merge(:disconnection_proc=>proc{|c| @max_size=3}, :max_connections=>@max_size)) {:got_connection}
|
42
|
+
end
|
43
|
+
|
44
|
+
specify "#hold should increment #created_count" do
|
45
|
+
@cpool.hold do
|
46
|
+
@cpool.created_count.should == 1
|
47
|
+
@cpool.hold {@cpool.hold {@cpool.created_count.should == 1}}
|
48
|
+
Thread.new{@cpool.hold {@cpool.created_count.should == 2}}.join
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
specify "#hold should add the connection to the #allocated array" do
|
53
|
+
@cpool.hold do
|
54
|
+
@cpool.allocated.size.should == 1
|
55
|
+
|
56
|
+
@cpool.allocated.should == {Thread.current=>:got_connection}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
specify "#hold should yield a new connection" do
|
61
|
+
@cpool.hold {|conn| conn.should == :got_connection}
|
62
|
+
end
|
63
|
+
|
64
|
+
specify "a connection should be de-allocated after it has been used in #hold" do
|
65
|
+
@cpool.hold {}
|
66
|
+
@cpool.allocated.size.should == 0
|
67
|
+
end
|
68
|
+
|
69
|
+
specify "#hold should return the value of its block" do
|
70
|
+
@cpool.hold {:block_return}.should == :block_return
|
71
|
+
end
|
72
|
+
|
73
|
+
if RUBY_VERSION < '1.9.0' and (!defined?(RUBY_ENGINE) or RUBY_ENGINE != 'jruby')
|
74
|
+
specify "#hold should remove dead threads from the pool if it reaches its max_size" do
|
75
|
+
Thread.new{@cpool.hold{Thread.current.exit!}}.join
|
76
|
+
@cpool.allocated.keys.map{|t| t.alive?}.should == [false]
|
77
|
+
|
78
|
+
Thread.new{@cpool.hold{Thread.current.exit!}}.join
|
79
|
+
@cpool.allocated.keys.map{|t| t.alive?}.should == [false, false]
|
80
|
+
|
81
|
+
Thread.new{@cpool.hold{}}.join
|
82
|
+
@cpool.allocated.should == {}
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
specify "#make_new should not make more than max_size connections" do
|
87
|
+
50.times{Thread.new{@cpool.hold{sleep 0.001}}}
|
88
|
+
@cpool.created_count.should <= @max_size
|
89
|
+
end
|
90
|
+
|
91
|
+
specify ":disconnection_proc option should set the disconnection proc to use" do
|
92
|
+
@max_size.should == 2
|
93
|
+
proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.should raise_error(Sequel::DatabaseDisconnectError)
|
94
|
+
@max_size.should == 3
|
95
|
+
end
|
96
|
+
|
97
|
+
specify "#hold should remove the connection if a DatabaseDisconnectError is raised" do
|
98
|
+
@cpool.created_count.should == 0
|
99
|
+
@cpool.hold{Thread.new{@cpool.hold{}}; sleep 0.01}
|
100
|
+
@cpool.created_count.should == 2
|
101
|
+
proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.should raise_error(Sequel::DatabaseDisconnectError)
|
102
|
+
@cpool.created_count.should == 1
|
103
|
+
proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.should raise_error(Sequel::DatabaseDisconnectError)
|
104
|
+
@cpool.created_count.should == 0
|
105
|
+
proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.should raise_error(Sequel::DatabaseDisconnectError)
|
106
|
+
@cpool.created_count.should == 0
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context "A connection pool handling connection errors" do
|
111
|
+
specify "#hold should raise a Sequel::DatabaseConnectionError if an exception is raised by the connection_proc" do
|
112
|
+
cpool = Sequel::ConnectionPool.get_pool(CONNECTION_POOL_DEFAULTS){raise Interrupt}
|
113
|
+
proc{cpool.hold{:block_return}}.should raise_error(Sequel::DatabaseConnectionError)
|
114
|
+
cpool.created_count.should == 0
|
115
|
+
end
|
116
|
+
|
117
|
+
specify "#hold should raise a Sequel::DatabaseConnectionError if nil is returned by the connection_proc" do
|
118
|
+
cpool = Sequel::ConnectionPool.get_pool(CONNECTION_POOL_DEFAULTS){nil}
|
119
|
+
proc{cpool.hold{:block_return}}.should raise_error(Sequel::DatabaseConnectionError)
|
120
|
+
cpool.created_count.should == 0
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
class DummyConnection
|
125
|
+
@@value = 0
|
126
|
+
def initialize
|
127
|
+
@@value += 1
|
128
|
+
end
|
129
|
+
|
130
|
+
def value
|
131
|
+
@@value
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context "ConnectionPool#hold" do
|
136
|
+
before do
|
137
|
+
@pool = Sequel::ConnectionPool.get_pool(CONNECTION_POOL_DEFAULTS) {DummyConnection.new}
|
138
|
+
end
|
139
|
+
|
140
|
+
specify "should pass the result of the connection maker proc to the supplied block" do
|
141
|
+
res = nil
|
142
|
+
@pool.hold {|c| res = c}
|
143
|
+
res.should be_a_kind_of(DummyConnection)
|
144
|
+
res.value.should == 1
|
145
|
+
@pool.hold {|c| res = c}
|
146
|
+
res.should be_a_kind_of(DummyConnection)
|
147
|
+
res.value.should == 1 # the connection maker is invoked only once
|
148
|
+
end
|
149
|
+
|
150
|
+
specify "should be re-entrant by the same thread" do
|
151
|
+
cc = nil
|
152
|
+
@pool.hold {|c| @pool.hold {|c| @pool.hold {|c| cc = c}}}
|
153
|
+
cc.should be_a_kind_of(DummyConnection)
|
154
|
+
end
|
155
|
+
|
156
|
+
specify "should catch exceptions and reraise them" do
|
157
|
+
proc {@pool.hold {|c| c.foobar}}.should raise_error(NoMethodError)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
context "A connection pool with a max size of 1" do
|
162
|
+
before do
|
163
|
+
@invoked_count = 0
|
164
|
+
@pool = Sequel::ConnectionPool.get_pool(CONNECTION_POOL_DEFAULTS.merge(:max_connections=>1)) {@invoked_count += 1; 'herro'}
|
165
|
+
end
|
166
|
+
|
167
|
+
specify "should let only one thread access the connection at any time" do
|
168
|
+
cc,c1, c2 = nil
|
169
|
+
|
170
|
+
t1 = Thread.new {@pool.hold {|c| cc = c; c1 = c.dup; while c == 'herro';sleep 0.01;end}}
|
171
|
+
sleep 0.02
|
172
|
+
cc.should == 'herro'
|
173
|
+
c1.should == 'herro'
|
174
|
+
|
175
|
+
t2 = Thread.new {@pool.hold {|c| c2 = c.dup; while c == 'hello';sleep 0.01;end}}
|
176
|
+
sleep 0.02
|
177
|
+
|
178
|
+
# connection held by t1
|
179
|
+
t1.should be_alive
|
180
|
+
t2.should be_alive
|
181
|
+
|
182
|
+
cc.should == 'herro'
|
183
|
+
c1.should == 'herro'
|
184
|
+
c2.should be_nil
|
185
|
+
|
186
|
+
@pool.available_connections.should be_empty
|
187
|
+
@pool.allocated.should == {t1=>cc}
|
188
|
+
|
189
|
+
cc.gsub!('rr', 'll')
|
190
|
+
sleep 0.05
|
191
|
+
|
192
|
+
# connection held by t2
|
193
|
+
t1.should_not be_alive
|
194
|
+
t2.should be_alive
|
195
|
+
|
196
|
+
c2.should == 'hello'
|
197
|
+
|
198
|
+
@pool.available_connections.should be_empty
|
199
|
+
@pool.allocated.should == {t2=>cc}
|
200
|
+
|
201
|
+
cc.gsub!('ll', 'rr')
|
202
|
+
sleep 0.05
|
203
|
+
|
204
|
+
#connection released
|
205
|
+
t2.should_not be_alive
|
206
|
+
|
207
|
+
cc.should == 'herro'
|
208
|
+
|
209
|
+
@invoked_count.should == 1
|
210
|
+
@pool.size.should == 1
|
211
|
+
@pool.available_connections.should == [cc]
|
212
|
+
@pool.allocated.should be_empty
|
213
|
+
end
|
214
|
+
|
215
|
+
specify "should let the same thread reenter #hold" do
|
216
|
+
c1, c2, c3 = nil
|
217
|
+
@pool.hold do |c|
|
218
|
+
c1 = c
|
219
|
+
@pool.hold do |c|
|
220
|
+
c2 = c
|
221
|
+
@pool.hold do |c|
|
222
|
+
c3 = c
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
c1.should == 'herro'
|
227
|
+
c2.should == 'herro'
|
228
|
+
c3.should == 'herro'
|
229
|
+
|
230
|
+
@invoked_count.should == 1
|
231
|
+
@pool.size.should == 1
|
232
|
+
@pool.available_connections.size.should == 1
|
233
|
+
@pool.allocated.should be_empty
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
shared_examples_for "A threaded connection pool" do
|
238
|
+
specify "should let five threads simultaneously access separate connections" do
|
239
|
+
cc = {}
|
240
|
+
threads = []
|
241
|
+
stop = nil
|
242
|
+
|
243
|
+
5.times {|i| threads << Thread.new {@pool.hold {|c| cc[i] = c; while !stop;sleep 0.01;end}}; sleep 0.01}
|
244
|
+
sleep 0.02
|
245
|
+
threads.each {|t| t.should be_alive}
|
246
|
+
cc.size.should == 5
|
247
|
+
@invoked_count.should == 5
|
248
|
+
@pool.size.should == 5
|
249
|
+
@pool.available_connections.should be_empty
|
250
|
+
i = 0
|
251
|
+
h = {}
|
252
|
+
threads.each{|t| h[t] = (i+=1)}
|
253
|
+
@pool.allocated.should == h
|
254
|
+
|
255
|
+
threads[0].raise "your'e dead"
|
256
|
+
sleep 0.01
|
257
|
+
threads[3].raise "your'e dead too"
|
258
|
+
|
259
|
+
sleep 0.01
|
260
|
+
|
261
|
+
@pool.available_connections.should == [1, 4]
|
262
|
+
@pool.allocated.should == {threads[1]=>2, threads[2]=>3, threads[4]=>5}
|
263
|
+
|
264
|
+
stop = true
|
265
|
+
sleep 0.02
|
266
|
+
|
267
|
+
@pool.available_connections.size.should == 5
|
268
|
+
@pool.allocated.should be_empty
|
269
|
+
end
|
270
|
+
|
271
|
+
specify "should block threads until a connection becomes available" do
|
272
|
+
cc = {}
|
273
|
+
threads = []
|
274
|
+
stop = nil
|
275
|
+
|
276
|
+
5.times {|i| threads << Thread.new {@pool.hold {|c| cc[i] = c; while !stop;sleep 0.01;end}}; sleep 0.01}
|
277
|
+
sleep 0.02
|
278
|
+
threads.each {|t| t.should be_alive}
|
279
|
+
@pool.available_connections.should be_empty
|
280
|
+
|
281
|
+
3.times {|i| threads << Thread.new {@pool.hold {|c| cc[i + 5] = c}}}
|
282
|
+
|
283
|
+
sleep 0.02
|
284
|
+
threads[5].should be_alive
|
285
|
+
threads[6].should be_alive
|
286
|
+
threads[7].should be_alive
|
287
|
+
cc.size.should == 5
|
288
|
+
cc[5].should be_nil
|
289
|
+
cc[6].should be_nil
|
290
|
+
cc[7].should be_nil
|
291
|
+
|
292
|
+
stop = true
|
293
|
+
sleep 0.05
|
294
|
+
|
295
|
+
threads.each {|t| t.should_not be_alive}
|
296
|
+
|
297
|
+
@pool.size.should == 5
|
298
|
+
@invoked_count.should == 5
|
299
|
+
@pool.available_connections.size.should == 5
|
300
|
+
@pool.allocated.should be_empty
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
context "Threaded Unsharded Connection Pool" do
|
305
|
+
before do
|
306
|
+
@invoked_count = 0
|
307
|
+
@pool = Sequel::ConnectionPool.get_pool(CONNECTION_POOL_DEFAULTS.merge(:max_connections=>5)) {@invoked_count += 1}
|
308
|
+
end
|
309
|
+
|
310
|
+
it_should_behave_like "A threaded connection pool"
|
311
|
+
end
|
312
|
+
|
313
|
+
context "Threaded Sharded Connection Pool" do
|
314
|
+
before do
|
315
|
+
@invoked_count = 0
|
316
|
+
@pool = Sequel::ConnectionPool.get_pool(CONNECTION_POOL_DEFAULTS.merge(:max_connections=>5, :servers=>{})) {@invoked_count += 1}
|
317
|
+
end
|
318
|
+
|
319
|
+
it_should_behave_like "A threaded connection pool"
|
320
|
+
end
|
321
|
+
|
322
|
+
context "ConnectionPool#disconnect" do
|
323
|
+
before do
|
324
|
+
@count = 0
|
325
|
+
@pool = Sequel::ConnectionPool.get_pool(CONNECTION_POOL_DEFAULTS.merge(:max_connections=>5, :servers=>{})) {{:id => @count += 1}}
|
326
|
+
end
|
327
|
+
|
328
|
+
specify "should invoke the given block for each available connection" do
|
329
|
+
threads = []
|
330
|
+
stop = nil
|
331
|
+
5.times {|i| threads << Thread.new {@pool.hold {|c| while !stop;sleep 0.01;end}}; sleep 0.01}
|
332
|
+
while @pool.size < 5
|
333
|
+
sleep 0.02
|
334
|
+
end
|
335
|
+
stop = true
|
336
|
+
sleep 0.1
|
337
|
+
threads.each {|t| t.join}
|
338
|
+
|
339
|
+
@pool.size.should == 5
|
340
|
+
@pool.available_connections.size.should == 5
|
341
|
+
@pool.available_connections.each {|c| c[:id].should_not be_nil}
|
342
|
+
conns = []
|
343
|
+
@pool.disconnect {|c| conns << c}
|
344
|
+
conns.size.should == 5
|
345
|
+
end
|
346
|
+
|
347
|
+
specify "should remove all available connections" do
|
348
|
+
threads = []
|
349
|
+
stop = nil
|
350
|
+
5.times {|i| threads << Thread.new {@pool.hold {|c| while !stop;sleep 0.01;end}}; sleep 0.01}
|
351
|
+
while @pool.size < 5
|
352
|
+
sleep 0.02
|
353
|
+
end
|
354
|
+
stop = true
|
355
|
+
sleep 0.1
|
356
|
+
threads.each {|t| t.join}
|
357
|
+
|
358
|
+
@pool.size.should == 5
|
359
|
+
@pool.disconnect
|
360
|
+
@pool.size.should == 0
|
361
|
+
end
|
362
|
+
|
363
|
+
specify "should disconnect connections in use as soon as they are no longer in use" do
|
364
|
+
threads = []
|
365
|
+
stop = nil
|
366
|
+
5.times {|i| threads << Thread.new {@pool.hold {|c| while !stop;sleep 0.01;end}}; sleep 0.01}
|
367
|
+
while @pool.size < 5
|
368
|
+
sleep 0.02
|
369
|
+
end
|
370
|
+
stop = true
|
371
|
+
sleep 0.1
|
372
|
+
threads.each {|t| t.join}
|
373
|
+
|
374
|
+
@pool.size.should == 5
|
375
|
+
|
376
|
+
@pool.hold do |conn|
|
377
|
+
@pool.available_connections.size.should == 4
|
378
|
+
@pool.available_connections.each {|c| c.should_not be(conn)}
|
379
|
+
conns = []
|
380
|
+
@pool.disconnect {|c| conns << c}
|
381
|
+
conns.size.should == 4
|
382
|
+
@pool.size.should == 1
|
383
|
+
end
|
384
|
+
@pool.size.should == 0
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
context "A connection pool with multiple servers" do
|
389
|
+
before do
|
390
|
+
@invoked_counts = Hash.new(0)
|
391
|
+
@pool = Sequel::ConnectionPool.get_pool(CONNECTION_POOL_DEFAULTS.merge(:servers=>{:read_only=>{}})){|server| "#{server}#{@invoked_counts[server] += 1}"}
|
392
|
+
end
|
393
|
+
|
394
|
+
specify "#servers should return symbols for all servers" do
|
395
|
+
@pool.servers.sort_by{|s| s.to_s}.should == [:default, :read_only]
|
396
|
+
end
|
397
|
+
|
398
|
+
specify "should use the :default server by default" do
|
399
|
+
@pool.size.should == 0
|
400
|
+
@pool.hold do |c|
|
401
|
+
c.should == "default1"
|
402
|
+
@pool.allocated.should == {Thread.current=>"default1"}
|
403
|
+
end
|
404
|
+
@pool.available_connections.should == ["default1"]
|
405
|
+
@pool.size.should == 1
|
406
|
+
@invoked_counts.should == {:default=>1}
|
407
|
+
end
|
408
|
+
|
409
|
+
specify "should use the :default server an invalid server is used" do
|
410
|
+
@pool.hold do |c1|
|
411
|
+
c1.should == "default1"
|
412
|
+
@pool.hold(:blah) do |c2|
|
413
|
+
c2.should == c1
|
414
|
+
@pool.hold(:blah2) do |c3|
|
415
|
+
c2.should == c3
|
416
|
+
end
|
417
|
+
end
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
specify "should use the requested server if server is given" do
|
422
|
+
@pool.size(:read_only).should == 0
|
423
|
+
@pool.hold(:read_only) do |c|
|
424
|
+
c.should == "read_only1"
|
425
|
+
@pool.allocated(:read_only).should == {Thread.current=>"read_only1"}
|
426
|
+
end
|
427
|
+
@pool.available_connections(:read_only).should == ["read_only1"]
|
428
|
+
@pool.size(:read_only).should == 1
|
429
|
+
@invoked_counts.should == {:read_only=>1}
|
430
|
+
end
|
431
|
+
|
432
|
+
specify "#hold should only yield connections for the server requested" do
|
433
|
+
@pool.hold(:read_only) do |c|
|
434
|
+
c.should == "read_only1"
|
435
|
+
@pool.allocated(:read_only).should == {Thread.current=>"read_only1"}
|
436
|
+
@pool.hold do |d|
|
437
|
+
d.should == "default1"
|
438
|
+
@pool.hold do |e|
|
439
|
+
e.should == d
|
440
|
+
@pool.hold(:read_only){|b| b.should == c}
|
441
|
+
end
|
442
|
+
@pool.allocated.should == {Thread.current=>"default1"}
|
443
|
+
end
|
444
|
+
end
|
445
|
+
@invoked_counts.should == {:read_only=>1, :default=>1}
|
446
|
+
end
|
447
|
+
|
448
|
+
specify "#disconnect should disconnect from all servers" do
|
449
|
+
@pool.hold(:read_only){}
|
450
|
+
@pool.hold{}
|
451
|
+
conns = []
|
452
|
+
@pool.size.should == 1
|
453
|
+
@pool.size(:read_only).should == 1
|
454
|
+
@pool.disconnect{|c| conns << c}
|
455
|
+
conns.sort.should == %w'default1 read_only1'
|
456
|
+
@pool.size.should == 0
|
457
|
+
@pool.size(:read_only).should == 0
|
458
|
+
@pool.hold(:read_only){|c| c.should == 'read_only2'}
|
459
|
+
@pool.hold{|c| c.should == 'default2'}
|
460
|
+
end
|
461
|
+
|
462
|
+
specify "#add_servers should add new servers to the pool" do
|
463
|
+
pool = Sequel::ConnectionPool.get_pool(:servers=>{:server1=>{}}){|s| s}
|
464
|
+
|
465
|
+
pool.hold{}
|
466
|
+
pool.hold(:server2){}
|
467
|
+
pool.hold(:server3){}
|
468
|
+
pool.hold(:server1) do
|
469
|
+
pool.allocated.length.should == 0
|
470
|
+
pool.allocated(:server1).length.should == 1
|
471
|
+
pool.allocated(:server2).should == nil
|
472
|
+
pool.allocated(:server3).should == nil
|
473
|
+
pool.available_connections.length.should == 1
|
474
|
+
pool.available_connections(:server1).length.should == 0
|
475
|
+
pool.available_connections(:server2).should == nil
|
476
|
+
pool.available_connections(:server3).should == nil
|
477
|
+
|
478
|
+
pool.add_servers([:server2, :server3])
|
479
|
+
pool.hold(:server2){}
|
480
|
+
pool.hold(:server3) do
|
481
|
+
pool.allocated.length.should == 0
|
482
|
+
pool.allocated(:server1).length.should == 1
|
483
|
+
pool.allocated(:server2).length.should == 0
|
484
|
+
pool.allocated(:server3).length.should == 1
|
485
|
+
pool.available_connections.length.should == 1
|
486
|
+
pool.available_connections(:server1).length.should == 0
|
487
|
+
pool.available_connections(:server2).length.should == 1
|
488
|
+
pool.available_connections(:server3).length.should == 0
|
489
|
+
end
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
specify "#add_servers should ignore existing keys" do
|
494
|
+
pool = Sequel::ConnectionPool.get_pool(:servers=>{:server1=>{}}){|s| s}
|
495
|
+
|
496
|
+
pool.allocated.length.should == 0
|
497
|
+
pool.allocated(:server1).length.should == 0
|
498
|
+
pool.available_connections.length.should == 0
|
499
|
+
pool.available_connections(:server1).length.should == 0
|
500
|
+
pool.hold do |c1|
|
501
|
+
c1.should == :default
|
502
|
+
pool.allocated.length.should == 1
|
503
|
+
pool.allocated(:server1).length.should == 0
|
504
|
+
pool.available_connections.length.should == 0
|
505
|
+
pool.available_connections(:server1).length.should == 0
|
506
|
+
pool.hold(:server1) do |c2|
|
507
|
+
c2.should == :server1
|
508
|
+
pool.allocated.length.should == 1
|
509
|
+
pool.allocated(:server1).length.should == 1
|
510
|
+
pool.available_connections.length.should == 0
|
511
|
+
pool.available_connections(:server1).length.should == 0
|
512
|
+
pool.add_servers([:default, :server1])
|
513
|
+
pool.allocated.length.should == 1
|
514
|
+
pool.allocated(:server1).length.should == 1
|
515
|
+
pool.available_connections.length.should == 0
|
516
|
+
pool.available_connections(:server1).length.should == 0
|
517
|
+
end
|
518
|
+
pool.allocated.length.should == 1
|
519
|
+
pool.allocated(:server1).length.should == 0
|
520
|
+
pool.available_connections.length.should == 0
|
521
|
+
pool.available_connections(:server1).length.should == 1
|
522
|
+
pool.add_servers([:default, :server1])
|
523
|
+
pool.allocated.length.should == 1
|
524
|
+
pool.allocated(:server1).length.should == 0
|
525
|
+
pool.available_connections.length.should == 0
|
526
|
+
pool.available_connections(:server1).length.should == 1
|
527
|
+
end
|
528
|
+
pool.allocated.length.should == 0
|
529
|
+
pool.allocated(:server1).length.should == 0
|
530
|
+
pool.available_connections.length.should == 1
|
531
|
+
pool.available_connections(:server1).length.should == 1
|
532
|
+
pool.add_servers([:default, :server1])
|
533
|
+
pool.allocated.length.should == 0
|
534
|
+
pool.allocated(:server1).length.should == 0
|
535
|
+
pool.available_connections.length.should == 1
|
536
|
+
pool.available_connections(:server1).length.should == 1
|
537
|
+
end
|
538
|
+
|
539
|
+
specify "#remove_servers should disconnect available connections immediately" do
|
540
|
+
pool = Sequel::ConnectionPool.get_pool(:max_connections=>5, :servers=>{:server1=>{}}){|s| s}
|
541
|
+
threads = []
|
542
|
+
stop = nil
|
543
|
+
5.times {|i| threads << Thread.new{pool.hold(:server1){|c| sleep 0.05}}}
|
544
|
+
sleep 0.1
|
545
|
+
threads.each {|t| t.join}
|
546
|
+
|
547
|
+
pool.size(:server1).should == 5
|
548
|
+
pool.remove_servers([:server1])
|
549
|
+
pool.size(:server1).should == 0
|
550
|
+
end
|
551
|
+
|
552
|
+
specify "#remove_servers should disconnect connections in use as soon as they are returned to the pool" do
|
553
|
+
dc = []
|
554
|
+
pool = Sequel::ConnectionPool.get_pool(:servers=>{:server1=>{}}, :disconnection_proc=>proc{|c| dc << c}){|s| s}
|
555
|
+
c1 = nil
|
556
|
+
pool.hold(:server1) do |c|
|
557
|
+
pool.size(:server1).should == 1
|
558
|
+
dc.should == []
|
559
|
+
pool.remove_servers([:server1])
|
560
|
+
pool.size(:server1).should == 0
|
561
|
+
dc.should == []
|
562
|
+
c1 = c
|
563
|
+
end
|
564
|
+
pool.size(:server1).should == 0
|
565
|
+
dc.should == [c1]
|
566
|
+
end
|
567
|
+
|
568
|
+
specify "#remove_servers should remove server related data structures immediately" do
|
569
|
+
pool = Sequel::ConnectionPool.get_pool(:servers=>{:server1=>{}}){|s| s}
|
570
|
+
pool.available_connections(:server1).should == []
|
571
|
+
pool.allocated(:server1).should == {}
|
572
|
+
pool.remove_servers([:server1])
|
573
|
+
pool.available_connections(:server1).should == nil
|
574
|
+
pool.allocated(:server1).should == nil
|
575
|
+
end
|
576
|
+
|
577
|
+
specify "#remove_servers should not allow the removal of the default server" do
|
578
|
+
pool = Sequel::ConnectionPool.get_pool(:servers=>{:server1=>{}}){|s| s}
|
579
|
+
proc{pool.remove_servers([:server1])}.should_not raise_error
|
580
|
+
proc{pool.remove_servers([:default])}.should raise_error(Sequel::Error)
|
581
|
+
end
|
582
|
+
|
583
|
+
specify "#remove_servers should ignore servers that have already been removed" do
|
584
|
+
dc = []
|
585
|
+
pool = Sequel::ConnectionPool.get_pool(:servers=>{:server1=>{}}, :disconnection_proc=>proc{|c| dc << c}){|s| s}
|
586
|
+
c1 = nil
|
587
|
+
pool.hold(:server1) do |c|
|
588
|
+
pool.size(:server1).should == 1
|
589
|
+
dc.should == []
|
590
|
+
pool.remove_servers([:server1])
|
591
|
+
pool.remove_servers([:server1])
|
592
|
+
pool.size(:server1).should == 0
|
593
|
+
dc.should == []
|
594
|
+
c1 = c
|
595
|
+
end
|
596
|
+
pool.size(:server1).should == 0
|
597
|
+
dc.should == [c1]
|
598
|
+
end
|
599
|
+
end
|
600
|
+
|
601
|
+
ST_CONNECTION_POOL_DEFAULTS = CONNECTION_POOL_DEFAULTS.merge(:single_threaded=>true)
|
602
|
+
|
603
|
+
context "SingleConnectionPool" do
|
604
|
+
before do
|
605
|
+
@pool = Sequel::ConnectionPool.get_pool(ST_CONNECTION_POOL_DEFAULTS){1234}
|
606
|
+
end
|
607
|
+
|
608
|
+
specify "should provide a #hold method" do
|
609
|
+
conn = nil
|
610
|
+
@pool.hold{|c| conn = c}
|
611
|
+
conn.should == 1234
|
612
|
+
end
|
613
|
+
|
614
|
+
specify "should provide a #disconnect method" do
|
615
|
+
conn = nil
|
616
|
+
x = nil
|
617
|
+
pool = Sequel::ConnectionPool.get_pool(ST_CONNECTION_POOL_DEFAULTS.merge(:disconnection_proc=>proc{|c| conn = c})){1234}
|
618
|
+
pool.hold{|c| x = c}
|
619
|
+
x.should == 1234
|
620
|
+
pool.disconnect
|
621
|
+
conn.should == 1234
|
622
|
+
end
|
623
|
+
end
|
624
|
+
|
625
|
+
context "A single threaded pool with multiple servers" do
|
626
|
+
before do
|
627
|
+
@max_size=2
|
628
|
+
@pool = Sequel::ConnectionPool.get_pool(ST_CONNECTION_POOL_DEFAULTS.merge(:disconnection_proc=>proc{|c| @max_size=3}, :servers=>{:read_only=>{}})){|server| server}
|
629
|
+
end
|
630
|
+
|
631
|
+
specify "#servers should return symbols for all servers" do
|
632
|
+
@pool.servers.sort_by{|s| s.to_s}.should == [:default, :read_only]
|
633
|
+
end
|
634
|
+
|
635
|
+
specify "#add_servers should add new servers to the pool" do
|
636
|
+
@pool.hold(:blah){|c| c.should == :default}
|
637
|
+
@pool.add_servers([:blah])
|
638
|
+
@pool.hold(:blah){|c| c.should == :blah}
|
639
|
+
end
|
640
|
+
|
641
|
+
specify "#add_servers should ignore keys already existing" do
|
642
|
+
@pool.hold{|c| c.should == :default}
|
643
|
+
@pool.hold(:read_only){|c| c.should == :read_only}
|
644
|
+
@pool.add_servers([:default, :read_only])
|
645
|
+
@pool.conn.should == :default
|
646
|
+
@pool.conn(:read_only).should == :read_only
|
647
|
+
end
|
648
|
+
|
649
|
+
specify "#remove_servers should remove servers from the pool" do
|
650
|
+
@pool.hold(:read_only){|c| c.should == :read_only}
|
651
|
+
@pool.remove_servers([:read_only])
|
652
|
+
@pool.hold(:read_only){|c| c.should == :default}
|
653
|
+
end
|
654
|
+
|
655
|
+
specify "#remove_servers should not allow the removal of the default server" do
|
656
|
+
proc{@pool.remove_servers([:default])}.should raise_error(Sequel::Error)
|
657
|
+
end
|
658
|
+
|
659
|
+
specify "#remove_servers should disconnect connection immediately" do
|
660
|
+
@pool.hold(:read_only){|c| c.should == :read_only}
|
661
|
+
@pool.conn(:read_only).should == :read_only
|
662
|
+
@pool.remove_servers([:read_only])
|
663
|
+
@pool.conn(:read_only).should == nil
|
664
|
+
@pool.hold{}
|
665
|
+
@pool.conn(:read_only).should == :default
|
666
|
+
end
|
667
|
+
|
668
|
+
specify "#remove_servers should ignore keys that do not exist" do
|
669
|
+
proc{@pool.remove_servers([:blah])}.should_not raise_error
|
670
|
+
end
|
671
|
+
|
672
|
+
specify "should use the :default server by default" do
|
673
|
+
@pool.hold{|c| c.should == :default}
|
674
|
+
@pool.conn.should == :default
|
675
|
+
end
|
676
|
+
|
677
|
+
specify "should use the :default server an invalid server is used" do
|
678
|
+
@pool.hold do |c1|
|
679
|
+
c1.should == :default
|
680
|
+
@pool.hold(:blah) do |c2|
|
681
|
+
c2.should == c1
|
682
|
+
@pool.hold(:blah2) do |c3|
|
683
|
+
c2.should == c3
|
684
|
+
end
|
685
|
+
end
|
686
|
+
end
|
687
|
+
end
|
688
|
+
|
689
|
+
specify "should use the requested server if server is given" do
|
690
|
+
@pool.hold(:read_only){|c| c.should == :read_only}
|
691
|
+
@pool.conn(:read_only).should == :read_only
|
692
|
+
end
|
693
|
+
|
694
|
+
specify "#hold should only yield connections for the server requested" do
|
695
|
+
@pool.hold(:read_only) do |c|
|
696
|
+
c.should == :read_only
|
697
|
+
@pool.hold do |d|
|
698
|
+
d.should == :default
|
699
|
+
@pool.hold do |e|
|
700
|
+
e.should == d
|
701
|
+
@pool.hold(:read_only){|b| b.should == c}
|
702
|
+
end
|
703
|
+
end
|
704
|
+
end
|
705
|
+
@pool.conn.should == :default
|
706
|
+
@pool.conn(:read_only).should == :read_only
|
707
|
+
end
|
708
|
+
|
709
|
+
specify "#disconnect should disconnect from all servers" do
|
710
|
+
@pool.hold(:read_only){}
|
711
|
+
@pool.hold{}
|
712
|
+
conns = []
|
713
|
+
@pool.conn.should == :default
|
714
|
+
@pool.conn(:read_only).should == :read_only
|
715
|
+
@pool.disconnect{|c| conns << c}
|
716
|
+
conns.sort_by{|x| x.to_s}.should == [:default, :read_only]
|
717
|
+
@pool.conn.should == nil
|
718
|
+
@pool.conn(:read_only).should == nil
|
719
|
+
end
|
720
|
+
|
721
|
+
specify ":disconnection_proc option should set the disconnection proc to use" do
|
722
|
+
@max_size.should == 2
|
723
|
+
proc{@pool.hold{raise Sequel::DatabaseDisconnectError}}.should raise_error(Sequel::DatabaseDisconnectError)
|
724
|
+
@max_size.should == 3
|
725
|
+
end
|
726
|
+
|
727
|
+
specify "#hold should remove the connection if a DatabaseDisconnectError is raised" do
|
728
|
+
@pool.instance_variable_get(:@conns).length.should == 0
|
729
|
+
@pool.hold{}
|
730
|
+
@pool.instance_variable_get(:@conns).length.should == 1
|
731
|
+
proc{@pool.hold{raise Sequel::DatabaseDisconnectError}}.should raise_error(Sequel::DatabaseDisconnectError)
|
732
|
+
@pool.instance_variable_get(:@conns).length.should == 0
|
733
|
+
end
|
734
|
+
end
|
735
|
+
|
736
|
+
shared_examples_for "All connection pools classes" do
|
737
|
+
specify "should yield a connection created by the initialize block to hold" do
|
738
|
+
x = nil
|
739
|
+
@class.new({}){123}.hold{|c| x = c}
|
740
|
+
x.should == 123
|
741
|
+
end
|
742
|
+
|
743
|
+
specify "should have the initialize block accept a shard/server argument" do
|
744
|
+
x = nil
|
745
|
+
@class.new({}){|c| [c, c]}.hold{|c| x = c}
|
746
|
+
x.should == [:default, :default]
|
747
|
+
end
|
748
|
+
|
749
|
+
specify "should have respect an :after_connect proc that is called with each newly created connection" do
|
750
|
+
x = nil
|
751
|
+
@class.new(:after_connect=>proc{|c| x = [c, c]}){|c| 123}.hold{}
|
752
|
+
x.should == [123, 123]
|
753
|
+
end
|
754
|
+
|
755
|
+
specify "should raise a DatabaseConnectionError if the connection raises an exception" do
|
756
|
+
proc{@class.new({}){|c| raise Exception}.hold{}}.should raise_error(Sequel::DatabaseConnectionError)
|
757
|
+
end
|
758
|
+
|
759
|
+
specify "should raise a DatabaseConnectionError if the initialize block returns nil" do
|
760
|
+
proc{@class.new({}){}.hold{}}.should raise_error(Sequel::DatabaseConnectionError)
|
761
|
+
end
|
762
|
+
|
763
|
+
specify "should call the disconnection_proc option if the hold block raises a DatabaseDisconnectError" do
|
764
|
+
x = nil
|
765
|
+
proc{@class.new(:disconnection_proc=>proc{|c| x = c}){123}.hold{raise Sequel::DatabaseDisconnectError}}.should raise_error(Sequel::DatabaseDisconnectError)
|
766
|
+
x.should == 123
|
767
|
+
end
|
768
|
+
|
769
|
+
specify "should have a disconnect method that calls the :disconnection_proc option with the connection" do
|
770
|
+
x = nil
|
771
|
+
c = @class.new(:disconnection_proc=>proc{|c| x = c}){123}
|
772
|
+
c.hold{}
|
773
|
+
x.should == nil
|
774
|
+
c.disconnect
|
775
|
+
x.should == 123
|
776
|
+
end
|
777
|
+
|
778
|
+
specify "should have a disconnect method that calls the given block with the connection" do
|
779
|
+
x = nil
|
780
|
+
y = nil
|
781
|
+
c = @class.new(:disconnection_proc=>proc{|c| x = c}){123}
|
782
|
+
c.hold{}
|
783
|
+
c.disconnect{|c| y = c}
|
784
|
+
x.should == nil
|
785
|
+
y.should == 123
|
786
|
+
end
|
787
|
+
|
788
|
+
specify "should have a servers method that returns an array of shard/server symbols" do
|
789
|
+
@class.new({}){123}.servers.should == [:default]
|
790
|
+
end
|
791
|
+
|
792
|
+
specify "should have a servers method that returns an array of shard/server symbols" do
|
793
|
+
c = @class.new({}){123}
|
794
|
+
c.size.should == 0
|
795
|
+
c.hold{}
|
796
|
+
c.size.should == 1
|
797
|
+
end
|
798
|
+
end
|
799
|
+
|
800
|
+
Sequel::ConnectionPool::CONNECTION_POOL_MAP.keys.each do |k, v|
|
801
|
+
opts = {:single_threaded=>k, :servers=>(v ? {} : nil)}
|
802
|
+
describe "Connection pool with #{opts.inspect}" do
|
803
|
+
before do
|
804
|
+
@class = Sequel::ConnectionPool.send(:connection_pool_class, opts)
|
805
|
+
end
|
806
|
+
it_should_behave_like "All connection pools classes"
|
807
|
+
end
|
808
|
+
end
|