seamless_database_pool 1.0.2 → 1.0.3

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/Rakefile CHANGED
@@ -22,7 +22,7 @@ end
22
22
 
23
23
  spec = Gem::Specification.new do |s|
24
24
  s.name = "seamless_database_pool"
25
- s.version = "1.0.2"
25
+ s.version = "1.0.3"
26
26
  s.author = "Brian Durand"
27
27
  s.platform = Gem::Platform::RUBY
28
28
  s.summary = "Support for master/slave database clusters in ActiveRecord"
@@ -31,9 +31,14 @@ module ActiveRecord
31
31
  end
32
32
  end if config[:read_pool]
33
33
 
34
-
35
- klass = ActiveRecord::ConnectionAdapters::SeamlessDatabasePoolAdapter.adapter_class(master_connection)
36
- klass.new(nil, logger, master_connection, read_connections, pool_weights)
34
+ @seamless_database_pool_classes ||= {}
35
+ klass = @seamless_database_pool_classes[master_connection.class]
36
+ unless klass
37
+ klass = ActiveRecord::ConnectionAdapters::SeamlessDatabasePoolAdapter.adapter_class(master_connection)
38
+ @seamless_database_pool_classes[master_connection.class] = klass
39
+ end
40
+
41
+ return klass.new(nil, logger, master_connection, read_connections, pool_weights)
37
42
  end
38
43
 
39
44
  def self.establish_adapter (adapter)
@@ -66,18 +71,6 @@ module ActiveRecord
66
71
  end
67
72
  alias_method_chain(:reload, :seamless_database_pool)
68
73
  end
69
-
70
- module Associations
71
- class AssociationProxy
72
- # Force reload to use the master connection since it's probably being called for a reason.
73
- def reload_with_seamless_database_pool
74
- SeamlessDatabasePool.use_master_connection do
75
- reload_without_seamless_database_pool
76
- end
77
- end
78
- alias_method_chain(:reload, :seamless_database_pool)
79
- end
80
- end
81
74
 
82
75
  module ConnectionAdapters
83
76
  class SeamlessDatabasePoolAdapter < AbstractAdapter
@@ -87,13 +80,11 @@ module ActiveRecord
87
80
  # Create an anonymous class that extends this one and proxies methods to the pool connections.
88
81
  def self.adapter_class (master_connection)
89
82
  # Define methods to proxy to the appropriate pool
90
- read_only_methods = [:select_one, :select_all, :select_value, :select_values, :select_rows, :select]
91
- connection_methods = [:adapter_name, :active?, :reconnect!, :disconnect!, :reset!, :verify!, :reset_runtime]
83
+ read_only_methods = [:select_one, :select_all, :select_value, :select_values, :select_rows]
92
84
  master_methods = master_connection.public_methods(false) + master_connection.protected_methods(false) + master_connection.private_methods(false)
93
- master_methods -= public_methods(false) + protected_methods(false) + private_methods(false)
85
+ master_methods -= public_instance_methods(false) + protected_instance_methods(false) + private_instance_methods(false)
94
86
  master_methods = master_methods.collect{|m| m.to_sym}
95
87
  master_methods -= read_only_methods
96
- master_methods -= connection_methods
97
88
  master_methods.delete(:transaction)
98
89
 
99
90
  klass = Class.new(self)
@@ -108,29 +99,6 @@ module ActiveRecord
108
99
  end
109
100
  ))
110
101
  end
111
-
112
- read_only_methods.each do |method_name|
113
- klass.class_eval(%Q(
114
- def #{method_name}(*args, &block)
115
- connection = current_read_connection
116
- begin
117
- proxy_connection_method(connection, :#{method_name}, :read, *args, &block)
118
- rescue DatabaseConnectionError => e
119
- unless block or using_master_connection?
120
- # Try again with a different connection if needed unless it could have a side effect
121
- unless connection.active?
122
- suppress_read_connection(connection, 30)
123
- connection = current_read_connection
124
- SeamlessDatabasePool.set_persistent_read_connection(self, connection)
125
- end
126
- proxy_connection_method(connection, :#{method_name}, :retry, *args, &block)
127
- else
128
- raise e.wrapped_exception
129
- end
130
- end
131
- end
132
- ))
133
- end
134
102
 
135
103
  return klass
136
104
  end
@@ -162,6 +130,10 @@ module ActiveRecord
162
130
  return @weighted_read_connections.select{|conn| conn == connection}.size
163
131
  end
164
132
 
133
+ def requires_reloading?
134
+ false
135
+ end
136
+
165
137
  def active?
166
138
  active = true
167
139
  all_connections.each{|conn| active &= conn.active?}
@@ -212,6 +184,21 @@ module ActiveRecord
212
184
  end
213
185
  end
214
186
 
187
+ # Returns the last auto-generated ID from the affected table.
188
+ def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
189
+ master_connection.insert(sql, name, pk, id_value, sequence_name)
190
+ end
191
+
192
+ # Executes the update statement and returns the number of rows affected.
193
+ def update(sql, name = nil)
194
+ master_connection.update(sql, name)
195
+ end
196
+
197
+ # Executes the delete statement and returns the number of rows affected.
198
+ def delete(sql, name = nil)
199
+ master_connection.delete(sql, name)
200
+ end
201
+
215
202
  def using_master_connection?
216
203
  !!@use_master
217
204
  end
@@ -290,6 +277,27 @@ module ActiveRecord
290
277
  end
291
278
  end
292
279
 
280
+ protected
281
+
282
+ def select (sql, name = nil)
283
+ connection = current_read_connection
284
+ begin
285
+ proxy_connection_method(connection, :select, :read, *[sql, name])
286
+ rescue DatabaseConnectionError => e
287
+ unless using_master_connection?
288
+ # Try again with a different connection if needed unless it could have a side effect
289
+ unless connection.active?
290
+ suppress_read_connection(connection, 30)
291
+ connection = current_read_connection
292
+ SeamlessDatabasePool.set_persistent_read_connection(self, connection)
293
+ end
294
+ proxy_connection_method(connection, :select, :retry, *[sql, name])
295
+ else
296
+ raise e.wrapped_exception
297
+ end
298
+ end
299
+ end
300
+
293
301
  private
294
302
 
295
303
  def proxy_connection_method (connection, method, proxy_type, *args, &block)
@@ -118,16 +118,16 @@ describe "SeamlessDatabasePoolAdapter" do
118
118
  connection_class = ActiveRecord::ConnectionAdapters::SeamlessDatabasePoolAdapter.adapter_class(@master_connection)
119
119
  connection = connection_class.new(nil, mock(:logger), @master_connection, [@read_connection_1], {@read_connection_1 => 1})
120
120
  @master_connection.should_receive(:transaction).with(true).and_yield
121
- @master_connection.should_receive(:select_one).with('Transaction SQL')
122
- @read_connection_1.should_receive(:select_one).with('SQL 1')
123
- @read_connection_1.should_receive(:select_one).with('SQL 2')
121
+ @master_connection.should_receive(:select).with('Transaction SQL', nil)
122
+ @read_connection_1.should_receive(:select).with('SQL 1', nil)
123
+ @read_connection_1.should_receive(:select).with('SQL 2', nil)
124
124
 
125
125
  SeamlessDatabasePool.use_persistent_read_connection do
126
- connection.select_one('SQL 1')
126
+ connection.send(:select, 'SQL 1', nil)
127
127
  connection.transaction do
128
- connection.select_one('Transaction SQL')
128
+ connection.send(:select, 'Transaction SQL', nil)
129
129
  end
130
- connection.select_one('SQL 2')
130
+ connection.send(:select, 'SQL 2', nil)
131
131
  end
132
132
  end
133
133
 
@@ -135,58 +135,23 @@ describe "SeamlessDatabasePoolAdapter" do
135
135
 
136
136
  it "should proxy select methods to a read connection" do
137
137
  @pool_connection.should_receive(:current_read_connection).and_return(@read_connection_1)
138
- @read_connection_1.should_receive(:select_one).with('SQL').and_return(:retval)
139
- @pool_connection.select_one('SQL').should == :retval
140
- end
141
-
142
- it "should proxy select methods to a read connection" do
143
- @pool_connection.should_receive(:current_read_connection).and_return(@read_connection_1)
144
- @read_connection_1.should_receive(:select_all).with('SQL').and_return(:retval)
145
- @pool_connection.select_all('SQL').should == :retval
146
- end
147
-
148
- it "should proxy select methods to a read connection" do
149
- @pool_connection.should_receive(:current_read_connection).and_return(@read_connection_1)
150
- @read_connection_1.should_receive(:select_value).with('SQL').and_return(:retval)
151
- @pool_connection.select_value('SQL').should == :retval
152
- end
153
-
154
- it "should proxy select methods to a read connection" do
155
- @pool_connection.should_receive(:current_read_connection).and_return(@read_connection_1)
156
- @read_connection_1.should_receive(:select_values).with('SQL').and_return(:retval)
157
- @pool_connection.select_values('SQL').should == :retval
158
- end
159
-
160
- it "should proxy select methods to a read connection" do
161
- @pool_connection.should_receive(:current_read_connection).and_return(@read_connection_1)
162
- @read_connection_1.should_receive(:select_rows).with('SQL').and_return(:retval)
163
- @pool_connection.select_rows('SQL').should == :retval
164
- end
165
-
166
- it "should proxy select methods to a read connection" do
167
- @pool_connection.should_receive(:current_read_connection).and_return(@read_connection_1)
168
- @read_connection_1.should_receive(:select).with('SQL', 'name').and_return(:retval)
169
- @pool_connection.send(:select, 'SQL', 'name').should == :retval
138
+ @read_connection_1.should_receive(:select).with('SQL', nil).and_return(:retval)
139
+ @pool_connection.send(:select, 'SQL').should == :retval
170
140
  end
171
141
 
172
142
  # Master connection methods
173
143
 
174
- it "should proxy quote method to the master connection" do
175
- @master_connection.should_receive(:insert).with('SQL').and_return(:retval)
144
+ it "should proxy insert method to the master connection" do
145
+ @master_connection.should_receive(:insert).with('SQL', nil, nil, nil, nil).and_return(:retval)
176
146
  @pool_connection.insert('SQL').should == :retval
177
147
  end
178
148
 
179
- it "should proxy quote method to the master connection" do
180
- @master_connection.should_receive(:update).with('SQL').and_return(:retval)
149
+ it "should proxy update method to the master connection" do
150
+ @master_connection.should_receive(:update).with('SQL', nil).and_return(:retval)
181
151
  @pool_connection.update('SQL').should == :retval
182
152
  end
183
153
 
184
- it "should proxy quote method to the master connection" do
185
- @master_connection.should_receive(:execute).with('SQL').and_return(:retval)
186
- @pool_connection.execute('SQL').should == :retval
187
- end
188
-
189
- it "should proxy quote method to the master connection" do
154
+ it "should proxy columns method to the master connection" do
190
155
  @master_connection.should_receive(:columns).with(:table).and_return(:retval)
191
156
  @pool_connection.columns(:table).should == :retval
192
157
  end
@@ -282,48 +247,40 @@ describe "SeamlessDatabasePoolAdapter" do
282
247
  connection_error = ActiveRecord::ConnectionAdapters::SeamlessDatabasePoolAdapter::DatabaseConnectionError.new
283
248
  connection_error.wrapped_exception = StandardError.new("Error")
284
249
  @pool_connection.should_receive(:current_read_connection).and_return(@read_connection_1)
285
- @pool_connection.should_receive(:proxy_connection_method).with(@read_connection_1, :select_value, :read, 'SQL').and_raise(connection_error)
250
+ @pool_connection.should_receive(:proxy_connection_method).with(@read_connection_1, :select, :read, 'SQL', nil).and_raise(connection_error)
286
251
  @read_connection_1.should_receive(:active?).and_return(true)
287
252
  @pool_connection.should_not_receive(:suppress_read_connection)
288
253
  SeamlessDatabasePool.should_not_receive(:set_persistent_read_connection)
289
- @pool_connection.should_receive(:proxy_connection_method).with(@read_connection_1, :select_value, :retry, 'SQL').and_return(:results)
290
- @pool_connection.select_value('SQL').should == :results
254
+ @pool_connection.should_receive(:proxy_connection_method).with(@read_connection_1, :select, :retry, 'SQL', nil).and_return(:results)
255
+ @pool_connection.send(:select, 'SQL').should == :results
291
256
  end
292
257
 
293
258
  it "should not try to execute a read statement again after a connection error if the master connection must be used" do
294
259
  connection_error = ActiveRecord::ConnectionAdapters::SeamlessDatabasePoolAdapter::DatabaseConnectionError.new
295
260
  connection_error.wrapped_exception = StandardError.new("Error")
296
261
  @pool_connection.should_receive(:current_read_connection).and_return(@read_connection_1)
297
- @pool_connection.should_receive(:proxy_connection_method).with(@read_connection_1, :select_value, :read, 'SQL').and_raise(connection_error)
262
+ @pool_connection.should_receive(:proxy_connection_method).with(@read_connection_1, :select, :read, 'SQL', nil).and_raise(connection_error)
298
263
  @pool_connection.use_master_connection do
299
- lambda{@pool_connection.select_value('SQL')}.should raise_error("Error")
264
+ lambda{@pool_connection.send(:select, 'SQL')}.should raise_error("Error")
300
265
  end
301
266
  end
302
267
 
303
- it "should not try to execute a read statement again after a connection error if there is a block" do
304
- connection_error = ActiveRecord::ConnectionAdapters::SeamlessDatabasePoolAdapter::DatabaseConnectionError.new
305
- connection_error.wrapped_exception = StandardError.new("Error")
306
- @pool_connection.should_receive(:current_read_connection).and_return(@read_connection_1)
307
- @pool_connection.should_receive(:proxy_connection_method).with(@read_connection_1, :select_value, :read, 'SQL').and_raise(connection_error)
308
- lambda{@pool_connection.select_value('SQL'){}}.should raise_error("Error")
309
- end
310
-
311
268
  it "should not try to execute a read statement again after a non-connection error" do
312
269
  @pool_connection.should_receive(:current_read_connection).and_return(@read_connection_1)
313
- @pool_connection.should_receive(:proxy_connection_method).with(@read_connection_1, :select_value, :read, 'SQL').and_raise("SQL Error")
314
- lambda{@pool_connection.select_value('SQL')}.should raise_error("SQL Error")
270
+ @pool_connection.should_receive(:proxy_connection_method).with(@read_connection_1, :select, :read, 'SQL', nil).and_raise("SQL Error")
271
+ lambda{@pool_connection.send(:select, 'SQL')}.should raise_error("SQL Error")
315
272
  end
316
273
 
317
274
  it "should use a different connection on a retry if the original connection could not be reconnected" do
318
275
  connection_error = ActiveRecord::ConnectionAdapters::SeamlessDatabasePoolAdapter::DatabaseConnectionError.new
319
276
  connection_error.wrapped_exception = StandardError.new("Error")
320
277
  @pool_connection.should_receive(:current_read_connection).and_return(@read_connection_1, @read_connection_2)
321
- @pool_connection.should_receive(:proxy_connection_method).with(@read_connection_1, :select_value, :read, 'SQL').and_raise(connection_error)
278
+ @pool_connection.should_receive(:proxy_connection_method).with(@read_connection_1, :select, :read, 'SQL', nil).and_raise(connection_error)
322
279
  @read_connection_1.should_receive(:active?).and_return(false)
323
280
  @pool_connection.should_receive(:suppress_read_connection).with(@read_connection_1, 30)
324
281
  SeamlessDatabasePool.should_receive(:set_persistent_read_connection).with(@pool_connection, @read_connection_2)
325
- @pool_connection.should_receive(:proxy_connection_method).with(@read_connection_2, :select_value, :retry, 'SQL').and_return(:results)
326
- @pool_connection.select_value('SQL').should == :results
282
+ @pool_connection.should_receive(:proxy_connection_method).with(@read_connection_2, :select, :retry, 'SQL', nil).and_return(:results)
283
+ @pool_connection.send(:select, 'SQL').should == :results
327
284
  end
328
285
 
329
286
  it "should keep track of read connections that can't be reconnected for a set period" do
@@ -427,11 +384,4 @@ describe "Reload extensions" do
427
384
  @record.should_receive(:reload_without_seamless_database_pool).with(:options)
428
385
  @record.reload(:options)
429
386
  end
430
-
431
- it "should force the master connection on reload of an association" do
432
- association = @record.seamless_database_pool_test_things
433
- SeamlessDatabasePool.should_receive(:use_master_connection).and_yield
434
- association.should_receive(:reload_without_seamless_database_pool)
435
- @record.seamless_database_pool_test_things(true)
436
- end
437
387
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: seamless_database_pool
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Durand
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-05-06 00:00:00 -05:00
12
+ date: 2009-05-26 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -22,10 +22,7 @@ extensions: []
22
22
  extra_rdoc_files:
23
23
  - README
24
24
  files:
25
- - lib/active_record
26
- - lib/active_record/connection_adapters
27
25
  - lib/active_record/connection_adapters/seamless_database_pool_adapter.rb
28
- - lib/seamless_database_pool
29
26
  - lib/seamless_database_pool/connect_timeout.rb
30
27
  - lib/seamless_database_pool/connection_statistics.rb
31
28
  - lib/seamless_database_pool/controller_filter.rb
@@ -36,6 +33,8 @@ files:
36
33
  - README
37
34
  has_rdoc: true
38
35
  homepage: http://seamlessdbpool.rubyforge.org
36
+ licenses: []
37
+
39
38
  post_install_message:
40
39
  rdoc_options:
41
40
  - --title
@@ -61,9 +60,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
61
60
  requirements:
62
61
  - rspec 1.0.8 or higher is needed to run the tests
63
62
  rubyforge_project: seamlessdbpool
64
- rubygems_version: 1.3.1
63
+ rubygems_version: 1.3.3
65
64
  signing_key:
66
- specification_version: 2
65
+ specification_version: 3
67
66
  summary: Support for master/slave database clusters in ActiveRecord
68
67
  test_files:
69
68
  - spec/connection_statistics_spec.rb