activerecord-turntable 1.1.2 → 2.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (144) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -0
  3. data/.travis.yml +3 -5
  4. data/CHANGELOG.md +70 -0
  5. data/Guardfile +7 -5
  6. data/README.md +490 -0
  7. data/Rakefile +37 -22
  8. data/activerecord-turntable.gemspec +37 -34
  9. data/gemfiles/rails4_0.gemfile +6 -0
  10. data/gemfiles/rails4_1.gemfile +6 -0
  11. data/lib/active_record/turntable/active_record_ext/abstract_adapter.rb +14 -29
  12. data/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb +45 -0
  13. data/lib/active_record/turntable/active_record_ext/acts_as_archive_extension.rb +21 -0
  14. data/lib/active_record/turntable/active_record_ext/association.rb +85 -0
  15. data/lib/active_record/turntable/active_record_ext/association_preloader.rb +37 -0
  16. data/lib/active_record/turntable/active_record_ext/clever_load.rb +33 -76
  17. data/lib/active_record/turntable/active_record_ext/connection_handler_extension.rb +31 -0
  18. data/lib/active_record/turntable/active_record_ext/database_tasks.rb +81 -0
  19. data/lib/active_record/turntable/active_record_ext/fixtures.rb +54 -42
  20. data/lib/active_record/turntable/active_record_ext/locking_optimistic.rb +101 -0
  21. data/lib/active_record/turntable/active_record_ext/log_subscriber.rb +28 -46
  22. data/lib/active_record/turntable/active_record_ext/migration_proxy.rb +7 -0
  23. data/lib/active_record/turntable/active_record_ext/persistence.rb +96 -94
  24. data/lib/active_record/turntable/active_record_ext/relation.rb +31 -0
  25. data/lib/active_record/turntable/active_record_ext/schema_dumper.rb +18 -28
  26. data/lib/active_record/turntable/active_record_ext/transactions.rb +9 -3
  27. data/lib/active_record/turntable/active_record_ext.rb +26 -11
  28. data/lib/active_record/turntable/algorithm/base.rb +1 -1
  29. data/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb +1 -1
  30. data/lib/active_record/turntable/algorithm.rb +7 -3
  31. data/lib/active_record/turntable/base.rb +67 -14
  32. data/lib/active_record/turntable/cluster.rb +46 -2
  33. data/lib/active_record/turntable/config.rb +1 -1
  34. data/lib/active_record/turntable/connection_proxy/mixable.rb +7 -29
  35. data/lib/active_record/turntable/connection_proxy.rb +61 -72
  36. data/lib/active_record/turntable/error.rb +5 -6
  37. data/lib/active_record/turntable/helpers.rb +5 -1
  38. data/lib/active_record/turntable/migration.rb +9 -49
  39. data/lib/active_record/turntable/mixer/fader/calculate_shards_sum_result.rb +13 -2
  40. data/lib/active_record/turntable/mixer/fader/select_shards_merge_result.rb +17 -6
  41. data/lib/active_record/turntable/mixer/fader/specified_shard.rb +3 -1
  42. data/lib/active_record/turntable/mixer/fader.rb +12 -10
  43. data/lib/active_record/turntable/mixer.rb +59 -29
  44. data/lib/active_record/turntable/plugin.rb +6 -0
  45. data/lib/active_record/turntable/pool_proxy.rb +12 -19
  46. data/lib/active_record/turntable/rack/query_cache.rb +20 -23
  47. data/lib/active_record/turntable/rack.rb +4 -2
  48. data/lib/active_record/turntable/railtie.rb +4 -3
  49. data/lib/active_record/turntable/railties/databases.rake +81 -122
  50. data/lib/active_record/turntable/seq_shard.rb +1 -1
  51. data/lib/active_record/turntable/sequencer/api.rb +1 -1
  52. data/lib/active_record/turntable/sequencer/barrage.rb +28 -0
  53. data/lib/active_record/turntable/sequencer.rb +27 -9
  54. data/lib/active_record/turntable/shard.rb +2 -2
  55. data/lib/active_record/turntable/sql_tree_patch.rb +1 -1
  56. data/lib/active_record/turntable/version.rb +1 -1
  57. data/lib/active_record/turntable.rb +26 -16
  58. data/lib/generators/templates/turntable.yml +9 -7
  59. data/spec/active_record/turntable/active_record_ext/association_preloader_spec.rb +78 -0
  60. data/spec/active_record/turntable/active_record_ext/association_spec.rb +72 -0
  61. data/spec/active_record/turntable/active_record_ext/clever_load_spec.rb +25 -46
  62. data/spec/active_record/turntable/active_record_ext/locking_optimistic_spec.rb +28 -0
  63. data/spec/active_record/turntable/active_record_ext/persistence_spec.rb +46 -25
  64. data/spec/active_record/turntable/algorithm/range_algorithm_spec.rb +4 -4
  65. data/spec/active_record/turntable/algorithm/range_bsearch_algorithm_spec.rb +35 -0
  66. data/spec/active_record/turntable/algorithm_spec.rb +28 -12
  67. data/spec/active_record/turntable/base_spec.rb +1 -1
  68. data/spec/active_record/turntable/cluster_spec.rb +27 -5
  69. data/spec/active_record/turntable/config_spec.rb +2 -2
  70. data/spec/active_record/turntable/connection_proxy_spec.rb +112 -45
  71. data/spec/active_record/turntable/finder_spec.rb +24 -11
  72. data/spec/active_record/turntable/mixer_spec.rb +21 -21
  73. data/spec/active_record/turntable/rack/query_cache_spec.rb +19 -0
  74. data/spec/active_record/turntable/sequencer/api_spec.rb +38 -0
  75. data/spec/active_record/turntable/sequencer/barrage_spec.rb +22 -0
  76. data/spec/active_record/turntable/sequencer/mysql_spec.rb +22 -0
  77. data/spec/active_record/turntable/shard_spec.rb +1 -1
  78. data/spec/active_record/turntable/transaction_spec.rb +35 -0
  79. data/spec/active_record/turntable_spec.rb +4 -4
  80. data/spec/config/database.yml +24 -34
  81. data/spec/config/turntable.yml +18 -1
  82. data/spec/fabricators/turntable_fabricator.rb +0 -2
  83. data/spec/models/card.rb +3 -0
  84. data/spec/models/cards_user.rb +10 -0
  85. data/spec/models/cards_users_histories.rb +7 -0
  86. data/spec/models/events_users_history.rb +7 -0
  87. data/spec/models/user.rb +7 -0
  88. data/spec/models/user_status.rb +6 -0
  89. data/spec/spec_helper.rb +10 -4
  90. data/spec/support/matchers/be_saved_to.rb +6 -0
  91. data/spec/support/turntable_helper.rb +29 -0
  92. metadata +124 -74
  93. data/README.rdoc +0 -294
  94. data/gemfiles/rails3_0.gemfile +0 -7
  95. data/gemfiles/rails3_1.gemfile +0 -6
  96. data/gemfiles/rails3_2.gemfile +0 -6
  97. data/lib/active_record/turntable/compatible.rb +0 -19
  98. data/sample_app/.gitignore +0 -16
  99. data/sample_app/Gemfile +0 -41
  100. data/sample_app/README.rdoc +0 -261
  101. data/sample_app/Rakefile +0 -7
  102. data/sample_app/app/assets/images/rails.png +0 -0
  103. data/sample_app/app/assets/javascripts/application.js +0 -15
  104. data/sample_app/app/assets/stylesheets/application.css +0 -13
  105. data/sample_app/app/controllers/application_controller.rb +0 -3
  106. data/sample_app/app/helpers/application_helper.rb +0 -2
  107. data/sample_app/app/mailers/.gitkeep +0 -0
  108. data/sample_app/app/models/.gitkeep +0 -0
  109. data/sample_app/app/models/user.rb +0 -4
  110. data/sample_app/app/views/layouts/application.html.erb +0 -14
  111. data/sample_app/config/application.rb +0 -65
  112. data/sample_app/config/boot.rb +0 -6
  113. data/sample_app/config/database.yml +0 -70
  114. data/sample_app/config/environment.rb +0 -5
  115. data/sample_app/config/environments/development.rb +0 -37
  116. data/sample_app/config/environments/production.rb +0 -67
  117. data/sample_app/config/environments/test.rb +0 -37
  118. data/sample_app/config/initializers/backtrace_silencers.rb +0 -7
  119. data/sample_app/config/initializers/inflections.rb +0 -15
  120. data/sample_app/config/initializers/mime_types.rb +0 -5
  121. data/sample_app/config/initializers/secret_token.rb +0 -7
  122. data/sample_app/config/initializers/session_store.rb +0 -8
  123. data/sample_app/config/initializers/wrap_parameters.rb +0 -14
  124. data/sample_app/config/locales/en.yml +0 -5
  125. data/sample_app/config/routes.rb +0 -58
  126. data/sample_app/config/turntable.yml +0 -64
  127. data/sample_app/config.ru +0 -4
  128. data/sample_app/db/migrate/20120316073058_create_users.rb +0 -11
  129. data/sample_app/db/seeds.rb +0 -7
  130. data/sample_app/lib/assets/.gitkeep +0 -0
  131. data/sample_app/lib/tasks/.gitkeep +0 -0
  132. data/sample_app/log/.gitkeep +0 -0
  133. data/sample_app/public/404.html +0 -26
  134. data/sample_app/public/422.html +0 -26
  135. data/sample_app/public/500.html +0 -25
  136. data/sample_app/public/favicon.ico +0 -0
  137. data/sample_app/public/index.html +0 -241
  138. data/sample_app/public/robots.txt +0 -5
  139. data/sample_app/script/rails +0 -6
  140. data/sample_app/vendor/assets/javascripts/.gitkeep +0 -0
  141. data/sample_app/vendor/assets/stylesheets/.gitkeep +0 -0
  142. data/sample_app/vendor/plugins/.gitkeep +0 -0
  143. data/spec/test_models.rb +0 -27
  144. data/spec/turntable_helper.rb +0 -29
data/Rakefile CHANGED
@@ -7,6 +7,9 @@ RSpec::Core::RakeTask.new(:spec) do |spec|
7
7
  spec.pattern = FileList['spec/**/*_spec.rb']
8
8
  end
9
9
 
10
+ require 'active_record'
11
+ require "active_record/turntable/active_record_ext/database_tasks"
12
+
10
13
  namespace :turntable do
11
14
  namespace :db do
12
15
  task :rails_env do
@@ -16,32 +19,34 @@ namespace :turntable do
16
19
  end
17
20
 
18
21
  task :load_config => :rails_env do
19
- require 'active_record'
20
- ActiveRecord::Base.configurations = YAML.load_file(File.join(File.dirname(__FILE__), 'spec/config/database.yml'))
22
+ yaml_file = File.join(File.dirname(__FILE__), 'spec/config/database.yml')
23
+ ActiveRecord::Base.configurations = YAML.load ERB.new(IO.read(yaml_file)).result
21
24
  end
22
25
 
23
26
  desc "create turntable test database"
24
27
  task :create => :load_config do
25
- database_configs = [ActiveRecord::Base.configurations[RAILS_ENV]] + ActiveRecord::Base.configurations[RAILS_ENV]["shards"].values + ActiveRecord::Base.configurations[RAILS_ENV]["seq"].values
26
- database_configs.each do |dbconf|
27
- command = "mysql "
28
- command << "-u #{dbconf["username"]} " if dbconf["username"]
29
- command << "-p#{dbconf["password"]} " if dbconf["password"]
30
- command << "-h #{dbconf["host"]}" if dbconf["host"]
31
- %x{ echo "CREATE DATABASE #{dbconf["database"]}" | #{command} }
32
- end
28
+ ActiveRecord::Tasks::DatabaseTasks.create_current(RAILS_ENV)
29
+ ActiveRecord::Tasks::DatabaseTasks.create_current_turntable_cluster(RAILS_ENV)
30
+ end
31
+
32
+ desc "drop turntable test database"
33
+ task :drop => :load_config do
34
+ ActiveRecord::Tasks::DatabaseTasks.drop_current(RAILS_ENV)
35
+ ActiveRecord::Tasks::DatabaseTasks.drop_current_turntable_cluster(RAILS_ENV)
33
36
  end
34
37
 
35
38
  desc "migrate turntable test tables"
36
39
  task :migrate => :load_config do
37
- ActiveRecord::Base.establish_connection RAILS_ENV
40
+ ActiveRecord::Base.establish_connection RAILS_ENV.to_sym
38
41
  require 'active_record/turntable'
39
42
  ActiveRecord::Base.send(:include, ActiveRecord::Turntable)
40
43
  ActiveRecord::ConnectionAdapters::SchemaStatements.send(:include, ActiveRecord::Turntable::Migration::SchemaStatementsExt)
41
- database_configs = [ActiveRecord::Base.configurations[RAILS_ENV]] + ActiveRecord::Base.configurations[RAILS_ENV]["shards"].values + ActiveRecord::Base.configurations[RAILS_ENV]["seq"].values
42
44
 
43
- database_configs.each do |dbconf|
44
- ActiveRecord::Base.establish_connection dbconf
45
+ configurations = [ActiveRecord::Base.configurations[RAILS_ENV]]
46
+ configurations += ActiveRecord::Tasks::DatabaseTasks.current_turntable_cluster_configurations(RAILS_ENV).map {|v| v[1]}.flatten.uniq
47
+
48
+ configurations.each do |configuration|
49
+ ActiveRecord::Base.establish_connection configuration
45
50
 
46
51
  ActiveRecord::Base.connection.create_table :users do |t|
47
52
  t.string :nickname
@@ -56,6 +61,7 @@ namespace :turntable do
56
61
  t.belongs_to :user, :null => false
57
62
  t.integer :hp, :null => false, :default => 0
58
63
  t.integer :mp, :null => false, :default => 0
64
+ t.integer :lock_version, :null => false, :default => 0
59
65
  t.datetime :deleted_at, :default => nil
60
66
  t.timestamps
61
67
  end
@@ -89,21 +95,30 @@ namespace :turntable do
89
95
  t.datetime :deleted_at, :default => nil
90
96
  end
91
97
  ActiveRecord::Base.connection.create_sequence_for :archived_cards_users
98
+
99
+ ActiveRecord::Base.connection.create_table :cards_users_histories do |t|
100
+ t.belongs_to :cards_user, :null => false
101
+ t.belongs_to :user, :null => false
102
+ t.timestamps
103
+ end
104
+ ActiveRecord::Base.connection.create_sequence_for :cards_users_histories
105
+
106
+ ActiveRecord::Base.connection.create_table :events_users_histories do |t|
107
+ t.belongs_to :events_user, :null => false
108
+ t.belongs_to :cards_user, :null => false
109
+ t.belongs_to :user, :null => false
110
+ t.timestamps
111
+ end
112
+ ActiveRecord::Base.connection.create_sequence_for :events_users_histories
92
113
  end
93
114
  end
94
115
 
95
116
  desc "drop turntable test database"
96
117
  task :drop => :load_config do
97
- database_configs = [ActiveRecord::Base.configurations[RAILS_ENV]] + ActiveRecord::Base.configurations[RAILS_ENV]["shards"].values + ActiveRecord::Base.configurations[RAILS_ENV]["seq"].values
98
- database_configs.each do |dbconf|
99
- command = "mysql "
100
- command << "-u #{dbconf["username"]} " if dbconf["username"]
101
- command << "-p#{dbconf["password"]} " if dbconf["password"]
102
- command << "-h #{dbconf["host"]}" if dbconf["host"]
103
- %x{ echo "DROP DATABASE #{dbconf["database"]}" | #{command} }
104
- end
118
+ ActiveRecord::Tasks::DatabaseTasks.drop_current_turntable_cluster(RAILS_ENV)
105
119
  end
106
120
 
121
+ desc "reset turntable test databases"
107
122
  task :reset => ["turntable:db:drop", "turntable:db:create", "turntable:db:migrate"]
108
123
  end
109
124
  end
@@ -1,48 +1,51 @@
1
1
  $:.push File.expand_path("../lib", __FILE__)
2
2
  require "active_record/turntable/version"
3
3
 
4
- Gem::Specification.new do |s|
5
- s.name = "activerecord-turntable"
6
- s.version = ActiveRecord::Turntable::VERSION
7
- s.authors = ["gussan"]
8
- s.homepage = "https://github.com/drecom/activerecord-turntable"
9
- s.summary = %q{ActiveRecord Sharding plugin}
10
- s.description = %q{ActiveRecord Sharding plugin}
4
+ Gem::Specification.new do |spec|
5
+ spec.name = "activerecord-turntable"
6
+ spec.version = ActiveRecord::Turntable::VERSION
7
+ spec.authors = ["gussan", "sue445"]
8
+ spec.homepage = "https://github.com/drecom/activerecord-turntable"
9
+ spec.summary = %q{ActiveRecord sharding extension}
10
+ spec.description = %q{ActiveRecord sharding extension}
11
+ spec.license = "MIT"
11
12
 
12
- s.rubyforge_project = "activerecord-turntable"
13
- s.extra_rdoc_files = [
13
+ spec.rubyforge_project = "activerecord-turntable"
14
+ spec.extra_rdoc_files = [
14
15
  "LICENSE.txt",
15
- "README.rdoc",
16
+ "README.md",
16
17
  "CHANGELOG.md"
17
18
  ]
18
19
 
19
- s.files = `git ls-files | grep -v "^spec"`.split("\n")
20
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
- s.require_paths = ["lib"]
23
- s.licenses = ["MIT"]
24
- s.rubygems_version = "1.8.16"
20
+ spec.files = `git ls-files`.split($/)
21
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
22
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
23
+ spec.require_paths = ["lib"]
25
24
 
26
- # runtime dependencies
27
- s.add_runtime_dependency(%q<activerecord>, [">= 3.0.0"])
28
- s.add_runtime_dependency(%q<activesupport>, [">=3.0.0"])
29
- s.add_runtime_dependency(%q<sql_tree>, ["= 0.2.0"])
30
- s.add_runtime_dependency(%q<bsearch>, ["~> 1.5"])
31
- s.add_runtime_dependency(%q<httpclient>, [">= 0"])
25
+ spec.add_dependency "activerecord", ">= 4.0.0"
26
+ spec.add_dependency "activesupport", ">= 4.0.0"
27
+ spec.add_dependency "sql_tree", "= 0.2.0"
28
+ spec.add_dependency "bsearch", "~> 1.5"
29
+ spec.add_dependency "httpclient", ">= 0"
32
30
 
33
- # development dependencies
34
- s.add_development_dependency(%q<rake>, ["~> 10.0.3"])
35
- s.add_development_dependency(%q<rspec>, [">= 0"])
36
- s.add_development_dependency(%q<rr>, [">= 0"])
37
- s.add_development_dependency(%q<mysql2>, [">= 0"])
38
- s.add_development_dependency(%q<fabrication>, [">= 0"])
39
- s.add_development_dependency(%q<faker>, [">= 0"])
40
- s.add_development_dependency(%q<activerecord-import>, [">= 0"])
41
- s.add_development_dependency(%q<pry>, [">= 0"])
42
- s.add_development_dependency(%q<guard-rspec>, [">= 0"])
43
- s.add_development_dependency(%q<coveralls>, [">= 0"])
31
+ # optional dependencies
32
+ spec.add_development_dependency "activerecord-import"
33
+ spec.add_development_dependency "barrage"
34
+ spec.add_development_dependency "mysql2"
35
+
36
+ spec.add_development_dependency "rake"
37
+ spec.add_development_dependency "rack"
38
+ spec.add_development_dependency "rspec", "~> 3.1.0"
39
+ spec.add_development_dependency "rspec-its"
40
+ spec.add_development_dependency "rspec-collection_matchers"
41
+ spec.add_development_dependency "fabrication"
42
+ spec.add_development_dependency "faker"
43
+ spec.add_development_dependency "webmock"
44
+ spec.add_development_dependency "pry"
45
+ spec.add_development_dependency "guard-rspec"
46
+ spec.add_development_dependency "coveralls"
44
47
 
45
48
  if RUBY_PLATFORM =~ /darwin/
46
- s.add_development_dependency(%q<growl>, [">= 0"])
49
+ spec.add_development_dependency "growl"
47
50
  end
48
51
  end
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem 'activerecord', "~> 4.0.0"
4
+ gem 'activesupport', "~> 4.0.0"
5
+
6
+ gemspec :path => '../'
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem 'activerecord', "~> 4.1.0"
4
+ gem 'activesupport', "~> 4.1.0"
5
+
6
+ gemspec :path => '../'
@@ -6,35 +6,20 @@ module ActiveRecord::Turntable
6
6
  included do
7
7
  protected
8
8
 
9
- if ActiveRecord::VERSION::STRING < '3.1'
10
- def log(sql, name)
11
- name ||= "SQL"
12
- @instrumenter.instrument("sql.active_record",
13
- :sql => sql, :name => name, :connection_id => object_id,
14
- :turntable_shard_name => turntable_shard_name) do
15
- yield
16
- end
17
- rescue Exception => e
18
- message = "#{e.class.name}: #{e.message}: #{sql} : #{turntable_shard_name}"
19
- @logger.debug message if @logger
20
- raise translate_exception(e, message)
21
- end
22
- else
23
- def log(sql, name = "SQL", binds = [])
24
- @instrumenter.instrument(
25
- "sql.active_record",
26
- :sql => sql,
27
- :name => name,
28
- :connection_id => object_id,
29
- :binds => binds,
30
- :turntable_shard_name => turntable_shard_name) { yield }
31
- rescue Exception => e
32
- message = "#{e.class.name}: #{e.message}: #{sql} : #{turntable_shard_name}"
33
- @logger.debug message if @logger
34
- exception = translate_exception(e, message)
35
- exception.set_backtrace e.backtrace
36
- raise exception
37
- end
9
+ def log(sql, name = "SQL", binds = [])
10
+ @instrumenter.instrument(
11
+ "sql.active_record",
12
+ :sql => sql,
13
+ :name => name,
14
+ :connection_id => object_id,
15
+ :binds => binds,
16
+ :turntable_shard_name => turntable_shard_name) { yield }
17
+ rescue Exception => e
18
+ message = "#{e.class.name}: #{e.message}: #{sql} : #{turntable_shard_name}"
19
+ @logger.debug message if @logger
20
+ exception = translate_exception(e, message)
21
+ exception.set_backtrace e.backtrace
22
+ raise exception
38
23
  end
39
24
  end
40
25
 
@@ -0,0 +1,45 @@
1
+ module ActiveRecord::Turntable
2
+ module ActiveRecordExt
3
+ module ActiverecordImportExt
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ alias_method_chain :values_sql_for_columns_and_attributes, :turntable
8
+ end
9
+
10
+ private
11
+
12
+ def values_sql_for_columns_and_attributes_with_turntable(columns, array_of_attributes)
13
+ connection_memo = connection
14
+ array_of_attributes.map do |arr|
15
+ my_values = arr.each_with_index.map do |val,j|
16
+ column = columns[j]
17
+
18
+ # be sure to query sequence_name *last*, only if cheaper tests fail, because it's costly
19
+ if val.nil? && column.name == primary_key && !sequence_name.blank?
20
+ if sequencer_enabled?
21
+ connection_memo.next_sequence_value(sequence_name)
22
+ else
23
+ connection_memo.next_value_for_sequence(sequence_name)
24
+ end
25
+ else
26
+ if serialized_attributes.include?(column.name)
27
+ connection_memo.quote(serialized_attributes[column.name].dump(val), column)
28
+ else
29
+ connection_memo.quote(val, column)
30
+ end
31
+ end
32
+ end
33
+ "(#{my_values.join(',')})"
34
+ end
35
+ end
36
+ end
37
+
38
+ begin
39
+ require 'activerecord-import'
40
+ require 'activerecord-import/base'
41
+ (class << ActiveRecord::Base; self; end).send(:include, ActiverecordImportExt)
42
+ rescue LoadError
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,21 @@
1
+ begin
2
+ require 'acts_as_archive'
3
+
4
+ class ActsAsArchive
5
+ class << self
6
+ def move_with_turntable(config, where, merge_options={})
7
+ if [config[:to], config[:from]].all? { |k| k.try(:turntable_enabled?) }
8
+ current_shard = config[:from].connection.current_shard.name.to_sym
9
+ config[:to].connection.with_shard(current_shard) {
10
+ move_without_turntable(config, where, merge_options)
11
+ }
12
+ else
13
+ move_without_turntable(config, where, merge_options)
14
+ end
15
+ end
16
+
17
+ alias_method_chain :move, :turntable
18
+ end
19
+ end
20
+ rescue LoadError
21
+ end
@@ -0,0 +1,85 @@
1
+ require 'active_record/associations'
2
+
3
+ module ActiveRecord::Turntable
4
+ module ActiveRecordExt
5
+ module Association
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ ActiveRecord::Associations::SingularAssociation.send(:include, SingularAssociationExt)
10
+ ActiveRecord::Associations::CollectionAssociation.send(:include, CollectionAssociationExt)
11
+ ActiveRecord::Associations::Builder::Association.valid_options += [:foreign_shard_key]
12
+ end
13
+
14
+ module SingularAssociationExt
15
+ extend ActiveSupport::Concern
16
+
17
+ included do
18
+ alias_method_chain :find_target, :turntable
19
+ end
20
+
21
+ private
22
+
23
+ if ActiveRecord::Turntable.rails41_later?
24
+ def find_target_with_turntable
25
+ current_scope = scope
26
+ if should_use_shard_key?
27
+ current_scope = current_scope.where(klass.turntable_shard_key => owner.send(foreign_shard_key))
28
+ end
29
+ if record = current_scope.take
30
+ set_inverse_instance record
31
+ end
32
+ end
33
+ else
34
+ def find_target_with_turntable
35
+ current_scope = scope
36
+ if should_use_shard_key?
37
+ current_scope = current_scope.where(klass.turntable_shard_key => owner.send(foreign_shard_key))
38
+ end
39
+ current_scope.take.tap { |record| set_inverse_instance(record) }
40
+ end
41
+ end
42
+ end
43
+
44
+ module CollectionAssociationExt
45
+ extend ActiveSupport::Concern
46
+
47
+ included do
48
+ alias_method_chain :find_target, :turntable
49
+ end
50
+
51
+ private
52
+
53
+ def find_target_with_turntable
54
+ records =
55
+ if options[:finder_sql]
56
+ reflection.klass.find_by_sql(custom_finder_sql)
57
+ else
58
+ current_scope = scope
59
+ if should_use_shard_key?
60
+ current_scope = current_scope.where(klass.turntable_shard_key => owner.send(foreign_shard_key))
61
+ end
62
+ current_scope.to_a
63
+ end
64
+ records.each { |record| set_inverse_instance(record) }
65
+ records
66
+ end
67
+
68
+ end
69
+
70
+ private
71
+
72
+ def foreign_shard_key
73
+ options[:foreign_shard_key] || owner.turntable_shard_key
74
+ end
75
+
76
+ def should_use_shard_key?
77
+ same_association_shard_key? || !!options[:foreign_shard_key]
78
+ end
79
+
80
+ def same_association_shard_key?
81
+ owner.class.turntable_enabled? && klass.turntable_enabled? && foreign_shard_key == klass.turntable_shard_key
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,37 @@
1
+ require 'active_record/associations/preloader/association'
2
+
3
+ module ActiveRecord::Turntable
4
+ module ActiveRecordExt
5
+ module AssociationPreloader
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ alias_method_chain :records_for, :turntable
10
+ end
11
+
12
+ def records_for_with_turntable(ids)
13
+ returning_scope = records_for_without_turntable(ids)
14
+ if should_use_shard_key?
15
+ returning_scope = returning_scope.where(klass.turntable_shard_key => owners.map(&foreign_shard_key.to_sym).uniq)
16
+ end
17
+ returning_scope
18
+ end
19
+
20
+ private
21
+
22
+ def foreign_shard_key
23
+ options[:foreign_shard_key] || model.turntable_shard_key
24
+ end
25
+
26
+ def should_use_shard_key?
27
+ sharded_by_same_key? || !!options[:foreign_shard_key]
28
+ end
29
+
30
+ def sharded_by_same_key?
31
+ model.turntable_enabled? &&
32
+ klass.turntable_enabled? &&
33
+ model.turntable_shard_key == klass.turntable_shard_key
34
+ end
35
+ end
36
+ end
37
+ end
@@ -3,88 +3,45 @@ module ActiveRecord::Turntable::ActiveRecordExt
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  included do
6
- ActiveRecord::VERSION::STRING < '3.1' ?
7
- include(AR30):
8
- include(AR31)
9
-
10
6
  class << ActiveRecord::Base
11
- delegate :clever_load!, :to => :scoped
7
+ delegate :clever_load!, :to => :all
12
8
  end
13
9
  end
14
10
 
15
- module AR30
16
- def clever_load!(association_name)
17
- # load records
18
- records = self.to_a
19
- klass = records.first.class
20
- reflection = klass.reflections[association_name]
21
-
22
- if reflection
23
- foreign_class = reflection.klass
24
- foreign_objects = case reflection.macro
25
- when :has_one
26
- foreign_class.where(reflection.primary_key_name => records.map(&reflection.association_primary_key.to_sym).uniq)
27
- when :belongs_to
28
- foreign_class.where(reflection.association_primary_key => records.map(&reflection.primary_key_name.to_sym).uniq)
29
- else
30
- []
31
- end
32
-
33
- self.each do |obj|
34
- matched_object = case reflection.macro
35
- when :has_one
36
- foreign_objects.find {|fo|
37
- obj.send(reflection.association_primary_key) == fo.send(reflection.primary_key_name)
38
- }
39
- when :belongs_to
40
- foreign_objects.find {|fo|
41
- obj.send(reflection.primary_key_name) == fo.send(reflection.association_primary_key)
42
- }
43
- end
44
- association_proxy = obj.send("set_#{reflection.name}_target", matched_object)
45
- # TODO: set reverse_instance
46
- # association_proxy.send(:set_inverse_instance, matched_object, obj)
47
- end
48
- end
49
- records
50
- end
51
- end
52
-
53
- module AR31
54
- def clever_load!(association_name)
55
- # load records
56
- records = self.to_a
57
- klass = records.first.class
58
- reflection = klass.reflections[association_name]
59
-
60
- if reflection
61
- foreign_class = reflection.klass
62
- foreign_objects = case reflection.macro
63
- when :has_one
64
- foreign_class.where(reflection.foreign_key => records.map(&reflection.association_primary_key.to_sym).uniq)
65
- when :belongs_to
66
- foreign_class.where(reflection.association_primary_key => records.map(&reflection.foreign_key.to_sym).uniq)
67
- else
68
- []
69
- end
70
-
71
- self.each do |obj|
72
- matched_object = case reflection.macro
73
- when :has_one
74
- foreign_objects.find {|fo|
75
- obj.send(reflection.association_primary_key) == fo.send(reflection.foreign_key)
76
- }
77
- when :belongs_to
78
- foreign_objects.find {|fo|
79
- obj.send(reflection.foreign_key) == fo.send(reflection.association_primary_key)
80
- }
81
- end
82
- obj.association(association_name).target = matched_object
83
- obj.association(association_name).send(:set_inverse_instance, matched_object)
84
- end
11
+ def clever_load!(association_name)
12
+ # load records
13
+ records = self.to_a
14
+ klass = records.first.class
15
+ reflection = klass.reflections[association_name]
16
+
17
+ if reflection
18
+ foreign_class = reflection.klass
19
+ foreign_objects = case reflection.macro
20
+ when :has_one
21
+ foreign_class.where(reflection.foreign_key => records.map(&reflection.association_primary_key.to_sym).uniq)
22
+ when :belongs_to
23
+ foreign_class.where(reflection.association_primary_key => records.map(&reflection.foreign_key.to_sym).uniq)
24
+ else
25
+ []
26
+ end
27
+
28
+ self.each do |obj|
29
+ matched_object = case reflection.macro
30
+ when :has_one
31
+ foreign_objects.find {|fo|
32
+ obj.send(reflection.association_primary_key) == fo.send(reflection.foreign_key)
33
+ }
34
+ when :belongs_to
35
+ foreign_objects.find {|fo|
36
+ obj.send(reflection.foreign_key) == fo.send(reflection.association_primary_key)
37
+ }
38
+ end
39
+ obj.association(association_name).target = matched_object
40
+ obj.association(association_name).set_inverse_instance(matched_object) if matched_object
41
+ obj.association(association_name).loaded!
85
42
  end
86
- records
87
43
  end
44
+ records
88
45
  end
89
46
  end
90
47
  end
@@ -0,0 +1,31 @@
1
+ module ActiveRecord::Turntable
2
+ module ActiveRecordExt
3
+ module ConnectionHandlerExtension
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ alias_method_chain :pool_for, :turntable
8
+ end
9
+
10
+ private
11
+
12
+ def pool_for_with_turntable(owner)
13
+ owner_to_pool.fetch(owner.name) {
14
+ if ancestor_pool = pool_from_any_process_for(owner)
15
+ if ancestor_pool.is_a?(ActiveRecord::Turntable::PoolProxy)
16
+ # Use same PoolProxy object
17
+ owner_to_pool[owner.name] = ancestor_pool
18
+ else
19
+ # A connection was established in an ancestor process that must have
20
+ # subsequently forked. We can't reuse the connection, but we can copy
21
+ # the specification and establish a new connection with it.
22
+ establish_connection owner, ancestor_pool.spec
23
+ end
24
+ else
25
+ owner_to_pool[owner.name] = nil
26
+ end
27
+ }
28
+ end
29
+ end
30
+ end
31
+ end