Permalink
Browse files

Make connection_handler overridable per thread

  • Loading branch information...
1 parent c56e620 commit b37399ab987c3f54e94178da7d41bfc5f48308de @SamSaffron SamSaffron committed with SamSaffron Mar 27, 2013
Showing with 75 additions and 3 deletions.
  1. +7 −1 activerecord/CHANGELOG.md
  2. +11 −2 activerecord/lib/active_record/core.rb
  3. +57 −0 activerecord/test/cases/base_test.rb
View
8 activerecord/CHANGELOG.md
@@ -1,5 +1,11 @@
## Rails 4.0.0 (unreleased) ##
+* Allow ActiveRecord::Base.connection_handler to have thread affinity and be
+ settable, this effectively allows ActiveRecord to be used in a multi threaded
+ setup with multiple connections to multiple dbs.
+
+ *Sam Saffron*
+
* `rename_column` preserves auto_increment in mysql migrations.
Fixes #3493.
@@ -8,7 +14,7 @@
* PostgreSQL geometric type point is supported by ActiveRecord. Fixes #7324.
*Martin Schuerrer*
-
+
* Add suport for concurrent indexing in PostgreSQL adapter via the
`algorithm: :concurrently` option
View
13 activerecord/lib/active_record/core.rb
@@ -77,8 +77,17 @@ module Core
mattr_accessor :disable_implicit_join_references, instance_writer: false
self.disable_implicit_join_references = false
- class_attribute :connection_handler, instance_writer: false
- self.connection_handler = ConnectionAdapters::ConnectionHandler.new
+ class_attribute :default_connection_handler, instance_writer: false
+
+ def self.connection_handler
+ Thread.current[:active_record_connection_handler] || self.default_connection_handler
+ end
+
+ def self.connection_handler=(handler)
+ Thread.current[:active_record_connection_handler] = handler
+ end
+
+ self.default_connection_handler = ConnectionAdapters::ConnectionHandler.new
end
module ClassMethods
View
57 activerecord/test/cases/base_test.rb
@@ -1578,4 +1578,61 @@ def test_default_values_are_deeply_dupped
klass = Class.new(ActiveRecord::Base)
assert_equal ['foo'], klass.all.merge!(select: 'foo').select_values
end
+
+ test "connection_handler can be overriden" do
+ klass = Class.new(ActiveRecord::Base)
+ orig_handler = klass.connection_handler
+ new_handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new
+ thread_connection_handler = nil
+
+ t = Thread.new do
+ klass.connection_handler = new_handler
+ thread_connection_handler = klass.connection_handler
+ end
+ t.join
+
+ assert_equal klass.connection_handler, orig_handler
+ assert_equal thread_connection_handler, new_handler
+ end
+
+ test "new threads get default the default connection handler" do
+ klass = Class.new(ActiveRecord::Base)
+ orig_handler = klass.connection_handler
+ handler = nil
+
+ t = Thread.new do
+ handler = klass.connection_handler
+ end
+ t.join
+
+ assert_equal handler, orig_handler
+ assert_equal klass.connection_handler, orig_handler
+ assert_equal klass.default_connection_handler, orig_handler
+ end
+
+ test "changing a connection handler in a main thread does not poison the other threads" do
+ klass = Class.new(ActiveRecord::Base)
+ orig_handler = klass.connection_handler
+ new_handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new
+ after_handler = nil
+ is_set = false
+
+ t = Thread.new do
+ klass.connection_handler = new_handler
+ is_set = true
+ Thread.stop
+ after_handler = klass.connection_handler
+ end
+
+ while(!is_set)
+ Thread.pass
+ end
+
+ klass.connection_handler = orig_handler
+ t.wakeup
+ t.join
+
+ assert_equal after_handler, new_handler
+ assert_equal orig_handler, klass.connection_handler
+ end
end

0 comments on commit b37399a

Please sign in to comment.