seamless_database_pool 1.0.5 → 1.0.6

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
@@ -1,6 +1,7 @@
1
1
  require 'rubygems'
2
2
  require 'rake'
3
3
  require 'rake/rdoctask'
4
+ require 'yaml'
4
5
 
5
6
  desc 'Default: run unit tests.'
6
7
  task :default => :test
@@ -11,17 +12,61 @@ begin
11
12
  Spec::Rake::SpecTask.new(:test) do |t|
12
13
  t.spec_files = FileList.new('spec/**/*_spec.rb')
13
14
  end
15
+
16
+ namespace :test do
17
+ desc "Run all tests including for all database adapters"
18
+ task :all do
19
+ save_val = ENV['TEST_ADAPTERS']
20
+ begin
21
+ ENV['TEST_ADAPTERS'] = YAML.load_file(File.expand_path("../spec/database.yml", __FILE__)).keys.join(' ')
22
+ Rake::Task["test"].execute
23
+ ensure
24
+ ENV['TEST_ADAPTERS'] = save_val
25
+ end
26
+ end
27
+
28
+ desc "Test all database adapters defined in database.yml or just the one specified in TEST_ADAPTERS"
29
+ task :adapters do
30
+ save_val = ENV['TEST_ADAPTERS']
31
+ begin
32
+ ENV['TEST_ADAPTERS'] ||= YAML.load_file(File.expand_path("../spec/database.yml", __FILE__)).keys.join(' ')
33
+ Rake::Task["test:adapters:specified"].execute
34
+ ensure
35
+ ENV['TEST_ADAPTERS'] = save_val
36
+ end
37
+ end
38
+
39
+ namespace :adapters do
40
+ desc "Internal task to run database adapter tests"
41
+ Spec::Rake::SpecTask.new(:specified) do |t|
42
+ t.spec_files = FileList.new('spec/connection_adapters_spec.rb')
43
+ end
44
+
45
+ YAML.load_file(File.expand_path("../spec/database.yml", __FILE__)).keys.each do |adapter_name|
46
+ desc "Test the #{adapter_name} database adapter"
47
+ task adapter_name do
48
+ save_val = ENV['TEST_ADAPTERS']
49
+ begin
50
+ ENV['TEST_ADAPTERS'] = adapter_name
51
+ Rake::Task["test:adapters:specified"].execute
52
+ ensure
53
+ ENV['TEST_ADAPTERS'] = save_val
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
14
59
  rescue LoadError
15
- tast :test do
16
- STDERR.puts "You must have rspec >= 1.2.9 to run the tests"
60
+ task :test do
61
+ STDERR.puts "You must have rspec >= 1.3.0 to run the tests"
17
62
  end
18
63
  end
19
64
 
20
65
  desc 'Generate documentation for seamless_database_pool.'
21
66
  Rake::RDocTask.new(:rdoc) do |rdoc|
22
67
  rdoc.rdoc_dir = 'rdoc'
23
- rdoc.options << '--title' << 'Seamless Database Pool' << '--line-numbers' << '--inline-source' << '--main' << 'README'
24
- rdoc.rdoc_files.include('README')
68
+ rdoc.options << '--title' << 'Seamless Database Pool' << '--line-numbers' << '--inline-source' << '--main' << 'README.rdoc'
69
+ rdoc.rdoc_files.include('README.rdoc')
25
70
  rdoc.rdoc_files.include('lib/**/*.rb')
26
71
  end
27
72
 
@@ -33,6 +78,9 @@ begin
33
78
  gem.email = "brian@embellishedvisions.com"
34
79
  gem.homepage = "http://github.com/bdurand/seamless_database_pool"
35
80
  gem.authors = ["Brian Durand"]
81
+ gem.files = FileList["lib/**/*", "spec/**/*", "README.rdoc", "Rakefile"].to_a
82
+ gem.has_rdoc = true
83
+ gem.extra_rdoc_files = ["README.rdoc"]
36
84
 
37
85
  gem.add_dependency('activerecord', '>= 2.2.2')
38
86
  gem.add_development_dependency('rspec', '>= 1.2.9')
@@ -1,73 +1,83 @@
1
1
  module ActiveRecord
2
2
  class Base
3
- def self.seamless_database_pool_connection (config)
4
- pool_weights = {}
5
-
6
- default_config = {:pool_weight => 1}.merge(config.merge(:adapter => config[:pool_adapter]))
7
- default_config.delete(:master)
8
- default_config.delete(:read_pool)
9
- default_config.delete(:pool_adapter)
10
-
11
- master_config = default_config.merge(config[:master].symbolize_keys)
12
- establish_adapter(master_config[:adapter])
13
- master_connection = send("#{master_config[:adapter]}_connection".to_sym, master_config)
14
- master_connection.class.send(:include, SeamlessDatabasePool::ConnectTimeout) unless master_connection.class.include?(SeamlessDatabasePool::ConnectTimeout)
15
- master_connection.connect_timeout = master_config[:connect_timeout]
16
- pool_weights[master_connection] = master_config[:pool_weight].to_i if master_config[:pool_weight].to_i > 0
17
-
18
- read_connections = []
19
- config[:read_pool].each do |read_config|
20
- read_config = default_config.merge(read_config.symbolize_keys)
21
- read_config[:pool_weight] = read_config[:pool_weight].to_i
22
- if read_config[:pool_weight] > 0
23
- establish_adapter(read_config[:adapter])
24
- conn = send("#{read_config[:adapter]}_connection".to_sym, read_config)
25
- conn.class.send(:include, SeamlessDatabasePool::ConnectTimeout) unless conn.class.include?(SeamlessDatabasePool::ConnectTimeout)
26
- conn.connect_timeout = read_config[:connect_timeout]
27
- read_connections << conn
28
- pool_weights[conn] = read_config[:pool_weight]
3
+ class << self
4
+ def seamless_database_pool_connection (config)
5
+ pool_weights = {}
6
+
7
+ config = config.with_indifferent_access
8
+ default_config = {:pool_weight => 1}.merge(config.merge(:adapter => config[:pool_adapter])).with_indifferent_access
9
+ default_config.delete(:master)
10
+ default_config.delete(:read_pool)
11
+ default_config.delete(:pool_adapter)
12
+
13
+ master_config = default_config.merge(config[:master]).with_indifferent_access
14
+ establish_adapter(master_config[:adapter])
15
+ master_connection = send("#{master_config[:adapter]}_connection".to_sym, master_config)
16
+ master_connection.class.send(:include, SeamlessDatabasePool::ConnectTimeout) unless master_connection.class.include?(SeamlessDatabasePool::ConnectTimeout)
17
+ master_connection.connect_timeout = master_config[:connect_timeout]
18
+ pool_weights[master_connection] = master_config[:pool_weight].to_i if master_config[:pool_weight].to_i > 0
19
+
20
+ read_connections = []
21
+ config[:read_pool].each do |read_config|
22
+ read_config = default_config.merge(read_config).with_indifferent_access
23
+ read_config[:pool_weight] = read_config[:pool_weight].to_i
24
+ if read_config[:pool_weight] > 0
25
+ establish_adapter(read_config[:adapter])
26
+ conn = send("#{read_config[:adapter]}_connection".to_sym, read_config)
27
+ conn.class.send(:include, SeamlessDatabasePool::ConnectTimeout) unless conn.class.include?(SeamlessDatabasePool::ConnectTimeout)
28
+ conn.connect_timeout = read_config[:connect_timeout]
29
+ read_connections << conn
30
+ pool_weights[conn] = read_config[:pool_weight]
31
+ end
32
+ end if config[:read_pool]
33
+
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
29
39
  end
30
- end if config[:read_pool]
31
40
 
32
- @seamless_database_pool_classes ||= {}
33
- klass = @seamless_database_pool_classes[master_connection.class]
34
- unless klass
35
- klass = ActiveRecord::ConnectionAdapters::SeamlessDatabasePoolAdapter.adapter_class(master_connection)
36
- @seamless_database_pool_classes[master_connection.class] = klass
41
+ return klass.new(nil, logger, master_connection, read_connections, pool_weights)
37
42
  end
38
-
39
- return klass.new(nil, logger, master_connection, read_connections, pool_weights)
40
- end
41
43
 
42
- def self.establish_adapter (adapter)
43
- unless adapter then raise AdapterNotSpecified, "database configuration does not specify adapter" end
44
- raise AdapterNotFound, "database pool must specify adapters" if adapter == 'seamless_database_pool'
45
-
46
- begin
47
- require 'rubygems'
48
- gem "activerecord-#{adapter}-adapter"
49
- require "active_record/connection_adapters/#{adapter}_adapter"
50
- rescue LoadError
44
+ def establish_adapter (adapter)
45
+ raise AdapterNotSpecified.new("database configuration does not specify adapter") unless adapter
46
+ raise AdapterNotFound.new("database pool must specify adapters") if adapter == 'seamless_database_pool'
47
+
51
48
  begin
49
+ require 'rubygems'
50
+ gem "activerecord-#{adapter}-adapter"
52
51
  require "active_record/connection_adapters/#{adapter}_adapter"
53
52
  rescue LoadError
54
- raise "Please install the #{adapter} adapter: `gem install activerecord-#{adapter}-adapter` (#{$!})"
53
+ begin
54
+ require "active_record/connection_adapters/#{adapter}_adapter"
55
+ rescue LoadError
56
+ raise "Please install the #{adapter} adapter: `gem install activerecord-#{adapter}-adapter` (#{$!})"
57
+ end
55
58
  end
56
- end
57
59
 
58
- adapter_method = "#{adapter}_connection"
59
- if !respond_to?(adapter_method)
60
- raise AdapterNotFound, "database configuration specifies nonexistent #{adapter} adapter"
60
+ adapter_method = "#{adapter}_connection"
61
+ if !respond_to?(adapter_method)
62
+ raise AdapterNotFound, "database configuration specifies nonexistent #{adapter} adapter"
63
+ end
61
64
  end
62
65
  end
63
-
64
- # Force reload to use the master connection since it's probably being called for a reason.
65
- def reload_with_seamless_database_pool (options = nil)
66
- SeamlessDatabasePool.use_master_connection do
67
- reload_without_seamless_database_pool(options)
66
+
67
+ module SeamlessDatabasePoolBehavior
68
+ def self.included (base)
69
+ base.alias_method_chain(:reload, :seamless_database_pool)
70
+ end
71
+
72
+ # Force reload to use the master connection since it's probably being called for a reason.
73
+ def reload_with_seamless_database_pool (*args)
74
+ SeamlessDatabasePool.use_master_connection do
75
+ reload_without_seamless_database_pool(*args)
76
+ end
68
77
  end
69
78
  end
70
- alias_method_chain(:reload, :seamless_database_pool)
79
+
80
+ include(SeamlessDatabasePoolBehavior) unless include?(SeamlessDatabasePoolBehavior)
71
81
  end
72
82
 
73
83
  module ConnectionAdapters
@@ -78,25 +88,45 @@ module ActiveRecord
78
88
  # Create an anonymous class that extends this one and proxies methods to the pool connections.
79
89
  def self.adapter_class (master_connection)
80
90
  # Define methods to proxy to the appropriate pool
81
- read_only_methods = [:select_one, :select_all, :select_value, :select_values, :select_rows]
82
- master_methods = master_connection.public_methods(false) + master_connection.protected_methods(false) + master_connection.private_methods(false)
91
+ read_only_methods = [:select_one, :select_all, :select_value, :select_values, :select, :select_rows, :execute, :tables, :columns]
92
+ master_methods = []
93
+ master_connection_classes = [AbstractAdapter, Quoting, DatabaseStatements, SchemaStatements]
94
+ master_connection_classes << DatabaseLimits if const_defined?(:DatabaseLimits)
95
+ master_connection_class = master_connection.class
96
+ while ![Object, AbstractAdapter].include?(master_connection_class) do
97
+ master_connection_classes << master_connection_class
98
+ master_connection_class = master_connection_class.superclass
99
+ end
100
+ master_connection_classes.each do |connection_class|
101
+ master_methods.concat(connection_class.public_instance_methods(false))
102
+ master_methods.concat(connection_class.protected_instance_methods(false))
103
+ #master_methods.concat(connection_class.private_instance_methods(false))
104
+ end
105
+ master_methods.uniq!
83
106
  master_methods -= public_instance_methods(false) + protected_instance_methods(false) + private_instance_methods(false)
84
107
  master_methods = master_methods.collect{|m| m.to_sym}
85
108
  master_methods -= read_only_methods
86
- master_methods.delete(:transaction)
87
109
 
88
110
  klass = Class.new(self)
89
111
  master_methods.each do |method_name|
90
- klass.class_eval(%Q(
112
+ klass.class_eval %Q(
91
113
  def #{method_name}(*args, &block)
92
- begin
93
- proxy_connection_method(master_connection, :#{method_name}, :master, *args, &block)
94
- rescue DatabaseConnectionError => e
95
- raise e.wrapped_exception
114
+ use_master_connection do
115
+ return proxy_connection_method(master_connection, :#{method_name}, :master, *args, &block)
96
116
  end
97
117
  end
98
- ))
118
+ )
119
+ end
120
+
121
+ read_only_methods.each do |method_name|
122
+ klass.class_eval %Q(
123
+ def #{method_name}(*args, &block)
124
+ connection = @use_master ? master_connection : current_read_connection
125
+ proxy_connection_method(connection, :#{method_name}, :read, *args, &block)
126
+ end
127
+ )
99
128
  end
129
+ klass.send :protected, :select
100
130
 
101
131
  return klass
102
132
  end
@@ -115,7 +145,7 @@ module ActiveRecord
115
145
  end
116
146
 
117
147
  def adapter_name #:nodoc:
118
- 'Seamless Database Pool'
148
+ 'Seamless_Database_Pool'
119
149
  end
120
150
 
121
151
  # Returns an array of the master connection and the read pool connections
@@ -174,37 +204,6 @@ module ActiveRecord
174
204
  return SeamlessDatabasePool.read_only_connection(self)
175
205
  end
176
206
 
177
- def transaction(start_db_transaction = true)
178
- use_master_connection do
179
- master_connection.transaction(start_db_transaction) do
180
- yield if block_given?
181
- end
182
- end
183
- end
184
-
185
- # Returns the last auto-generated ID from the affected table.
186
- def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
187
- master_connection.insert(sql, name, pk, id_value, sequence_name)
188
- end
189
-
190
- # Executes the update statement and returns the number of rows affected.
191
- def update(sql, name = nil)
192
- master_connection.update(sql, name)
193
- end
194
-
195
- # Executes the delete statement and returns the number of rows affected.
196
- def delete(sql, name = nil)
197
- master_connection.delete(sql, name)
198
- end
199
-
200
- def execute (*args)
201
- proxy_connection_method(current_read_connection, :execute, :read, *args)
202
- end
203
-
204
- def select_rows(*args)
205
- proxy_connection_method(current_read_connection, :select_rows, :read, *args)
206
- end
207
-
208
207
  def using_master_connection?
209
208
  !!@use_master
210
209
  end
@@ -221,7 +220,6 @@ module ActiveRecord
221
220
  end
222
221
 
223
222
  class DatabaseConnectionError < StandardError
224
- attr_accessor :wrapped_exception
225
223
  end
226
224
 
227
225
  # This simple class puts an expire time on an array of connections. It is used so the a connection
@@ -237,7 +235,7 @@ module ActiveRecord
237
235
  end
238
236
 
239
237
  def expired?
240
- @expires < Time.now if @expires
238
+ @expires <= Time.now if @expires
241
239
  end
242
240
 
243
241
  def reconnect!
@@ -253,7 +251,7 @@ module ActiveRecord
253
251
  available = @available_read_connections.last
254
252
  if available.expired?
255
253
  begin
256
- available.reconnect!
254
+ available.reconnect!# unless available.active?
257
255
  rescue
258
256
  # Couldn't reconnect so try again in a little bit
259
257
  available.expires = 30.seconds.from_now
@@ -266,6 +264,15 @@ module ActiveRecord
266
264
  end
267
265
  end
268
266
 
267
+ def reset_available_read_connections
268
+ @available_read_connections.slice!(1, @available_read_connections.length)
269
+ @available_read_connections.first.connections.each do |connection|
270
+ unless connection.active?
271
+ connection.reconnect! rescue nil
272
+ end
273
+ end
274
+ end
275
+
269
276
  # Temporarily remove a connection from the read pool.
270
277
  def suppress_read_connection (conn, expire)
271
278
  available = available_read_connections
@@ -276,47 +283,31 @@ module ActiveRecord
276
283
 
277
284
  if connections.empty?
278
285
  # No connections available so we might as well try them all again
279
- @available_read_connections.slice!(1, @available_read_connections.length)
286
+ reset_available_read_connections
280
287
  else
281
288
  # Available connections will now not include the suppressed connection for a while
282
289
  @available_read_connections.push(AvailableConnections.new(connections, conn, expire.seconds.from_now))
283
290
  end
284
291
  end
285
292
 
286
- protected
293
+ private
287
294
 
288
- def select (*args)
289
- connection = current_read_connection
295
+ def proxy_connection_method (connection, method, proxy_type, *args, &block)
290
296
  begin
291
- proxy_connection_method(connection, :select, :read, *args)
292
- rescue DatabaseConnectionError => e
293
- unless using_master_connection?
294
- # Try again with a different connection if needed unless it could have a side effect
297
+ connection.send(method, *args, &block)
298
+ rescue => e
299
+ # If the statement was a read statement and it wasn't forced against the master connection
300
+ # try to reconnect if the connection is dead and then re-run the statement.
301
+ if proxy_type == :read and !using_master_connection?
295
302
  unless connection.active?
296
303
  suppress_read_connection(connection, 30)
297
304
  connection = current_read_connection
298
305
  SeamlessDatabasePool.set_persistent_read_connection(self, connection)
299
306
  end
300
- proxy_connection_method(connection, :select, :retry, *args)
307
+ proxy_connection_method(connection, method, :retry, *args, &block)
301
308
  else
302
- raise e.wrapped_exception
303
- end
304
- end
305
- end
306
-
307
- private
308
-
309
- def proxy_connection_method (connection, method, proxy_type, *args, &block)
310
- begin
311
- connection.send(method, *args, &block)
312
- rescue => e
313
- unless proxy_type == :retry or connection.active?
314
- connection.reconnect! rescue nil
315
- connection_error = DatabaseConnectionError.new
316
- connection_error.wrapped_exception = e
317
- raise connection_error
309
+ raise e
318
310
  end
319
- raise e
320
311
  end
321
312
  end
322
313
 
@@ -0,0 +1,27 @@
1
+ module Arel
2
+ module SqlCompiler
3
+ # Hook into arel to use the compiler used by the master connection.
4
+ class Seamless_Database_PoolCompiler < GenericCompiler
5
+ def self.new (relation)
6
+ @compiler_classes ||= {}
7
+ master_adapter = relation.engine.connection.master_connection.adapter_name
8
+ compiler_class = @compiler_classes[master_adapter]
9
+ unless compiler_class
10
+ begin
11
+ require "arel/engines/sql/compilers/#{master_adapter.downcase}_compiler"
12
+ rescue LoadError
13
+ begin
14
+ # try to load an externally defined compiler, in case this adapter has defined the compiler on its own.
15
+ require "#{master_adapter.downcase}/arel_compiler"
16
+ rescue LoadError
17
+ raise "#{master_adapter} is not supported by Arel."
18
+ end
19
+ end
20
+ compiler_class = Arel::SqlCompiler.const_get("#{master_adapter}Compiler")
21
+ @compiler_classes[master_adapter] = compiler_class
22
+ end
23
+ compiler_class.new(relation)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -2,6 +2,7 @@ require File.join(File.dirname(__FILE__), 'seamless_database_pool', 'connect_tim
2
2
  require File.join(File.dirname(__FILE__), 'seamless_database_pool', 'connection_statistics')
3
3
  require File.join(File.dirname(__FILE__), 'seamless_database_pool', 'controller_filter')
4
4
  require File.join(File.dirname(__FILE__), 'active_record', 'connection_adapters', 'seamless_database_pool_adapter')
5
+ $LOAD_PATH << File.dirname(__FILE__) unless $LOAD_PATH.include?(File.dirname(__FILE__))
5
6
 
6
7
  # This module allows setting the read pool connection type. Generally you will use one of
7
8
  #
@@ -17,97 +18,99 @@ module SeamlessDatabasePool
17
18
 
18
19
  READ_CONNECTION_METHODS = [:master, :persistent, :random]
19
20
 
20
- # Call this method to use a random connection from the read pool for every select statement.
21
- # This method is good if your replication is very fast. Otherwise there is a chance you could
22
- # get inconsistent results from one request to the next. This can result in mysterious failures
23
- # if your code selects a value in one statement and then uses in another statement. You can wind
24
- # up trying to use a value from one server that hasn't been replicated to another one yet.
25
- # This method is best if you have few processes which generate a lot of queries and you have
26
- # fast replication.
27
- def self.use_random_read_connection
28
- if block_given?
29
- set_read_only_connection_type(:random){yield}
30
- else
31
- Thread.current[:read_only_connection] = :random
21
+ class << self
22
+ # Call this method to use a random connection from the read pool for every select statement.
23
+ # This method is good if your replication is very fast. Otherwise there is a chance you could
24
+ # get inconsistent results from one request to the next. This can result in mysterious failures
25
+ # if your code selects a value in one statement and then uses in another statement. You can wind
26
+ # up trying to use a value from one server that hasn't been replicated to another one yet.
27
+ # This method is best if you have few processes which generate a lot of queries and you have
28
+ # fast replication.
29
+ def use_random_read_connection
30
+ if block_given?
31
+ set_read_only_connection_type(:random){yield}
32
+ else
33
+ Thread.current[:read_only_connection] = :random
34
+ end
32
35
  end
33
- end
34
36
 
35
- # Call this method to pick a random connection from the read pool and use it for all subsequent
36
- # select statements. This provides consistency from one select statement to the next. This
37
- # method should always be called with a block otherwise you can end up with an imbalanced read
38
- # pool. This method is best if you have lots of processes which have a relatively few select
39
- # statements or a slow replication mechanism. Generally this is the best method to use for web
40
- # applications.
41
- def self.use_persistent_read_connection
42
- if block_given?
43
- set_read_only_connection_type(:persistent){yield}
44
- else
45
- Thread.current[:read_only_connection] = {}
37
+ # Call this method to pick a random connection from the read pool and use it for all subsequent
38
+ # select statements. This provides consistency from one select statement to the next. This
39
+ # method should always be called with a block otherwise you can end up with an imbalanced read
40
+ # pool. This method is best if you have lots of processes which have a relatively few select
41
+ # statements or a slow replication mechanism. Generally this is the best method to use for web
42
+ # applications.
43
+ def use_persistent_read_connection
44
+ if block_given?
45
+ set_read_only_connection_type(:persistent){yield}
46
+ else
47
+ Thread.current[:read_only_connection] = {}
48
+ end
46
49
  end
47
- end
48
50
 
49
- # Call this method to use the master connection for all subsequent select statements. This
50
- # method is most useful when you are doing lots of updates since it guarantees consistency
51
- # if you do a select immediately after an update or insert.
52
- #
53
- # The master connection will also be used for selects inside any transaction blocks. It will
54
- # also be used if you pass :readonly => false to any ActiveRecord.find method.
55
- def self.use_master_connection
56
- if block_given?
57
- set_read_only_connection_type(:master){yield}
58
- else
59
- Thread.current[:read_only_connection] = :master
51
+ # Call this method to use the master connection for all subsequent select statements. This
52
+ # method is most useful when you are doing lots of updates since it guarantees consistency
53
+ # if you do a select immediately after an update or insert.
54
+ #
55
+ # The master connection will also be used for selects inside any transaction blocks. It will
56
+ # also be used if you pass :readonly => false to any ActiveRecord.find method.
57
+ def use_master_connection
58
+ if block_given?
59
+ set_read_only_connection_type(:master){yield}
60
+ else
61
+ Thread.current[:read_only_connection] = :master
62
+ end
60
63
  end
61
- end
62
64
 
63
- # Set the read only connection type to either :master, :random, or :persistent.
64
- def self.set_read_only_connection_type (connection_type)
65
- saved_connection = Thread.current[:read_only_connection]
66
- retval = nil
67
- begin
68
- connection_type = {} if connection_type == :persistent
69
- Thread.current[:read_only_connection] = connection_type
70
- retval = yield if block_given?
71
- ensure
72
- Thread.current[:read_only_connection] = saved_connection
65
+ # Set the read only connection type to either :master, :random, or :persistent.
66
+ def set_read_only_connection_type (connection_type)
67
+ saved_connection = Thread.current[:read_only_connection]
68
+ retval = nil
69
+ begin
70
+ connection_type = {} if connection_type == :persistent
71
+ Thread.current[:read_only_connection] = connection_type
72
+ retval = yield if block_given?
73
+ ensure
74
+ Thread.current[:read_only_connection] = saved_connection
75
+ end
76
+ return retval
73
77
  end
74
- return retval
75
- end
76
78
 
77
- # Get the read only connection type currently in use. Will be one of :master, :random, or :persistent.
78
- def self.read_only_connection_type (default = :master)
79
- connection_type = Thread.current[:read_only_connection] || default
80
- connection_type = :persistent if connection_type.kind_of?(Hash)
81
- return connection_type
82
- end
79
+ # Get the read only connection type currently in use. Will be one of :master, :random, or :persistent.
80
+ def read_only_connection_type (default = :master)
81
+ connection_type = Thread.current[:read_only_connection] || default
82
+ connection_type = :persistent if connection_type.kind_of?(Hash)
83
+ return connection_type
84
+ end
83
85
 
84
- # Get a read only connection from a connection pool.
85
- def self.read_only_connection (pool_connection)
86
- return pool_connection.master_connection if pool_connection.using_master_connection?
87
- connection_type = Thread.current[:read_only_connection]
86
+ # Get a read only connection from a connection pool.
87
+ def read_only_connection (pool_connection)
88
+ return pool_connection.master_connection if pool_connection.using_master_connection?
89
+ connection_type = Thread.current[:read_only_connection]
88
90
 
89
- if connection_type.kind_of?(Hash)
90
- connection = connection_type[pool_connection]
91
- unless connection
92
- connection = pool_connection.random_read_connection
93
- connection_type[pool_connection] = connection
91
+ if connection_type.kind_of?(Hash)
92
+ connection = connection_type[pool_connection]
93
+ unless connection
94
+ connection = pool_connection.random_read_connection
95
+ connection_type[pool_connection] = connection
96
+ end
97
+ return connection
98
+ elsif connection_type == :random
99
+ return pool_connection.random_read_connection
100
+ else
101
+ return pool_connection.master_connection
94
102
  end
95
- return connection
96
- elsif connection_type == :random
97
- return pool_connection.random_read_connection
98
- else
99
- return pool_connection.master_connection
100
103
  end
101
- end
102
104
 
103
- # This method is provided as a way to change the persistent connection when it fails and a new one is substituted.
104
- def self.set_persistent_read_connection (pool_connection, read_connection)
105
- connection_type = Thread.current[:read_only_connection]
106
- connection_type[pool_connection] = read_connection if connection_type.kind_of?(Hash)
107
- end
105
+ # This method is provided as a way to change the persistent connection when it fails and a new one is substituted.
106
+ def set_persistent_read_connection (pool_connection, read_connection)
107
+ connection_type = Thread.current[:read_only_connection]
108
+ connection_type[pool_connection] = read_connection if connection_type.kind_of?(Hash)
109
+ end
108
110
 
109
- def self.clear_read_only_connection
110
- Thread.current[:read_only_connection] = nil
111
+ def clear_read_only_connection
112
+ Thread.current[:read_only_connection] = nil
113
+ end
111
114
  end
112
115
 
113
116
  end