Skip to content

Commit

Permalink
Make connection_handler overridable per thread
Browse files Browse the repository at this point in the history
  • Loading branch information
SamSaffron committed Mar 27, 2013
1 parent c56e620 commit b37399a
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 3 deletions.
8 changes: 7 additions & 1 deletion 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.

Expand All @@ -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

Expand Down
13 changes: 11 additions & 2 deletions activerecord/lib/active_record/core.rb
Expand Up @@ -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
Expand Down
57 changes: 57 additions & 0 deletions activerecord/test/cases/base_test.rb
Expand Up @@ -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.