diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6ccec9e --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/.bundle/config +/bin +/bundle +/test/*.db diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..9a746ec --- /dev/null +++ b/Gemfile @@ -0,0 +1,5 @@ +source :rubygems +gem 'rake' +gem 'flexmock' +gem 'activerecord', '2.3.10' +gem 'sqlite3' diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..ba20d97 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,18 @@ +GEM + remote: http://rubygems.org/ + specs: + activerecord (2.3.10) + activesupport (= 2.3.10) + activesupport (2.3.10) + flexmock (0.9.0) + rake (0.9.2) + sqlite3 (1.3.3) + +PLATFORMS + ruby + +DEPENDENCIES + activerecord (= 2.3.10) + flexmock + rake + sqlite3 diff --git a/data_fabric.gemspec b/data_fabric.gemspec index 0c74788..50e3f19 100644 --- a/data_fabric.gemspec +++ b/data_fabric.gemspec @@ -1,4 +1,4 @@ -require './lib/data_fabric/version' +require File.expand_path('../lib/data_fabric/version', __FILE__) Gem::Specification.new do |s| s.version = DataFabric::Version::STRING diff --git a/example23/.gitignore b/example23/.gitignore new file mode 100644 index 0000000..3d9d59e --- /dev/null +++ b/example23/.gitignore @@ -0,0 +1,6 @@ +/.bundle/config +/bin +/db/*.sqlite3 +/db/schema.rb +/log +/vendor diff --git a/example23/Gemfile b/example23/Gemfile new file mode 100644 index 0000000..73d1519 --- /dev/null +++ b/example23/Gemfile @@ -0,0 +1,5 @@ +source :rubygems +gem 'rake' +gem 'rails', '2.3.10' +gem "data_fabric", :path => File.expand_path('../../', __FILE__) +gem 'sqlite3-ruby' diff --git a/example23/Gemfile.lock b/example23/Gemfile.lock new file mode 100644 index 0000000..330ce00 --- /dev/null +++ b/example23/Gemfile.lock @@ -0,0 +1,39 @@ +PATH + remote: /Users/jason/projects/data_fabric + specs: + data_fabric (1.3.2) + +GEM + remote: http://rubygems.org/ + specs: + actionmailer (2.3.10) + actionpack (= 2.3.10) + actionpack (2.3.10) + activesupport (= 2.3.10) + rack (~> 1.1.0) + activerecord (2.3.10) + activesupport (= 2.3.10) + activeresource (2.3.10) + activesupport (= 2.3.10) + activesupport (2.3.10) + rack (1.1.2) + rails (2.3.10) + actionmailer (= 2.3.10) + actionpack (= 2.3.10) + activerecord (= 2.3.10) + activeresource (= 2.3.10) + activesupport (= 2.3.10) + rake (>= 0.8.3) + rake (0.9.2) + sqlite3 (1.3.3) + sqlite3-ruby (1.3.3) + sqlite3 (>= 1.3.3) + +PLATFORMS + ruby + +DEPENDENCIES + data_fabric! + rails (= 2.3.10) + rake + sqlite3-ruby diff --git a/example23/Rakefile b/example23/Rakefile index 06e3529..b62b7d6 100644 --- a/example23/Rakefile +++ b/example23/Rakefile @@ -47,12 +47,7 @@ task :test do end namespace :app do - task :prepare => [:clean, :copy_plugin, :migrate] - - task :copy_plugin do - mkdir_p 'vendor/gems/data_fabric-1.0.0' - cp_r '../lib', 'vendor/gems/data_fabric-1.0.0' - end + task :prepare => [:clean, :migrate] task :clean do rm_rf 'log' diff --git a/example23/config/boot.rb b/example23/config/boot.rb index 0a51688..45f8e44 100644 --- a/example23/config/boot.rb +++ b/example23/config/boot.rb @@ -105,5 +105,19 @@ def read_environment_rb end end +class Rails::Boot + def run + load_initializer + + Rails::Initializer.class_eval do + def load_gems + @bundler_loaded ||= Bundler.require :default, Rails.env + end + end + + Rails::Initializer.run(:set_load_path) + end +end + # All that for this: Rails.boot! diff --git a/example23/config/preinitializer.rb b/example23/config/preinitializer.rb new file mode 100644 index 0000000..3ad0241 --- /dev/null +++ b/example23/config/preinitializer.rb @@ -0,0 +1,20 @@ +begin + require "rubygems" + require "bundler" +rescue LoadError + raise "Could not load the bundler gem. Install it with `gem install bundler`." +end + +if Gem::Version.new(Bundler::VERSION) <= Gem::Version.new("0.9.24") + raise RuntimeError, "Your bundler version is too old for Rails 2.3." + + "Run `gem install bundler` to upgrade." +end + +begin + # Set up load paths for all bundled gems + ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", __FILE__) + Bundler.setup +rescue Bundler::GemNotFound + raise RuntimeError, "Bundler couldn't find some gems." + + "Did you run `bundle install`?" +end diff --git a/example30/.gitignore b/example30/.gitignore index af64fae..0b25597 100644 --- a/example30/.gitignore +++ b/example30/.gitignore @@ -2,3 +2,6 @@ db/*.sqlite3 log/*.log tmp/**/* +/bin +/db/schema.rb +/vendor/bundle diff --git a/lib/data_fabric.rb b/lib/data_fabric.rb index 6614a20..3978381 100644 --- a/lib/data_fabric.rb +++ b/lib/data_fabric.rb @@ -2,7 +2,7 @@ require 'active_record/version' require 'active_record/connection_adapters/abstract/connection_pool' require 'active_record/connection_adapters/abstract/connection_specification' -require 'data_fabric/version' +require File.expand_path('../data_fabric/version', __FILE__) # DataFabric adds a new level of flexibility to ActiveRecord connection handling. # You need to describe the topology for your database infrastructure in your model(s). As with ActiveRecord normally, different models can use different topologies. diff --git a/lib/data_fabric/connection_proxy.rb b/lib/data_fabric/connection_proxy.rb index a1a02c6..86ac2ae 100644 --- a/lib/data_fabric/connection_proxy.rb +++ b/lib/data_fabric/connection_proxy.rb @@ -120,7 +120,11 @@ def current_pool self.class.shard_pools[name] ||= begin config = ActiveRecord::Base.configurations[name] raise ArgumentError, "Unknown database config: #{name}, have #{ActiveRecord::Base.configurations.inspect}" unless config - ActiveRecord::ConnectionAdapters::ConnectionPool.new(spec_for(config)) + n, existing_equivalent_connection = self.class.shard_pools.detect do |name, conn| + config.stringify_keys == conn.spec.config.stringify_keys + end + existing_equivalent_connection || + ActiveRecord::ConnectionAdapters::ConnectionPool.new(spec_for(config)) end end @@ -158,7 +162,7 @@ def connection_name_builder clauses << @prefix if @prefix clauses << @shard_group if @shard_group clauses << StringProxy.new { DataFabric.active_shard(@shard_group) } if @shard_group - clauses << RAILS_ENV + clauses << ::Rails.env clauses << StringProxy.new { current_role } if @replicated clauses end @@ -177,4 +181,4 @@ def master end end -end \ No newline at end of file +end diff --git a/lib/data_fabric/version.rb b/lib/data_fabric/version.rb index ed302fb..a559dca 100644 --- a/lib/data_fabric/version.rb +++ b/lib/data_fabric/version.rb @@ -1,5 +1,5 @@ module DataFabric module Version - STRING = '1.3.2' + STRING = '1.3.2.2' end end diff --git a/test/database.yml b/test/database.yml index 58c0825..270363a 100644 --- a/test/database.yml +++ b/test/database.yml @@ -22,3 +22,11 @@ fiveruns_city_dallas_test_master: fiveruns_city_dallas_test_slave: adapter: sqlite3 database: test/vr_dallas_slave.db + +fiveruns_city_austin_burb_test_master: + adapter: sqlite3 + database: test/vr_austin_master.db + +fiveruns_city_austin_burb_test_slave: + adapter: sqlite3 + database: test/vr_austin_slave.db diff --git a/test/database_test.rb b/test/database_test.rb index e025f83..07adc3b 100644 --- a/test/database_test.rb +++ b/test/database_test.rb @@ -51,4 +51,45 @@ def test_live_burrito end end end + + def test_we_reuse_connections + [:austin, :dallas].each do |city| + DataFabric.activate_shard :city => city do + assert_equal "fiveruns_city_#{city}_test_slave", TheWholeBurrito.connection.connection_name, "city: #{city}" + assert_equal DataFabric::PoolProxy, TheWholeBurrito.connection_pool.class, "city: #{city}" + assert !TheWholeBurrito.connected?, "city: #{city}" + + # Should use the slave + burrito = TheWholeBurrito.find(1) + assert_match "vr_#{city}_slave", burrito.name, "city: #{city}" + + assert TheWholeBurrito.connected?, "city: #{city}" + end + end + + # Since the burb uses the same db as austin we should re-use that connection instead of creating a new one + city = :austin_burb + DataFabric.activate_shard :city => city do + assert_equal "fiveruns_city_#{city}_test_slave", TheWholeBurrito.connection.connection_name, "city: #{city}" + assert_equal DataFabric::PoolProxy, TheWholeBurrito.connection_pool.class, "city: #{city}" + assert TheWholeBurrito.connected?, "city: #{city}" + + # Should use the slave + burrito = TheWholeBurrito.find(1) + assert_match "vr_austin_slave", burrito.name, "city: #{city}" + + assert TheWholeBurrito.connected?, "city: #{city}" + end + + db_connections = [] + [:austin, :dallas, :austin_burb].each do |city| + DataFabric.activate_shard(:city => city) do + db_connections << TheWholeBurrito.connection.connection + end + end + db_connections = db_connections.uniq + + # We should only have 2 db connections since there are 2 uniq dbs + assert_equal 2, db_connections.size + end end