seamless_database_pool 1.0.17 → 1.0.18
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.travis.yml +5 -0
- data/HISTORY.txt +79 -0
- data/Rakefile +1 -24
- data/VERSION +1 -0
- data/lib/active_record/connection_adapters/seamless_database_pool_adapter.rb +4 -4
- data/seamless_database_pool.gemspec +21 -0
- data/spec/connection_statistics_spec.rb +1 -1
- data/spec/database.yml +1 -0
- data/spec/seamless_database_pool_adapter_spec.rb +70 -68
- data/spec/spec_helper.rb +12 -0
- metadata +26 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 97df06be58768fd03235c0370d3f6e48a997f720
|
4
|
+
data.tar.gz: 4175c26ce145bc7e429f7b996a72fda489450506
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fab0026bafa0d44e418d1522f0d6ee584b9fcaaa01af1fffe2a3388c93ff52b841656e2e68487d7e7b58ae4bfd757a8532d197157f5e7a677400c37d0bf48092
|
7
|
+
data.tar.gz: cdb1f53c64c9798e252ad7016d04d3fc5c771195cba4a6745a7b31eee5fa8d8c68def54dfc94db7b23e6bb83b287d4546423bbd03916374be85f7092bc6c8f87
|
data/.gitignore
ADDED
data/HISTORY.txt
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
1.0.18
|
2
|
+
|
3
|
+
ActiveRecord 5.0 compatibility (thanks jkowens)
|
4
|
+
|
5
|
+
1.0.17
|
6
|
+
|
7
|
+
Do not update the HTTP session if there are no changes.
|
8
|
+
|
9
|
+
1.0.16
|
10
|
+
|
11
|
+
Use shorter to_s output for output on connection.inspect.
|
12
|
+
|
13
|
+
1.0.15
|
14
|
+
|
15
|
+
Implement less wordy connection to string method so logs don't fill up with long messages on connection errors.
|
16
|
+
|
17
|
+
Update specs to remove deprecation warnings
|
18
|
+
|
19
|
+
Fix adapter specs to work with ActiveRecord 4.1 configuration changes
|
20
|
+
|
21
|
+
1.0.14
|
22
|
+
|
23
|
+
Remove custom connection timeout logic; Use the underlying driver's timeouts instead.
|
24
|
+
|
25
|
+
Fix to work with query cache.
|
26
|
+
|
27
|
+
Make driver less aggressive about overriding methods to proxy to the master connection.
|
28
|
+
|
29
|
+
End support for ActiveRecord 2.x
|
30
|
+
|
31
|
+
Add support for ActiveRecord 4.0
|
32
|
+
|
33
|
+
1.0.13
|
34
|
+
|
35
|
+
Fix to work with `rake db:*` Rails tasks by removing the adapter from the configuration when db:* tasks are run.
|
36
|
+
|
37
|
+
Fix connection pool issues so checkout/checkins don't interact with the underlying connections (thanks afex)
|
38
|
+
|
39
|
+
Ruby 2.0/Rails 4.0 compatibility (thanks t27duck)
|
40
|
+
|
41
|
+
1.0.12
|
42
|
+
|
43
|
+
Remove excessively long log messages on reconnect attempts.
|
44
|
+
|
45
|
+
1.0.11
|
46
|
+
|
47
|
+
Remove debug code that prevented recovering from errors.
|
48
|
+
|
49
|
+
1.0.10
|
50
|
+
|
51
|
+
Compatibility with ActiveRecord 3.1.0
|
52
|
+
|
53
|
+
1.0.9
|
54
|
+
|
55
|
+
Compatibility with bind variables.
|
56
|
+
|
57
|
+
1.0.8
|
58
|
+
|
59
|
+
Compatibility with ActiveRecord 3.1.0rc4
|
60
|
+
|
61
|
+
1.0.7
|
62
|
+
|
63
|
+
Make compatible with ActionController 3.0
|
64
|
+
|
65
|
+
Improved handling of down slave instances.
|
66
|
+
|
67
|
+
1.0.6
|
68
|
+
|
69
|
+
Make compatible with ActiveRecord 3.0.
|
70
|
+
|
71
|
+
Make compatible with database adapters other than MySQL including PostgrSQL.
|
72
|
+
|
73
|
+
Better test suite to actually hit three different database adapters.
|
74
|
+
|
75
|
+
1.0.5
|
76
|
+
|
77
|
+
Update docs.
|
78
|
+
|
79
|
+
Remove rake dependency on rspec
|
data/Rakefile
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rake'
|
3
3
|
require 'yaml'
|
4
|
+
require "bundler/gem_tasks"
|
4
5
|
|
5
6
|
desc 'Default: run unit tests.'
|
6
7
|
task :default => :test
|
@@ -59,27 +60,3 @@ rescue LoadError
|
|
59
60
|
STDERR.puts "You must have rspec >= 2.0 to run the tests"
|
60
61
|
end
|
61
62
|
end
|
62
|
-
|
63
|
-
begin
|
64
|
-
require 'jeweler'
|
65
|
-
Jeweler::Tasks.new do |gem|
|
66
|
-
gem.name = "seamless_database_pool"
|
67
|
-
gem.summary = "Add support for master/slave database clusters in ActiveRecord to improve performance."
|
68
|
-
gem.email = "bbdurand@gmail.com"
|
69
|
-
gem.homepage = "http://github.com/bdurand/seamless_database_pool"
|
70
|
-
gem.authors = ["Brian Durand"]
|
71
|
-
gem.files = FileList["lib/**/*", "spec/**/*", "README.rdoc", "Rakefile", "MIT-LICENSE"].to_a
|
72
|
-
gem.has_rdoc = true
|
73
|
-
gem.extra_rdoc_files = ["README.rdoc", "MIT-LICENSE"]
|
74
|
-
|
75
|
-
gem.add_dependency('activerecord', '>= 3.0.20')
|
76
|
-
gem.add_development_dependency('rspec', '>= 2.0')
|
77
|
-
gem.add_development_dependency('jeweler')
|
78
|
-
gem.add_development_dependency('sqlite3')
|
79
|
-
gem.add_development_dependency('mysql')
|
80
|
-
gem.add_development_dependency('pg')
|
81
|
-
end
|
82
|
-
|
83
|
-
Jeweler::GemcutterTasks.new
|
84
|
-
rescue LoadError
|
85
|
-
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.18
|
@@ -35,7 +35,7 @@ module ActiveRecord
|
|
35
35
|
end if config[:read_pool]
|
36
36
|
|
37
37
|
klass = ::ActiveRecord::ConnectionAdapters::SeamlessDatabasePoolAdapter.adapter_class(master_connection)
|
38
|
-
klass.new(nil, logger, master_connection, read_connections, pool_weights)
|
38
|
+
klass.new(nil, logger, master_connection, read_connections, pool_weights, config)
|
39
39
|
end
|
40
40
|
|
41
41
|
def establish_adapter(adapter)
|
@@ -153,12 +153,12 @@ module ActiveRecord
|
|
153
153
|
end
|
154
154
|
end
|
155
155
|
|
156
|
-
def initialize(connection, logger, master_connection, read_connections, pool_weights)
|
156
|
+
def initialize(connection, logger, master_connection, read_connections, pool_weights, config)
|
157
157
|
@master_connection = master_connection
|
158
158
|
@read_connections = read_connections.dup.freeze
|
159
159
|
|
160
|
-
super(connection, logger)
|
161
|
-
|
160
|
+
super(connection, logger, config)
|
161
|
+
|
162
162
|
@weighted_read_connections = []
|
163
163
|
pool_weights.each_pair do |conn, weight|
|
164
164
|
weight.times{@weighted_read_connections << conn}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
Gem::Specification.new do |spec|
|
2
|
+
spec.name = "seamless_database_pool"
|
3
|
+
spec.version = File.read(File.expand_path("../VERSION", __FILE__)).chomp
|
4
|
+
spec.authors = ["Brian Durand"]
|
5
|
+
spec.email = ["bbdurand@gmail.com"]
|
6
|
+
spec.description = %q{Add support for master/slave database database clusters in ActiveRecord to improve performance.}
|
7
|
+
spec.summary = %q{Add support for master/slave database clusters in ActiveRecord to improve performance.}
|
8
|
+
spec.homepage = "https://github.com/bdurand/seamless_database_pool"
|
9
|
+
spec.license = "MIT"
|
10
|
+
|
11
|
+
spec.files = `git ls-files`.split($/)
|
12
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
13
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
14
|
+
spec.require_paths = ["lib"]
|
15
|
+
|
16
|
+
spec.add_runtime_dependency(%q<activerecord>, [">= 3.0.20"])
|
17
|
+
spec.add_development_dependency(%q<rspec>, [">= 2.0"])
|
18
|
+
spec.add_development_dependency(%q<sqlite3>, [">= 0"])
|
19
|
+
spec.add_development_dependency(%q<mysql>, [">= 0"])
|
20
|
+
spec.add_development_dependency(%q<pg>, [">= 0"])
|
21
|
+
end
|
@@ -61,7 +61,7 @@ describe SeamlessDatabasePool::ConnectionStatistics do
|
|
61
61
|
|
62
62
|
it "should increment counts only once within a block" do
|
63
63
|
connection = SeamlessDatabasePool::ConnectionStatisticsTester.new
|
64
|
-
connection.
|
64
|
+
expect(connection).to receive(:execute).with('SQL')
|
65
65
|
connection.update('SQL')
|
66
66
|
connection.connection_statistics.should == {:update => 1}
|
67
67
|
end
|
data/spec/database.yml
CHANGED
@@ -58,16 +58,16 @@ describe "SeamlessDatabasePoolAdapter ActiveRecord::Base extension" do
|
|
58
58
|
logger = ActiveRecord::Base.logger
|
59
59
|
weights = {master_connection => 1, read_connection_1 => 1, read_connection_2 => 2}
|
60
60
|
|
61
|
-
ActiveRecord::Base.
|
62
|
-
ActiveRecord::Base.
|
63
|
-
ActiveRecord::Base.
|
61
|
+
expect(ActiveRecord::Base).to receive(:writer_connection).with('adapter' => 'writer', 'host' => 'master_host', 'username' => 'user', 'pool_weight' => 1).and_return(master_connection)
|
62
|
+
expect(ActiveRecord::Base).to receive(:reader_connection).with('adapter' => 'reader', 'host' => 'read_host_1', 'username' => 'user', 'pool_weight' => 1).and_return(read_connection_1)
|
63
|
+
expect(ActiveRecord::Base).to receive(:reader_connection).with('adapter' => 'reader', 'host' => 'read_host_2', 'username' => 'user', 'pool_weight' => 2).and_return(read_connection_2)
|
64
64
|
|
65
65
|
klass = double(:class)
|
66
|
-
ActiveRecord::ConnectionAdapters::SeamlessDatabasePoolAdapter.
|
67
|
-
klass.
|
66
|
+
expect(ActiveRecord::ConnectionAdapters::SeamlessDatabasePoolAdapter).to receive(:adapter_class).with(master_connection).and_return(klass)
|
67
|
+
expect(klass).to receive(:new).with(nil, logger, master_connection, [read_connection_1, read_connection_2], weights, options).and_return(pool_connection)
|
68
68
|
|
69
|
-
ActiveRecord::Base.
|
70
|
-
ActiveRecord::Base.
|
69
|
+
expect(ActiveRecord::Base).to receive(:establish_adapter).with('writer')
|
70
|
+
expect(ActiveRecord::Base).to receive(:establish_adapter).with('reader').twice
|
71
71
|
|
72
72
|
ActiveRecord::Base.seamless_database_pool_connection(options).should == pool_connection
|
73
73
|
end
|
@@ -82,10 +82,11 @@ describe "SeamlessDatabasePoolAdapter" do
|
|
82
82
|
let(:master_connection){ SeamlessDatabasePool::MockMasterConnection.new("master") }
|
83
83
|
let(:read_connection_1){ SeamlessDatabasePool::MockConnection.new("read_1") }
|
84
84
|
let(:read_connection_2){ SeamlessDatabasePool::MockConnection.new("read_2") }
|
85
|
+
let(:config){ {} }
|
85
86
|
let(:pool_connection) do
|
86
87
|
weights = {master_connection => 1, read_connection_1 => 1, read_connection_2 => 2}
|
87
88
|
connection_class = ActiveRecord::ConnectionAdapters::SeamlessDatabasePoolAdapter.adapter_class(master_connection)
|
88
|
-
connection_class.new(nil, nil, master_connection, [read_connection_1, read_connection_2], weights)
|
89
|
+
connection_class.new(nil, nil, master_connection, [read_connection_1, read_connection_2], weights, config)
|
89
90
|
end
|
90
91
|
|
91
92
|
it "should be able to be converted to a string" do
|
@@ -104,26 +105,26 @@ describe "SeamlessDatabasePoolAdapter" do
|
|
104
105
|
end
|
105
106
|
|
106
107
|
it "should return the current read connection" do
|
107
|
-
SeamlessDatabasePool.
|
108
|
+
expect(SeamlessDatabasePool).to receive(:read_only_connection).with(pool_connection).and_return(:current)
|
108
109
|
pool_connection.current_read_connection.should == :current
|
109
110
|
end
|
110
111
|
|
111
112
|
it "should select a random read connection" do
|
112
113
|
mock_connection = double(:connection)
|
113
114
|
mock_connection.stub(:active? => true)
|
114
|
-
pool_connection.
|
115
|
-
pool_connection.
|
115
|
+
expect(pool_connection).to receive(:available_read_connections).and_return([:fake1, :fake2, mock_connection])
|
116
|
+
expect(pool_connection).to receive(:rand).with(3).and_return(2)
|
116
117
|
pool_connection.random_read_connection.should == mock_connection
|
117
118
|
end
|
118
119
|
|
119
120
|
it "should select the master connection if the read pool is empty" do
|
120
|
-
pool_connection.
|
121
|
+
expect(pool_connection).to receive(:available_read_connections).and_return([])
|
121
122
|
pool_connection.random_read_connection.should == master_connection
|
122
123
|
end
|
123
124
|
|
124
125
|
it "should use the master connection in a block" do
|
125
126
|
connection_class = ActiveRecord::ConnectionAdapters::SeamlessDatabasePoolAdapter.adapter_class(master_connection)
|
126
|
-
connection = connection_class.new(nil, double(:logger), master_connection, [read_connection_1], {read_connection_1 => 1})
|
127
|
+
connection = connection_class.new(nil, double(:logger), master_connection, [read_connection_1], {read_connection_1 => 1}, config)
|
127
128
|
connection.random_read_connection.should == read_connection_1
|
128
129
|
connection.use_master_connection do
|
129
130
|
connection.random_read_connection.should == master_connection
|
@@ -133,12 +134,12 @@ describe "SeamlessDatabasePoolAdapter" do
|
|
133
134
|
|
134
135
|
it "should use the master connection inside a transaction" do
|
135
136
|
connection_class = ActiveRecord::ConnectionAdapters::SeamlessDatabasePoolAdapter.adapter_class(master_connection)
|
136
|
-
connection = connection_class.new(nil, double(:logger), master_connection, [read_connection_1], {read_connection_1 => 1})
|
137
|
-
master_connection.
|
138
|
-
master_connection.
|
139
|
-
master_connection.
|
140
|
-
read_connection_1.
|
141
|
-
read_connection_1.
|
137
|
+
connection = connection_class.new(nil, double(:logger), master_connection, [read_connection_1], {read_connection_1 => 1}, config)
|
138
|
+
expect(master_connection).to receive(:begin_db_transaction)
|
139
|
+
expect(master_connection).to receive(:commit_db_transaction)
|
140
|
+
expect(master_connection).to receive(:select).with('Transaction SQL', nil)
|
141
|
+
expect(read_connection_1).to receive(:select).with('SQL 1', nil)
|
142
|
+
expect(read_connection_1).to receive(:select).with('SQL 2', nil)
|
142
143
|
|
143
144
|
SeamlessDatabasePool.use_persistent_read_connection do
|
144
145
|
connection.send(:select, 'SQL 1', nil)
|
@@ -152,81 +153,81 @@ describe "SeamlessDatabasePoolAdapter" do
|
|
152
153
|
|
153
154
|
context "read connection methods" do
|
154
155
|
it "should proxy select methods to a read connection" do
|
155
|
-
pool_connection.
|
156
|
-
read_connection_1.
|
156
|
+
expect(pool_connection).to receive(:current_read_connection).and_return(read_connection_1)
|
157
|
+
expect(read_connection_1).to receive(:select).with('SQL').and_return(:retval)
|
157
158
|
pool_connection.send(:select, 'SQL').should == :retval
|
158
159
|
end
|
159
160
|
|
160
161
|
it "should proxy execute methods to a read connection" do
|
161
|
-
pool_connection.
|
162
|
-
read_connection_1.
|
162
|
+
expect(pool_connection).to receive(:current_read_connection).and_return(read_connection_1)
|
163
|
+
expect(read_connection_1).to receive(:execute).with('SQL').and_return(:retval)
|
163
164
|
pool_connection.execute('SQL').should == :retval
|
164
165
|
end
|
165
166
|
|
166
167
|
it "should proxy select_rows methods to a read connection" do
|
167
|
-
pool_connection.
|
168
|
-
read_connection_1.
|
168
|
+
expect(pool_connection).to receive(:current_read_connection).and_return(read_connection_1)
|
169
|
+
expect(read_connection_1).to receive(:select_rows).with('SQL').and_return(:retval)
|
169
170
|
pool_connection.select_rows('SQL').should == :retval
|
170
171
|
end
|
171
172
|
end
|
172
173
|
|
173
174
|
context "master connection methods" do
|
174
175
|
it "should proxy insert method to the master connection" do
|
175
|
-
master_connection.
|
176
|
+
expect(master_connection).to receive(:insert).with('SQL').and_return(:retval)
|
176
177
|
pool_connection.insert('SQL').should == :retval
|
177
178
|
end
|
178
179
|
|
179
180
|
it "should proxy update method to the master connection" do
|
180
|
-
master_connection.
|
181
|
+
expect(master_connection).to receive(:update).with('SQL').and_return(:retval)
|
181
182
|
pool_connection.update('SQL').should == :retval
|
182
183
|
end
|
183
184
|
|
184
185
|
it "should proxy columns method to the master connection" do
|
185
|
-
master_connection.
|
186
|
+
expect(master_connection).to receive(:columns).with(:table).and_return(:retval)
|
186
187
|
pool_connection.columns(:table).should == :retval
|
187
188
|
end
|
188
189
|
end
|
189
190
|
|
190
191
|
context "fork to all connections" do
|
191
192
|
it "should fork active? to all connections and return true if all are up" do
|
192
|
-
master_connection.
|
193
|
-
read_connection_1.
|
194
|
-
read_connection_2.
|
193
|
+
expect(master_connection).to receive(:active?).and_return(true)
|
194
|
+
expect(read_connection_1).to receive(:active?).and_return(true)
|
195
|
+
expect(read_connection_2).to receive(:active?).and_return(true)
|
195
196
|
pool_connection.active?.should == true
|
196
197
|
end
|
197
198
|
|
198
199
|
it "should fork active? to all connections and return false if one is down" do
|
199
|
-
master_connection.
|
200
|
-
read_connection_1.
|
201
|
-
read_connection_2.
|
200
|
+
expect(master_connection).to receive(:active?).and_return(true)
|
201
|
+
expect(read_connection_1).to receive(:active?).and_return(true)
|
202
|
+
expect(read_connection_2).to receive(:active?).and_return(false)
|
202
203
|
pool_connection.active?.should == false
|
203
204
|
end
|
204
205
|
|
205
206
|
it "should fork verify! to all connections" do
|
206
|
-
master_connection.
|
207
|
-
read_connection_1.
|
208
|
-
read_connection_2.
|
207
|
+
expect(master_connection).to receive(:verify!).with(5)
|
208
|
+
expect(read_connection_1).to receive(:verify!).with(5)
|
209
|
+
expect(read_connection_2).to receive(:verify!).with(5)
|
209
210
|
pool_connection.verify!(5)
|
210
211
|
end
|
211
212
|
|
212
213
|
it "should fork disconnect! to all connections" do
|
213
|
-
master_connection.
|
214
|
-
read_connection_1.
|
215
|
-
read_connection_2.
|
214
|
+
expect(master_connection).to receive(:disconnect!)
|
215
|
+
expect(read_connection_1).to receive(:disconnect!)
|
216
|
+
expect(read_connection_2).to receive(:disconnect!)
|
216
217
|
pool_connection.disconnect!
|
217
218
|
end
|
218
219
|
|
219
220
|
it "should fork reconnect! to all connections" do
|
220
|
-
master_connection.
|
221
|
-
read_connection_1.
|
222
|
-
read_connection_2.
|
221
|
+
expect(master_connection).to receive(:reconnect!)
|
222
|
+
expect(read_connection_1).to receive(:reconnect!)
|
223
|
+
expect(read_connection_2).to receive(:reconnect!)
|
223
224
|
pool_connection.reconnect!
|
224
225
|
end
|
225
226
|
|
226
227
|
it "should fork reset_runtime to all connections" do
|
227
|
-
master_connection.
|
228
|
-
read_connection_1.
|
229
|
-
read_connection_2.
|
228
|
+
expect(master_connection).to receive(:reset_runtime).and_return(1)
|
229
|
+
expect(read_connection_1).to receive(:reset_runtime).and_return(2)
|
230
|
+
expect(read_connection_2).to receive(:reset_runtime).and_return(3)
|
230
231
|
pool_connection.reset_runtime.should == 6
|
231
232
|
end
|
232
233
|
end
|
@@ -235,16 +236,17 @@ describe "SeamlessDatabasePoolAdapter" do
|
|
235
236
|
it "should proxy requests to a connection" do
|
236
237
|
args = [:arg1, :arg2]
|
237
238
|
block = Proc.new{}
|
238
|
-
master_connection.
|
239
|
+
expect(master_connection).to receive(:select_value).with(*args, &block)
|
239
240
|
master_connection.should_not_receive(:active?)
|
240
241
|
master_connection.should_not_receive(:reconnect!)
|
241
242
|
pool_connection.send(:proxy_connection_method, master_connection, :select_value, :master, *args, &block)
|
242
243
|
end
|
243
244
|
|
244
245
|
it "should try to reconnect dead connections when they become available again" do
|
245
|
-
master_connection.stub(:select).and_raise("SQL ERROR")
|
246
|
-
master_connection.
|
247
|
-
master_connection.
|
246
|
+
master_connection.stub(:select).and_raise("SQL ERROR") # Rails 3, 4
|
247
|
+
master_connection.stub(:select_rows).and_raise("SQL ERROR") # Rails 5
|
248
|
+
expect(master_connection).to receive(:active?).and_return(false, false, true)
|
249
|
+
expect(master_connection).to receive(:reconnect!)
|
248
250
|
now = Time.now
|
249
251
|
lambda{pool_connection.select_value("SQL")}.should raise_error("SQL ERROR")
|
250
252
|
Time.stub(:now => now + 31)
|
@@ -254,8 +256,8 @@ describe "SeamlessDatabasePoolAdapter" do
|
|
254
256
|
it "should not try to reconnect live connections" do
|
255
257
|
args = [:arg1, :arg2]
|
256
258
|
block = Proc.new{}
|
257
|
-
master_connection.
|
258
|
-
master_connection.
|
259
|
+
expect(master_connection).to receive(:select).with(*args, &block).twice.and_raise("SQL ERROR")
|
260
|
+
expect(master_connection).to receive(:active?).and_return(true)
|
259
261
|
master_connection.should_not_receive(:reconnect!)
|
260
262
|
lambda{pool_connection.send(:proxy_connection_method, master_connection, :select, :read, *args, &block)}.should raise_error("SQL ERROR")
|
261
263
|
end
|
@@ -263,7 +265,7 @@ describe "SeamlessDatabasePoolAdapter" do
|
|
263
265
|
it "should not try to reconnect a connection during a retry" do
|
264
266
|
args = [:arg1, :arg2]
|
265
267
|
block = Proc.new{}
|
266
|
-
master_connection.
|
268
|
+
expect(master_connection).to receive(:select).with(*args, &block).and_raise("SQL ERROR")
|
267
269
|
master_connection.should_not_receive(:active?)
|
268
270
|
master_connection.should_not_receive(:reconnect!)
|
269
271
|
lambda{pool_connection.send(:proxy_connection_method, master_connection, :select, :retry, *args, &block)}.should raise_error("SQL ERROR")
|
@@ -271,35 +273,35 @@ describe "SeamlessDatabasePoolAdapter" do
|
|
271
273
|
|
272
274
|
it "should try to execute a read statement again after a connection error" do
|
273
275
|
connection_error = ActiveRecord::ConnectionAdapters::SeamlessDatabasePoolAdapter::DatabaseConnectionError.new
|
274
|
-
pool_connection.
|
275
|
-
read_connection_1.
|
276
|
-
read_connection_1.
|
276
|
+
expect(pool_connection).to receive(:current_read_connection).and_return(read_connection_1)
|
277
|
+
expect(read_connection_1).to receive(:select).with('SQL').and_raise(connection_error)
|
278
|
+
expect(read_connection_1).to receive(:active?).and_return(true)
|
277
279
|
pool_connection.should_not_receive(:suppress_read_connection)
|
278
280
|
SeamlessDatabasePool.should_not_receive(:set_persistent_read_connection)
|
279
|
-
read_connection_1.
|
281
|
+
expect(read_connection_1).to receive(:select).with('SQL').and_return(:results)
|
280
282
|
pool_connection.send(:select, 'SQL').should == :results
|
281
283
|
end
|
282
284
|
|
283
285
|
it "should not try to execute a read statement again after a connection error if the master connection must be used" do
|
284
|
-
master_connection.
|
286
|
+
expect(master_connection).to receive(:select).with('SQL').and_raise("Fail")
|
285
287
|
pool_connection.use_master_connection do
|
286
288
|
lambda{pool_connection.send(:select, 'SQL')}.should raise_error("Fail")
|
287
289
|
end
|
288
290
|
end
|
289
291
|
|
290
292
|
it "should not try to execute a read statement again after a non-connection error" do
|
291
|
-
pool_connection.
|
292
|
-
pool_connection.
|
293
|
+
expect(pool_connection).to receive(:current_read_connection).and_return(read_connection_1)
|
294
|
+
expect(pool_connection).to receive(:proxy_connection_method).with(read_connection_1, :select, :read, 'SQL').and_raise("SQL Error")
|
293
295
|
lambda{pool_connection.send(:select, 'SQL')}.should raise_error("SQL Error")
|
294
296
|
end
|
295
297
|
|
296
298
|
it "should use a different connection on a retry if the original connection could not be reconnected" do
|
297
|
-
pool_connection.
|
298
|
-
read_connection_1.
|
299
|
-
read_connection_1.
|
300
|
-
pool_connection.
|
301
|
-
SeamlessDatabasePool.
|
302
|
-
read_connection_2.
|
299
|
+
expect(pool_connection).to receive(:current_read_connection).and_return(read_connection_1, read_connection_2)
|
300
|
+
expect(read_connection_1).to receive(:select).with('SQL').and_raise("Fail")
|
301
|
+
expect(read_connection_1).to receive(:active?).and_return(false)
|
302
|
+
expect(pool_connection).to receive(:suppress_read_connection).with(read_connection_1, 30)
|
303
|
+
expect(SeamlessDatabasePool).to receive(:set_persistent_read_connection).with(pool_connection, read_connection_2)
|
304
|
+
expect(read_connection_2).to receive(:select).with('SQL').and_return(:results)
|
303
305
|
pool_connection.send(:select, 'SQL').should == :results
|
304
306
|
end
|
305
307
|
|
@@ -322,8 +324,8 @@ describe "SeamlessDatabasePoolAdapter" do
|
|
322
324
|
pool_connection.suppress_read_connection(read_connection_1, 0.2)
|
323
325
|
pool_connection.available_read_connections.should_not include(read_connection_1)
|
324
326
|
sleep(0.3)
|
325
|
-
read_connection_1.
|
326
|
-
read_connection_1.
|
327
|
+
expect(read_connection_1).to receive(:reconnect!)
|
328
|
+
expect(read_connection_1).to receive(:active?).and_return(false)
|
327
329
|
pool_connection.available_read_connections.should_not include(read_connection_1)
|
328
330
|
end
|
329
331
|
|
data/spec/spec_helper.rb
CHANGED
@@ -11,3 +11,15 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'seamles
|
|
11
11
|
require File.expand_path(File.join(File.dirname(__FILE__), 'test_model'))
|
12
12
|
|
13
13
|
$LOAD_PATH << File.expand_path("../test_adapter", __FILE__)
|
14
|
+
|
15
|
+
RSpec.configure do |config|
|
16
|
+
config.run_all_when_everything_filtered = true
|
17
|
+
config.filter_run :focus
|
18
|
+
|
19
|
+
# Run specs in random order to surface order dependencies. If you find an
|
20
|
+
# order dependency and want to debug it, you can fix the order by providing
|
21
|
+
# the seed, which is printed after each run.
|
22
|
+
# --seed 1234
|
23
|
+
config.order = 'random'
|
24
|
+
config.expect_with(:rspec) { |c| c.syntax = [:should, :expect] }
|
25
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: seamless_database_pool
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.18
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Durand
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-05-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -38,20 +38,6 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '2.0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: jeweler
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - ">="
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
42
|
name: sqlite3
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -94,23 +80,28 @@ dependencies:
|
|
94
80
|
- - ">="
|
95
81
|
- !ruby/object:Gem::Version
|
96
82
|
version: '0'
|
97
|
-
description:
|
98
|
-
|
83
|
+
description: Add support for master/slave database database clusters in ActiveRecord
|
84
|
+
to improve performance.
|
85
|
+
email:
|
86
|
+
- bbdurand@gmail.com
|
99
87
|
executables: []
|
100
88
|
extensions: []
|
101
|
-
extra_rdoc_files:
|
102
|
-
- MIT-LICENSE
|
103
|
-
- README.rdoc
|
89
|
+
extra_rdoc_files: []
|
104
90
|
files:
|
91
|
+
- ".gitignore"
|
92
|
+
- ".travis.yml"
|
93
|
+
- HISTORY.txt
|
105
94
|
- MIT-LICENSE
|
106
95
|
- README.rdoc
|
107
96
|
- Rakefile
|
97
|
+
- VERSION
|
108
98
|
- lib/active_record/connection_adapters/seamless_database_pool_adapter.rb
|
109
99
|
- lib/seamless_database_pool.rb
|
110
100
|
- lib/seamless_database_pool/arel_compiler.rb
|
111
101
|
- lib/seamless_database_pool/connection_statistics.rb
|
112
102
|
- lib/seamless_database_pool/controller_filter.rb
|
113
103
|
- lib/seamless_database_pool/railtie.rb
|
104
|
+
- seamless_database_pool.gemspec
|
114
105
|
- spec/connection_adapters_spec.rb
|
115
106
|
- spec/connection_statistics_spec.rb
|
116
107
|
- spec/controller_filter_spec.rb
|
@@ -120,8 +111,9 @@ files:
|
|
120
111
|
- spec/spec_helper.rb
|
121
112
|
- spec/test_adapter/active_record/connection_adapters/read_only_adapter.rb
|
122
113
|
- spec/test_model.rb
|
123
|
-
homepage:
|
124
|
-
licenses:
|
114
|
+
homepage: https://github.com/bdurand/seamless_database_pool
|
115
|
+
licenses:
|
116
|
+
- MIT
|
125
117
|
metadata: {}
|
126
118
|
post_install_message:
|
127
119
|
rdoc_options: []
|
@@ -139,9 +131,18 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
139
131
|
version: '0'
|
140
132
|
requirements: []
|
141
133
|
rubyforge_project:
|
142
|
-
rubygems_version: 2.
|
134
|
+
rubygems_version: 2.4.5
|
143
135
|
signing_key:
|
144
136
|
specification_version: 4
|
145
137
|
summary: Add support for master/slave database clusters in ActiveRecord to improve
|
146
138
|
performance.
|
147
|
-
test_files:
|
139
|
+
test_files:
|
140
|
+
- spec/connection_adapters_spec.rb
|
141
|
+
- spec/connection_statistics_spec.rb
|
142
|
+
- spec/controller_filter_spec.rb
|
143
|
+
- spec/database.yml
|
144
|
+
- spec/seamless_database_pool_adapter_spec.rb
|
145
|
+
- spec/seamless_database_pool_spec.rb
|
146
|
+
- spec/spec_helper.rb
|
147
|
+
- spec/test_adapter/active_record/connection_adapters/read_only_adapter.rb
|
148
|
+
- spec/test_model.rb
|