From eda2388de8d5dd3a0ae6c4bfaa9c2e547914e7c2 Mon Sep 17 00:00:00 2001 From: gussan Date: Thu, 21 Apr 2016 15:08:40 +0900 Subject: [PATCH 001/125] Change required ruby version to 2.2.0 or later --- activerecord-turntable.gemspec | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/activerecord-turntable.gemspec b/activerecord-turntable.gemspec index efe805c5..babd19e1 100644 --- a/activerecord-turntable.gemspec +++ b/activerecord-turntable.gemspec @@ -21,7 +21,7 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ["lib"] - spec.required_ruby_version = '>= 1.9.3' + spec.required_ruby_version = ">= 2.2" spec.add_runtime_dependency "activerecord", ">= 4.0.0", "< 5.0" spec.add_runtime_dependency "activesupport", ">= 4.0.0", "< 5.0" @@ -43,9 +43,7 @@ Gem::Specification.new do |spec| spec.add_development_dependency "faker" spec.add_development_dependency "webmock" spec.add_development_dependency "pry" - if RUBY_VERSION > "2.0" - spec.add_development_dependency "pry-byebug" - end + spec.add_development_dependency "pry-byebug" spec.add_development_dependency "guard-rspec" spec.add_development_dependency "coveralls" From 567d1d5707e66a8999435c37c156a5e374293652 Mon Sep 17 00:00:00 2001 From: gussan Date: Thu, 21 Apr 2016 15:12:53 +0900 Subject: [PATCH 002/125] Enable rubocop --- .rubocop.yml | 5 +++++ Guardfile | 5 +++++ activerecord-turntable.gemspec | 3 +++ 3 files changed, 13 insertions(+) create mode 100644 .rubocop.yml diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 00000000..fa5b2671 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,5 @@ +inherit_gem: + onkcop: "config/rubocop.yml" + +AllCops: + TargetRubyVersion: 2.2 diff --git a/Guardfile b/Guardfile index c4082ad1..8d9ab2bc 100644 --- a/Guardfile +++ b/Guardfile @@ -9,3 +9,8 @@ guard 'rspec', watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } watch('spec/spec_helper.rb') { "spec" } end + +guard :rubocop do + watch(%r{.+\.rb$}) + watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) } +end diff --git a/activerecord-turntable.gemspec b/activerecord-turntable.gemspec index babd19e1..f4634d3a 100644 --- a/activerecord-turntable.gemspec +++ b/activerecord-turntable.gemspec @@ -46,6 +46,9 @@ Gem::Specification.new do |spec| spec.add_development_dependency "pry-byebug" spec.add_development_dependency "guard-rspec" spec.add_development_dependency "coveralls" + spec.add_development_dependency "rubocop" + spec.add_development_dependency "onkcop" + spec.add_development_dependency "guard-rubocop" if RUBY_PLATFORM =~ /darwin/ spec.add_development_dependency "growl" From 60a61bc1b2959ae10eee327569b86329b7e8dd26 Mon Sep 17 00:00:00 2001 From: gussan Date: Thu, 21 Apr 2016 15:20:26 +0900 Subject: [PATCH 003/125] rubocop --auto-correct --- Guardfile | 14 +- Rakefile | 24 +- activerecord-turntable.gemspec | 12 +- lib/active_record/turntable.rb | 18 +- .../turntable/active_record_ext.rb | 8 +- .../active_record_ext/abstract_adapter.rb | 12 +- .../activerecord_import_ext.rb | 50 ++-- .../acts_as_archive_extension.rb | 4 +- .../active_record_ext/association.rb | 192 +++++++------- .../association_preloader.rb | 24 +- .../active_record_ext/clever_load.rb | 2 +- .../connection_handler_extension.rb | 32 +-- .../active_record_ext/database_tasks.rb | 18 +- .../turntable/active_record_ext/fixtures.rb | 34 +-- .../active_record_ext/locking_optimistic.rb | 1 - .../active_record_ext/log_subscriber.rb | 52 ++-- .../active_record_ext/migration_proxy.rb | 2 +- .../active_record_ext/persistence.rb | 22 +- .../turntable/active_record_ext/relation.rb | 14 +- .../active_record_ext/schema_dumper.rb | 149 ++++++----- .../active_record_ext/transactions.rb | 4 +- .../turntable/algorithm/range_algorithm.rb | 8 +- .../algorithm/range_bsearch_algorithm.rb | 10 +- lib/active_record/turntable/base.rb | 19 +- lib/active_record/turntable/cluster.rb | 17 +- .../turntable/cluster_helper_methods.rb | 6 +- lib/active_record/turntable/config.rb | 6 +- .../turntable/connection_proxy.rb | 45 ++-- .../turntable/connection_proxy/mixable.rb | 2 +- .../turntable/helpers/test_helper.rb | 8 +- lib/active_record/turntable/master_shard.rb | 6 +- lib/active_record/turntable/migration.rb | 26 +- lib/active_record/turntable/mixer.rb | 242 +++++++++--------- .../fader/calculate_shards_sum_result.rb | 14 +- .../mixer/fader/select_shards_merge_result.rb | 24 +- lib/active_record/turntable/plugin.rb | 2 +- lib/active_record/turntable/pool_proxy.rb | 16 +- .../turntable/rack/query_cache.rb | 18 +- lib/active_record/turntable/railtie.rb | 2 +- .../turntable/railties/databases.rake | 37 ++- lib/active_record/turntable/seq_shard.rb | 30 +-- lib/active_record/turntable/sequencer.rb | 24 +- lib/active_record/turntable/sequencer/api.rb | 10 +- .../turntable/sequencer/barrage.rb | 8 +- .../turntable/sequencer/mysql.rb | 4 +- lib/active_record/turntable/shard.rb | 38 +-- lib/active_record/turntable/sql_tree_patch.rb | 116 ++++----- lib/active_record/turntable/util.rb | 2 +- lib/active_record/turntable/version.rb | 2 +- lib/activerecord-turntable.rb | 4 +- script/performance/algorithm | 15 +- .../association_preloader_spec.rb | 8 +- .../active_record_ext/association_spec.rb | 4 +- .../active_record_ext/clever_load_spec.rb | 12 +- .../active_record_ext/fixture_set_spec.rb | 8 +- .../locking_optimistic_spec.rb | 2 +- .../active_record_ext/migration_spec.rb | 4 +- .../active_record_ext/persistence_spec.rb | 21 +- .../active_record_ext/sequencer_spec.rb | 2 +- .../active_record_ext/test_fixtures_spec.rb | 6 +- .../algorithm/modulo_algorithm_spec.rb | 5 +- .../algorithm/range_algorithm_spec.rb | 5 +- .../algorithm/range_bsearch_algorithm_spec.rb | 5 +- .../active_record/turntable/algorithm_spec.rb | 10 +- spec/active_record/turntable/base_spec.rb | 2 +- spec/active_record/turntable/cluster_spec.rb | 2 +- spec/active_record/turntable/config_spec.rb | 2 +- .../turntable/connection_proxy_spec.rb | 33 ++- spec/active_record/turntable/finder_spec.rb | 2 +- .../turntable/mixer/fader_spec.rb | 2 +- spec/active_record/turntable/mixer_spec.rb | 6 +- .../turntable/rack/query_cache_spec.rb | 4 +- .../turntable/sequencer/api_spec.rb | 6 +- .../turntable/sequencer/barrage_spec.rb | 4 +- .../turntable/sequencer/mysql_spec.rb | 2 +- spec/active_record/turntable/shard_spec.rb | 2 +- .../turntable/sql_tree_patch_spec.rb | 4 +- .../turntable/transaction_spec.rb | 4 +- spec/active_record/turntable_spec.rb | 2 +- spec/migrations/002_create_user_statuses.rb | 8 +- spec/migrations/003_create_cards.rb | 6 +- spec/migrations/004_create_cards_users.rb | 4 +- spec/spec_helper.rb | 28 +- spec/support/turntable_helper.rb | 6 +- 84 files changed, 827 insertions(+), 843 deletions(-) diff --git a/Guardfile b/Guardfile index 8d9ab2bc..14b3f19b 100644 --- a/Guardfile +++ b/Guardfile @@ -1,13 +1,13 @@ # A sample Guardfile # More info at https://github.com/guard/guard#readme -guard 'rspec', - cmd: "bundle exec rspec", - all_after_pass: true, - all_on_start: true do - watch(%r{^spec/.+_spec\.rb$}) - watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } - watch('spec/spec_helper.rb') { "spec" } +guard "rspec", + cmd: "bundle exec rspec", + all_after_pass: true, + all_on_start: true do + watch(%r{^spec/.+_spec\.rb$}) + watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } + watch("spec/spec_helper.rb") { "spec" } end guard :rubocop do diff --git a/Rakefile b/Rakefile index 96cbf99f..9ab8a7bf 100644 --- a/Rakefile +++ b/Rakefile @@ -1,25 +1,25 @@ require "bundler/gem_tasks" -require 'rubygems' +require "rubygems" -require 'rspec/core' -require 'rspec/core/rake_task' +require "rspec/core" +require "rspec/core/rake_task" RSpec::Core::RakeTask.new(:spec) do |spec| - spec.pattern = FileList['spec/**/*_spec.rb'] + spec.pattern = FileList["spec/**/*_spec.rb"] end -require 'active_record' +require "active_record" require "active_record/turntable/active_record_ext/database_tasks" namespace :turntable do namespace :db do task :rails_env do unless defined? RAILS_ENV - RAILS_ENV = ENV['RAILS_ENV'] ||= 'test' + RAILS_ENV = ENV["RAILS_ENV"] ||= "test" end end task :load_config => :rails_env do - yaml_file = File.join(File.dirname(__FILE__), 'spec/config/database.yml') + yaml_file = File.join(File.dirname(__FILE__), "spec/config/database.yml") ActiveRecord::Base.configurations = YAML.load ERB.new(IO.read(yaml_file)).result end @@ -38,12 +38,12 @@ namespace :turntable do desc "migrate turntable test tables" task :migrate => :load_config do ActiveRecord::Base.establish_connection RAILS_ENV.to_sym - require 'active_record/turntable' + require "active_record/turntable" ActiveRecord::Base.send(:include, ActiveRecord::Turntable) ActiveRecord::ConnectionAdapters::SchemaStatements.send(:include, ActiveRecord::Turntable::Migration::SchemaStatementsExt) configurations = [ActiveRecord::Base.configurations[RAILS_ENV]] - configurations += ActiveRecord::Tasks::DatabaseTasks.current_turntable_cluster_configurations(RAILS_ENV).map {|v| v[1]}.flatten.uniq + configurations += ActiveRecord::Tasks::DatabaseTasks.current_turntable_cluster_configurations(RAILS_ENV).map { |v| v[1] }.flatten.uniq configurations.each do |configuration| ActiveRecord::Base.establish_connection configuration @@ -100,15 +100,15 @@ namespace :turntable do ActiveRecord::Base.connection.create_table :cards_users_histories do |t| t.belongs_to :cards_user, :null => false - t.belongs_to :user, :null => false + t.belongs_to :user, :null => false t.timestamps end ActiveRecord::Base.connection.create_sequence_for :cards_users_histories ActiveRecord::Base.connection.create_table :events_users_histories do |t| - t.belongs_to :events_user, :null => false + t.belongs_to :events_user, :null => false t.belongs_to :cards_user, :null => false - t.belongs_to :user, :null => false + t.belongs_to :user, :null => false t.timestamps end ActiveRecord::Base.connection.create_sequence_for :events_users_histories diff --git a/activerecord-turntable.gemspec b/activerecord-turntable.gemspec index f4634d3a..6dc1e39c 100644 --- a/activerecord-turntable.gemspec +++ b/activerecord-turntable.gemspec @@ -1,23 +1,23 @@ -$:.push File.expand_path("../lib", __FILE__) +$LOAD_PATH.push File.expand_path("../lib", __FILE__) require "active_record/turntable/version" Gem::Specification.new do |spec| spec.name = "activerecord-turntable" spec.version = ActiveRecord::Turntable::VERSION - spec.authors = ["gussan", "sue445"] + spec.authors = %w(gussan sue445) spec.homepage = "https://github.com/drecom/activerecord-turntable" - spec.summary = %q{ActiveRecord sharding extension} - spec.description = %q{ActiveRecord sharding extension} + spec.summary = "ActiveRecord sharding extension" + spec.description = "ActiveRecord sharding extension" spec.license = "MIT" spec.rubyforge_project = "activerecord-turntable" spec.extra_rdoc_files = [ "LICENSE.txt", "README.md", - "CHANGELOG.md" + "CHANGELOG.md", ] - spec.files = `git ls-files`.split($/) + spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR) spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ["lib"] diff --git a/lib/active_record/turntable.rb b/lib/active_record/turntable.rb index ba71b329..12d0c78e 100644 --- a/lib/active_record/turntable.rb +++ b/lib/active_record/turntable.rb @@ -3,14 +3,14 @@ # # ActiveRecord Sharding Plugin # -require 'active_record/turntable/version' -require 'active_record' -require 'active_record/fixtures' -require 'active_support/concern' -require 'active_record/turntable/error' -require 'active_record/turntable/util' -require 'logger' -require 'singleton' +require "active_record/turntable/version" +require "active_record" +require "active_record/fixtures" +require "active_support/concern" +require "active_record/turntable/error" +require "active_record/turntable/util" +require "logger" +require "singleton" # for 4.0.x series module ActiveRecord @@ -55,7 +55,7 @@ module ClassMethods def turntable_config_file @@turntable_config_file ||= File.join(defined?(::Rails) ? - ::Rails.root.to_s : DEFAULT_PATH, 'config/turntable.yml') + ::Rails.root.to_s : DEFAULT_PATH, "config/turntable.yml") end def turntable_config_file=(filename) diff --git a/lib/active_record/turntable/active_record_ext.rb b/lib/active_record/turntable/active_record_ext.rb index 3b74d3a2..8c8c161f 100644 --- a/lib/active_record/turntable/active_record_ext.rb +++ b/lib/active_record/turntable/active_record_ext.rb @@ -32,10 +32,10 @@ module ActiveRecordExt end ActiveRecord::Associations::Preloader::Association.send(:include, AssociationPreloader) ActiveRecord::Associations::Association.send(:include, Association) - require 'active_record/turntable/active_record_ext/fixtures' - require 'active_record/turntable/active_record_ext/migration_proxy' - require 'active_record/turntable/active_record_ext/activerecord_import_ext' - require 'active_record/turntable/active_record_ext/acts_as_archive_extension' + require "active_record/turntable/active_record_ext/fixtures" + require "active_record/turntable/active_record_ext/migration_proxy" + require "active_record/turntable/active_record_ext/activerecord_import_ext" + require "active_record/turntable/active_record_ext/acts_as_archive_extension" end end end diff --git a/lib/active_record/turntable/active_record_ext/abstract_adapter.rb b/lib/active_record/turntable/active_record_ext/abstract_adapter.rb index 000c0786..3ad5025c 100644 --- a/lib/active_record/turntable/active_record_ext/abstract_adapter.rb +++ b/lib/active_record/turntable/active_record_ext/abstract_adapter.rb @@ -9,12 +9,12 @@ module AbstractAdapter # @note override for logging current shard name def log(sql, name = "SQL", binds = []) @instrumenter.instrument( - "sql.active_record", - :sql => sql, - :name => name, - :connection_id => object_id, - :binds => binds, - :turntable_shard_name => turntable_shard_name) { yield } + "sql.active_record", + sql: sql, + name: name, + connection_id: object_id, + binds: binds, + turntable_shard_name: turntable_shard_name) { yield } rescue Exception => e message = "#{e.class.name}: #{e.message}: #{sql} : #{turntable_shard_name}" @logger.error message if @logger diff --git a/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb b/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb index fb61ea42..2bc6fae9 100644 --- a/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb +++ b/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb @@ -10,39 +10,39 @@ module ActiverecordImportExt private - # @note override for sequencer injection - # @see https://github.com/zdennis/activerecord-import/blob/ba909fed5a4785fe9c7cce89e48e1242bb6804ea/lib/activerecord-import/import.rb#L558-L581 - def values_sql_for_columns_and_attributes_with_turntable(columns, array_of_attributes) - connection_memo = connection - array_of_attributes.map do |arr| - my_values = arr.each_with_index.map do |val,j| - column = columns[j] + # @note override for sequencer injection + # @see https://github.com/zdennis/activerecord-import/blob/ba909fed5a4785fe9c7cce89e48e1242bb6804ea/lib/activerecord-import/import.rb#L558-L581 + def values_sql_for_columns_and_attributes_with_turntable(columns, array_of_attributes) + connection_memo = connection + array_of_attributes.map do |arr| + my_values = arr.each_with_index.map do |val, j| + column = columns[j] - # be sure to query sequence_name *last*, only if cheaper tests fail, because it's costly - if val.nil? && column.name == primary_key && !sequence_name.blank? - if sequencer_enabled? - connection_memo.next_sequence_value(sequence_name) - else - connection_memo.next_value_for_sequence(sequence_name) - end - elsif column - if respond_to?(:type_caster) && type_caster.respond_to?(:type_cast_for_database) # Rails 5.0 and higher - connection_memo.quote(type_caster.type_cast_for_database(column.name, val)) - elsif column.respond_to?(:type_cast_from_user) # Rails 4.2 and higher - connection_memo.quote(column.type_cast_from_user(val), column) - else # Rails 3.1, 3.2, and 4.1 - connection_memo.quote(column.type_cast(val), column) + # be sure to query sequence_name *last*, only if cheaper tests fail, because it's costly + if val.nil? && column.name == primary_key && !sequence_name.blank? + if sequencer_enabled? + connection_memo.next_sequence_value(sequence_name) + else + connection_memo.next_value_for_sequence(sequence_name) + end + elsif column + if respond_to?(:type_caster) && type_caster.respond_to?(:type_cast_for_database) # Rails 5.0 and higher + connection_memo.quote(type_caster.type_cast_for_database(column.name, val)) + elsif column.respond_to?(:type_cast_from_user) # Rails 4.2 and higher + connection_memo.quote(column.type_cast_from_user(val), column) + else # Rails 3.1, 3.2, and 4.1 + connection_memo.quote(column.type_cast(val), column) + end end end + "(#{my_values.join(',')})" end - "(#{my_values.join(',')})" end - end end begin - require 'activerecord-import' - require 'activerecord-import/base' + require "activerecord-import" + require "activerecord-import/base" (class << ActiveRecord::Base; self; end).send(:include, ActiverecordImportExt) rescue LoadError end diff --git a/lib/active_record/turntable/active_record_ext/acts_as_archive_extension.rb b/lib/active_record/turntable/active_record_ext/acts_as_archive_extension.rb index c7ab021d..1e18c2a7 100644 --- a/lib/active_record/turntable/active_record_ext/acts_as_archive_extension.rb +++ b/lib/active_record/turntable/active_record_ext/acts_as_archive_extension.rb @@ -1,10 +1,10 @@ begin - require 'acts_as_archive' + require "acts_as_archive" # acts_as_archive extension class ActsAsArchive class << self # @note use the same shard which `from` shard using - def move_with_turntable(config, where, merge_options={}) + def move_with_turntable(config, where, merge_options = {}) if [config[:to], config[:from]].all? { |k| k.try(:turntable_enabled?) } current_shard = config[:from].connection.current_shard.name.to_sym config[:to].connection.with_shard(current_shard) { diff --git a/lib/active_record/turntable/active_record_ext/association.rb b/lib/active_record/turntable/active_record_ext/association.rb index ce01fce3..8f4b80f6 100644 --- a/lib/active_record/turntable/active_record_ext/association.rb +++ b/lib/active_record/turntable/active_record_ext/association.rb @@ -1,4 +1,4 @@ -require 'active_record/associations' +require "active_record/associations" module ActiveRecord::Turntable module ActiveRecordExt @@ -13,127 +13,127 @@ module Association private - def turntable_scope(scope, bind = nil) - if should_use_shard_key? - scope = scope.where(klass.turntable_shard_key => owner.send(foreign_shard_key)) + def turntable_scope(scope, bind = nil) + if should_use_shard_key? + scope = scope.where(klass.turntable_shard_key => owner.send(foreign_shard_key)) + end + scope end - scope - end - module SingularAssociationExt - extend ActiveSupport::Concern + module SingularAssociationExt + extend ActiveSupport::Concern - included do - if Util.ar42_or_later? - alias_method_chain :get_records, :turntable - else - alias_method_chain :find_target, :turntable + included do + if Util.ar42_or_later? + alias_method_chain :get_records, :turntable + else + alias_method_chain :find_target, :turntable + end end - end - # @note Override to add sharding condition for singular association - if Util.ar42_or_later? - def get_records_with_turntable - if reflection.scope_chain.any?(&:any?) || - scope.eager_loading? || - klass.current_scope || - klass.default_scopes.any? || - should_use_shard_key? # OPTIMIZE: Use bind values if cachable scope + # @note Override to add sharding condition for singular association + if Util.ar42_or_later? + def get_records_with_turntable + if reflection.scope_chain.any?(&:any?) || + scope.eager_loading? || + klass.current_scope || + klass.default_scopes.any? || + should_use_shard_key? # OPTIMIZE: Use bind values if cachable scope + + return turntable_scope(scope).limit(1).to_a + end - return turntable_scope(scope).limit(1).to_a - end + conn = klass.connection + sc = reflection.association_scope_cache(conn, owner) do + ActiveRecord::StatementCache.create(conn) { |params| + as = ActiveRecord::Associations::AssociationScope.create { params.bind } + target_scope.merge(as.scope(self, conn)).limit(1) + } + end - conn = klass.connection - sc = reflection.association_scope_cache(conn, owner) do - ActiveRecord::StatementCache.create(conn) { |params| - as = ActiveRecord::Associations::AssociationScope.create { params.bind } - target_scope.merge(as.scope(self, conn)).limit(1) - } + binds = ActiveRecord::Associations::AssociationScope.get_bind_values(owner, reflection.chain) + sc.execute binds, klass, klass.connection end - - binds = ActiveRecord::Associations::AssociationScope.get_bind_values(owner, reflection.chain) - sc.execute binds, klass, klass.connection - end - elsif Util.ar41_or_later? - def find_target_with_turntable - if record = turntable_scope(scope).take - set_inverse_instance record + elsif Util.ar41_or_later? + def find_target_with_turntable + if record = turntable_scope(scope).take + set_inverse_instance record + end + end + else + def find_target_with_turntable + turntable_scope(scope).take.tap { |record| set_inverse_instance(record) } end - end - else - def find_target_with_turntable - turntable_scope(scope).take.tap { |record| set_inverse_instance(record) } end end - end - module CollectionAssociationExt - extend ActiveSupport::Concern + module CollectionAssociationExt + extend ActiveSupport::Concern - included do - if Util.ar42_or_later? - alias_method_chain :get_records, :turntable - else - alias_method_chain :find_target, :turntable + included do + if Util.ar42_or_later? + alias_method_chain :get_records, :turntable + else + alias_method_chain :find_target, :turntable + end end - end - private + private - if Util.ar42_or_later? - def get_records_with_turntable - if reflection.scope_chain.any?(&:any?) || - scope.eager_loading? || - klass.current_scope || - klass.default_scopes.any? || - should_use_shard_key? # OPTIMIZE: Use bind values if cachable scope + if Util.ar42_or_later? + def get_records_with_turntable + if reflection.scope_chain.any?(&:any?) || + scope.eager_loading? || + klass.current_scope || + klass.default_scopes.any? || + should_use_shard_key? # OPTIMIZE: Use bind values if cachable scope - return turntable_scope(scope).to_a - end - - conn = klass.connection - sc = reflection.association_scope_cache(conn, owner) do - ActiveRecord::StatementCache.create(conn) { |params| - as = ActiveRecord::Associations::AssociationScope.create { params.bind } - target_scope.merge as.scope(self, conn) - } - end + return turntable_scope(scope).to_a + end - binds = ActiveRecord::Associations::AssociationScope.get_bind_values(owner, reflection.chain) - sc.execute binds, klass, klass.connection - end - else - # @note Override to add sharding condition for collection association - def find_target_with_turntable - records = - if options[:finder_sql] - reflection.klass.find_by_sql(custom_finder_sql) - else - current_scope = scope - if should_use_shard_key? - current_scope = current_scope.where(klass.turntable_shard_key => owner.send(foreign_shard_key)) + conn = klass.connection + sc = reflection.association_scope_cache(conn, owner) do + ActiveRecord::StatementCache.create(conn) { |params| + as = ActiveRecord::Associations::AssociationScope.create { params.bind } + target_scope.merge as.scope(self, conn) + } end - current_scope.to_a + + binds = ActiveRecord::Associations::AssociationScope.get_bind_values(owner, reflection.chain) + sc.execute binds, klass, klass.connection end - records.each { |record| set_inverse_instance(record) } - records - end + else + # @note Override to add sharding condition for collection association + def find_target_with_turntable + records = + if options[:finder_sql] + reflection.klass.find_by_sql(custom_finder_sql) + else + current_scope = scope + if should_use_shard_key? + current_scope = current_scope.where(klass.turntable_shard_key => owner.send(foreign_shard_key)) + end + current_scope.to_a + end + records.each { |record| set_inverse_instance(record) } + records + end + end end - end private - def foreign_shard_key - options[:foreign_shard_key] || owner.turntable_shard_key - end + def foreign_shard_key + options[:foreign_shard_key] || owner.turntable_shard_key + end - def should_use_shard_key? - same_association_shard_key? || !!options[:foreign_shard_key] - end + def should_use_shard_key? + same_association_shard_key? || !!options[:foreign_shard_key] + end - def same_association_shard_key? - owner.class.turntable_enabled? && klass.turntable_enabled? && foreign_shard_key == klass.turntable_shard_key - end + def same_association_shard_key? + owner.class.turntable_enabled? && klass.turntable_enabled? && foreign_shard_key == klass.turntable_shard_key + end end end end diff --git a/lib/active_record/turntable/active_record_ext/association_preloader.rb b/lib/active_record/turntable/active_record_ext/association_preloader.rb index 0ccef8f2..9f7e7f80 100644 --- a/lib/active_record/turntable/active_record_ext/association_preloader.rb +++ b/lib/active_record/turntable/active_record_ext/association_preloader.rb @@ -1,4 +1,4 @@ -require 'active_record/associations/preloader/association' +require "active_record/associations/preloader/association" module ActiveRecord::Turntable module ActiveRecordExt @@ -20,19 +20,19 @@ def records_for_with_turntable(ids) private - def foreign_shard_key - options[:foreign_shard_key] || model.turntable_shard_key - end + def foreign_shard_key + options[:foreign_shard_key] || model.turntable_shard_key + end - def should_use_shard_key? - sharded_by_same_key? || !!options[:foreign_shard_key] - end + def should_use_shard_key? + sharded_by_same_key? || !!options[:foreign_shard_key] + end - def sharded_by_same_key? - model.turntable_enabled? && - klass.turntable_enabled? && - model.turntable_shard_key == klass.turntable_shard_key - end + def sharded_by_same_key? + model.turntable_enabled? && + klass.turntable_enabled? && + model.turntable_shard_key == klass.turntable_shard_key + end end end end diff --git a/lib/active_record/turntable/active_record_ext/clever_load.rb b/lib/active_record/turntable/active_record_ext/clever_load.rb index 068e79d4..6abaa5fa 100644 --- a/lib/active_record/turntable/active_record_ext/clever_load.rb +++ b/lib/active_record/turntable/active_record_ext/clever_load.rb @@ -5,7 +5,7 @@ module CleverLoad included do class << ActiveRecord::Base - delegate :clever_load!, :to => :all + delegate :clever_load!, to: :all end end diff --git a/lib/active_record/turntable/active_record_ext/connection_handler_extension.rb b/lib/active_record/turntable/active_record_ext/connection_handler_extension.rb index bc843458..67810c0a 100644 --- a/lib/active_record/turntable/active_record_ext/connection_handler_extension.rb +++ b/lib/active_record/turntable/active_record_ext/connection_handler_extension.rb @@ -9,24 +9,24 @@ module ConnectionHandlerExtension private - # @note Override not to establish_connection destroy existing connection pool proxy object - def pool_for_with_turntable(owner) - owner_to_pool.fetch(owner.name) { - if ancestor_pool = pool_from_any_process_for(owner) - if ancestor_pool.is_a?(ActiveRecord::ConnectionAdapters::ConnectionPool) - # A connection was established in an ancestor process that must have - # subsequently forked. We can't reuse the connection, but we can copy - # the specification and establish a new connection with it. - establish_connection owner, ancestor_pool.spec + # @note Override not to establish_connection destroy existing connection pool proxy object + def pool_for_with_turntable(owner) + owner_to_pool.fetch(owner.name) { + if ancestor_pool = pool_from_any_process_for(owner) + if ancestor_pool.is_a?(ActiveRecord::ConnectionAdapters::ConnectionPool) + # A connection was established in an ancestor process that must have + # subsequently forked. We can't reuse the connection, but we can copy + # the specification and establish a new connection with it. + establish_connection owner, ancestor_pool.spec + else + # Use same PoolProxy object + owner_to_pool[owner.name] = ancestor_pool + end else - # Use same PoolProxy object - owner_to_pool[owner.name] = ancestor_pool + owner_to_pool[owner.name] = nil end - else - owner_to_pool[owner.name] = nil - end - } - end + } + end end end end diff --git a/lib/active_record/turntable/active_record_ext/database_tasks.rb b/lib/active_record/turntable/active_record_ext/database_tasks.rb index dff045c4..5dcd0ed5 100644 --- a/lib/active_record/turntable/active_record_ext/database_tasks.rb +++ b/lib/active_record/turntable/active_record_ext/database_tasks.rb @@ -1,24 +1,24 @@ -require 'active_record/tasks/database_tasks' +require "active_record/tasks/database_tasks" module ActiveRecord module Tasks module DatabaseTasks def create_all_turntable_cluster - each_local_turntable_cluster_configuration { |name, configuration| + each_local_turntable_cluster_configuration { |_name, configuration| puts "[turntable] *** executing to database: #{configuration['database']}" create configuration } end def drop_all_turntable_cluster - each_local_turntable_cluster_configuration { |name, configuration| + each_local_turntable_cluster_configuration { |_name, configuration| puts "[turntable] *** executing to database: #{configuration['database']}" drop configuration } end def create_current_turntable_cluster(environment = env) - each_current_turntable_cluster_configuration(true, environment) { |name, configuration| + each_current_turntable_cluster_configuration(true, environment) { |_name, configuration| puts "[turntable] *** executing to database: #{configuration['database']}" create configuration } @@ -26,7 +26,7 @@ def create_current_turntable_cluster(environment = env) end def drop_current_turntable_cluster(environment = env) - each_current_turntable_cluster_configuration(true, environment) { |name, configuration| + each_current_turntable_cluster_configuration(true, environment) { |_name, configuration| puts "[turntable] *** executing to database: #{configuration['database']}" drop configuration } @@ -45,20 +45,20 @@ def each_current_turntable_cluster_connected(with_test = false, environment = en def each_current_turntable_cluster_configuration(with_test = false, environment = env) environments = [environment] - environments << 'test' if with_test and environment == 'development' + environments << "test" if with_test && environment == "development" current_turntable_cluster_configurations(*environments).each do |name, configuration| - yield(name, configuration) unless configuration['database'].blank? + yield(name, configuration) unless configuration["database"].blank? end end def each_local_turntable_cluster_configuration ActiveRecord::Base.configurations.keys.each do |k| current_turntable_cluster_configurations(k).each do |name, configuration| - next if configuration['database'].blank? + next if configuration["database"].blank? if local_database?(configuration) - yield(name,configuration) + yield(name, configuration) else $stderr.puts "This task only modifies local databases. #{configuration['database']} is on a remote host." end diff --git a/lib/active_record/turntable/active_record_ext/fixtures.rb b/lib/active_record/turntable/active_record_ext/fixtures.rb index 9bcaf276..c934602d 100644 --- a/lib/active_record/turntable/active_record_ext/fixtures.rb +++ b/lib/active_record/turntable/active_record_ext/fixtures.rb @@ -1,7 +1,7 @@ # # force TestFixtures to begin transaction with all shards. # -require 'active_record/fixtures' +require "active_record/fixtures" module ActiveRecord class FixtureSet @@ -46,13 +46,13 @@ def self.create_fixtures(fixtures_directory, fixture_set_names, class_names = {} all_loaded_fixtures.update(fixtures_map) end - ActiveRecord::Base.force_transaction_all_shards!(:requires_new => true) do + ActiveRecord::Base.force_transaction_all_shards!(requires_new: true) do fixture_sets.each do |fs| conn = fs.model_class.respond_to?(:connection) ? fs.model_class.connection : connection table_rows = fs.table_rows table_rows.each_key do |table| - conn.delete "DELETE FROM #{conn.quote_table_name(table)}", 'Fixture Delete' + conn.delete "DELETE FROM #{conn.quote_table_name(table)}", "Fixture Delete" end table_rows.each do |fixture_set_name, rows| @@ -81,10 +81,10 @@ module TestFixtures include ActiveRecord::Turntable::Util def setup_fixtures(config = ActiveRecord::Base) - return unless !ActiveRecord::Base.configurations.blank? + return if ActiveRecord::Base.configurations.blank? if pre_loaded_fixtures && !use_transactional_fixtures - raise RuntimeError, 'pre_loaded_fixtures requires use_transactional_fixtures' + raise "pre_loaded_fixtures requires use_transactional_fixtures" end @fixture_cache = {} @@ -122,20 +122,20 @@ def enlist_fixture_connections private - def turntable_load_fixtures(config) - if ar41_or_later? - load_fixtures(config) - else - load_fixtures + def turntable_load_fixtures(config) + if ar41_or_later? + load_fixtures(config) + else + load_fixtures + end end - end - def turntable_instantiate_fixtures(config) - if ar41_or_later? - instantiate_fixtures(config) - else - instantiate_fixtures + def turntable_instantiate_fixtures(config) + if ar41_or_later? + instantiate_fixtures(config) + else + instantiate_fixtures + end end - end end end diff --git a/lib/active_record/turntable/active_record_ext/locking_optimistic.rb b/lib/active_record/turntable/active_record_ext/locking_optimistic.rb index a546fe8a..0856eba1 100644 --- a/lib/active_record/turntable/active_record_ext/locking_optimistic.rb +++ b/lib/active_record/turntable/active_record_ext/locking_optimistic.rb @@ -3,7 +3,6 @@ module ActiveRecordExt module LockingOptimistic # @note Override to add sharding condition on optimistic locking ::ActiveRecord::Locking::Optimistic.class_eval do - ar_version = ActiveRecord::VERSION::STRING if Util.earlier_than_ar41? method_name = Util.ar_version_earlier_than?("4.0.6") ? "update_record" : "_update_record" diff --git a/lib/active_record/turntable/active_record_ext/log_subscriber.rb b/lib/active_record/turntable/active_record_ext/log_subscriber.rb index 27aeece7..49e2deed 100644 --- a/lib/active_record/turntable/active_record_ext/log_subscriber.rb +++ b/lib/active_record/turntable/active_record_ext/log_subscriber.rb @@ -1,4 +1,4 @@ -require 'active_record/log_subscriber' +require "active_record/log_subscriber" module ActiveRecord::Turntable module ActiveRecordExt @@ -11,37 +11,37 @@ module LogSubscriber protected - # @note Override to add shard name logging - def sql_with_turntable(event) - self.class.runtime += event.duration - return unless logger.debug? + # @note Override to add shard name logging + def sql_with_turntable(event) + self.class.runtime += event.duration + return unless logger.debug? - payload = event.payload + payload = event.payload - return if ActiveRecord::LogSubscriber::IGNORE_PAYLOAD_NAMES.include?(payload[:name]) + return if ActiveRecord::LogSubscriber::IGNORE_PAYLOAD_NAMES.include?(payload[:name]) - name = "#{payload[:name]} (#{event.duration.round(1)}ms)" - shard = '[Shard: %s]' % (event.payload[:turntable_shard_name] ? event.payload[:turntable_shard_name] : nil) - sql = payload[:sql].squeeze(' ') - binds = nil + name = "#{payload[:name]} (#{event.duration.round(1)}ms)" + shard = "[Shard: %s]" % (event.payload[:turntable_shard_name] ? event.payload[:turntable_shard_name] : nil) + sql = payload[:sql].squeeze(" ") + binds = nil - unless (payload[:binds] || []).empty? - binds = " " + payload[:binds].map { |col,v| - render_bind(col, v) - }.inspect - end + unless (payload[:binds] || []).empty? + binds = " " + payload[:binds].map { |col, v| + render_bind(col, v) + }.inspect + end - if odd? - name = color(name, ActiveRecord::LogSubscriber::CYAN, true) - shard = color(shard, ActiveRecord::LogSubscriber::CYAN, true) - sql = color(sql, nil, true) - else - name = color(name, ActiveRecord::LogSubscriber::MAGENTA, true) - shard = color(shard, ActiveRecord::LogSubscriber::MAGENTA, true) - end + if odd? + name = color(name, ActiveRecord::LogSubscriber::CYAN, true) + shard = color(shard, ActiveRecord::LogSubscriber::CYAN, true) + sql = color(sql, nil, true) + else + name = color(name, ActiveRecord::LogSubscriber::MAGENTA, true) + shard = color(shard, ActiveRecord::LogSubscriber::MAGENTA, true) + end - debug " #{name} #{shard} #{sql}#{binds}" - end + debug " #{name} #{shard} #{sql}#{binds}" + end end end end diff --git a/lib/active_record/turntable/active_record_ext/migration_proxy.rb b/lib/active_record/turntable/active_record_ext/migration_proxy.rb index 00635d04..894c1ed1 100644 --- a/lib/active_record/turntable/active_record_ext/migration_proxy.rb +++ b/lib/active_record/turntable/active_record_ext/migration_proxy.rb @@ -1,4 +1,4 @@ -require 'active_record/migration' +require "active_record/migration" module ActiveRecord class MigrationProxy diff --git a/lib/active_record/turntable/active_record_ext/persistence.rb b/lib/active_record/turntable/active_record_ext/persistence.rb index 64b294d4..12b0c258 100644 --- a/lib/active_record/turntable/active_record_ext/persistence.rb +++ b/lib/active_record/turntable/active_record_ext/persistence.rb @@ -9,7 +9,7 @@ def reload(options = nil) clear_aggregation_cache clear_association_cache - finder_scope = if turntable_enabled? and self.class.primary_key != self.class.turntable_shard_key.to_s + finder_scope = if turntable_enabled? && self.class.primary_key != self.class.turntable_shard_key.to_s self.class.unscoped.where(self.class.turntable_shard_key => self.send(turntable_shard_key)) else self.class.unscoped @@ -23,12 +23,12 @@ def reload(options = nil) end if Util.ar42_or_later? - @attributes = fresh_object.instance_variable_get('@attributes') + @attributes = fresh_object.instance_variable_get("@attributes") else - @attributes.update(fresh_object.instance_variable_get('@attributes')) + @attributes.update(fresh_object.instance_variable_get("@attributes")) @column_types = self.class.column_types - @column_types_override = fresh_object.instance_variable_get('@column_types_override') + @column_types_override = fresh_object.instance_variable_get("@column_types_override") @attributes_cache = {} end @new_record = false @@ -57,7 +57,7 @@ def touch(*names) clear_attribute_changes(changes.keys) primary_key = self.class.primary_key - finder_scope = if turntable_enabled? and primary_key != self.class.turntable_shard_key.to_s + finder_scope = if turntable_enabled? && primary_key != self.class.turntable_shard_key.to_s self.class.unscoped.where(self.class.turntable_shard_key => self.send(turntable_shard_key)) else self.class.unscoped @@ -89,7 +89,7 @@ def touch(name = nil) @changed_attributes.except!(*changes.keys) primary_key = self.class.primary_key - finder_scope = if turntable_enabled? and primary_key != self.class.turntable_shard_key.to_s + finder_scope = if turntable_enabled? && primary_key != self.class.turntable_shard_key.to_s self.class.unscoped.where(self.class.turntable_shard_key => self.send(turntable_shard_key)) else self.class.unscoped @@ -111,7 +111,7 @@ def update_columns(attributes) verify_readonly_attribute(key.to_s) end - update_scope = if turntable_enabled? and self.class.primary_key != self.class.turntable_shard_key.to_s + update_scope = if turntable_enabled? && self.class.primary_key != self.class.turntable_shard_key.to_s self.class.unscoped.where(self.class.turntable_shard_key => self.send(turntable_shard_key)) else self.class.unscoped @@ -137,10 +137,10 @@ def relation_for_destroy klass = self.class relation = self.class.unscoped.where( - self.class.arel_table[pk].eq(substitute)) + self.class.arel_table[pk].eq(substitute)) relation.bind_values = [[column, id]] - if klass.turntable_enabled? and klass.primary_key != klass.turntable_shard_key.to_s + if klass.turntable_enabled? && klass.primary_key != klass.turntable_shard_key.to_s shard_key_column = klass.columns_hash[klass.turntable_shard_key] shard_key_substitute = klass.connection.substitute_at(shard_key_column) @@ -157,8 +157,8 @@ def relation_for_destroy klass = self.class relation = self.class.unscoped.where( - self.class.arel_table[pk].eq(substitute)) - if klass.turntable_enabled? and klass.primary_key != klass.turntable_shard_key.to_s + self.class.arel_table[pk].eq(substitute)) + if klass.turntable_enabled? && klass.primary_key != klass.turntable_shard_key.to_s relation = relation.where(klass.turntable_shard_key => self.send(turntable_shard_key)) end relation.bind_values = [[column, id]] diff --git a/lib/active_record/turntable/active_record_ext/relation.rb b/lib/active_record/turntable/active_record_ext/relation.rb index e43e02ff..67c7738d 100644 --- a/lib/active_record/turntable/active_record_ext/relation.rb +++ b/lib/active_record/turntable/active_record_ext/relation.rb @@ -5,7 +5,7 @@ module Relation included do if Util.ar41_or_later? - if Util.ar_version_earlier_than?('4.1.2') + if Util.ar_version_earlier_than?("4.1.2") alias_method :_update_record_without_turntable, :update_record alias_method :update_record, :_update_record_with_turntable else @@ -29,14 +29,14 @@ def _update_record_with_turntable(values, id, id_was, turntable_scope = nil) # : relation = relation.merge(turntable_scope) if turntable_scope bvs = binds + relation.bind_values - um = relation - .arel - .compile_update(substitutes, @klass.primary_key) + um = relation. + arel. + compile_update(substitutes, @klass.primary_key) @klass.connection.update( um, - 'SQL', - bvs, + "SQL", + bvs ) end else @@ -48,7 +48,7 @@ def _update_record_with_turntable(values, id, id_was, turntable_scope = nil) # : @klass.connection.update( um, - 'SQL', + "SQL", binds) end end diff --git a/lib/active_record/turntable/active_record_ext/schema_dumper.rb b/lib/active_record/turntable/active_record_ext/schema_dumper.rb index 6c57158f..df2ad381 100644 --- a/lib/active_record/turntable/active_record_ext/schema_dumper.rb +++ b/lib/active_record/turntable/active_record_ext/schema_dumper.rb @@ -10,89 +10,88 @@ module SchemaDumper private - # @note Override to dump database sequencer method - def table_with_turntable(table, stream) - columns = @connection.columns(table) - begin - tbl = StringIO.new - - # first dump primary key column - if @connection.respond_to?(:pk_and_sequence_for) - pk, _ = @connection.pk_and_sequence_for(table) - elsif @connection.respond_to?(:primary_key) - pk = @connection.primary_key(table) - end - - if table =~ /\A(.*)_id_seq\z/ - tbl.print " create_sequence_for #{remove_prefix_and_suffix($1).inspect}" - else - tbl.print " create_table #{remove_prefix_and_suffix(table).inspect}" - end - pkcol = columns.detect { |c| c.name == pk } - if pkcol - if pk != 'id' - tbl.print %Q(, primary_key: "#{pk}") - elsif pkcol.sql_type == 'uuid' - tbl.print ", id: :uuid" - tbl.print %Q(, default: "#{pkcol.default_function}") if pkcol.default_function + # @note Override to dump database sequencer method + def table_with_turntable(table, stream) + columns = @connection.columns(table) + begin + tbl = StringIO.new + + # first dump primary key column + if @connection.respond_to?(:pk_and_sequence_for) + pk, = @connection.pk_and_sequence_for(table) + elsif @connection.respond_to?(:primary_key) + pk = @connection.primary_key(table) end - else - tbl.print ", id: false" - end - tbl.print ", force: true" - tbl.puts " do |t|" - - # then dump all non-primary key columns - column_specs = columns.map do |column| - raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type) - next if column.name == pk - @connection.column_spec(column, @types) - end.compact - - # find all migration keys used in this table - keys = @connection.migration_keys - - # figure out the lengths for each column based on above keys - lengths = keys.map { |key| - column_specs.map { |spec| - spec[key] ? spec[key].length + 2 : 0 - }.max - } - - # the string we're going to sprintf our values against, with standardized column widths - format_string = lengths.map{ |len| "%-#{len}s" } - - # find the max length for the 'type' column, which is special - type_length = column_specs.map{ |column| column[:type].length }.max - # add column type definition to our format string - format_string.unshift " t.%-#{type_length}s " - - format_string *= '' + if table =~ /\A(.*)_id_seq\z/ + tbl.print " create_sequence_for #{remove_prefix_and_suffix($1).inspect}" + else + tbl.print " create_table #{remove_prefix_and_suffix(table).inspect}" + end + pkcol = columns.detect { |c| c.name == pk } + if pkcol + if pk != "id" + tbl.print %(, primary_key: "#{pk}") + elsif pkcol.sql_type == "uuid" + tbl.print ", id: :uuid" + tbl.print %(, default: "#{pkcol.default_function}") if pkcol.default_function + end + else + tbl.print ", id: false" + end + tbl.print ", force: true" + tbl.puts " do |t|" + + # then dump all non-primary key columns + column_specs = columns.map do |column| + raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type) + next if column.name == pk + @connection.column_spec(column, @types) + end.compact + + # find all migration keys used in this table + keys = @connection.migration_keys + + # figure out the lengths for each column based on above keys + lengths = keys.map { |key| + column_specs.map { |spec| + spec[key] ? spec[key].length + 2 : 0 + }.max + } + + # the string we're going to sprintf our values against, with standardized column widths + format_string = lengths.map { |len| "%-#{len}s" } + + # find the max length for the 'type' column, which is special + type_length = column_specs.map { |column| column[:type].length }.max + + # add column type definition to our format string + format_string.unshift " t.%-#{type_length}s " + + format_string *= "" + + column_specs.each do |colspec| + values = keys.zip(lengths).map { |key, len| colspec.key?(key) ? colspec[key] + ", " : " " * len } + values.unshift colspec[:type] + tbl.print((format_string % values).gsub(/,\s*$/, "")) + tbl.puts + end - column_specs.each do |colspec| - values = keys.zip(lengths).map{ |key, len| colspec.key?(key) ? colspec[key] + ", " : " " * len } - values.unshift colspec[:type] - tbl.print((format_string % values).gsub(/,\s*$/, '')) + tbl.puts " end" tbl.puts - end - tbl.puts " end" - tbl.puts + indexes(table, tbl) - indexes(table, tbl) + tbl.rewind + stream.print tbl.read + rescue => e + stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}" + stream.puts "# #{e.message}" + stream.puts + end - tbl.rewind - stream.print tbl.read - rescue => e - stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}" - stream.puts "# #{e.message}" - stream.puts + stream end - - stream - end - end end end diff --git a/lib/active_record/turntable/active_record_ext/transactions.rb b/lib/active_record/turntable/active_record_ext/transactions.rb index c32e411c..ee5d8da7 100644 --- a/lib/active_record/turntable/active_record_ext/transactions.rb +++ b/lib/active_record/turntable/active_record_ext/transactions.rb @@ -5,8 +5,8 @@ module Transactions def with_transaction_returning_status if self.class.turntable_enabled? status = nil - if self.new_record? and self.turntable_shard_key.to_s == self.class.primary_key and - self.id.nil? and self.class.connection.prefetch_primary_key?(self.class.table_name) + if self.new_record? && self.turntable_shard_key.to_s == self.class.primary_key && + self.id.nil? && self.class.connection.prefetch_primary_key?(self.class.table_name) self.id = self.class.connection.next_sequence_value(self.class.sequence_name) end self.class.connection.shards_transaction([self.turntable_shard]) do diff --git a/lib/active_record/turntable/algorithm/range_algorithm.rb b/lib/active_record/turntable/algorithm/range_algorithm.rb index 63d04d4c..b468dee3 100644 --- a/lib/active_record/turntable/algorithm/range_algorithm.rb +++ b/lib/active_record/turntable/algorithm/range_algorithm.rb @@ -13,7 +13,7 @@ def calculate(key) end def calculate_idx(key) - @config["shards"].find_index {|h| h["less_than"] > key } + @config["shards"].find_index { |h| h["less_than"] > key } end # { connection_name => weight, ... } @@ -21,9 +21,9 @@ def calculate_used_shards_with_weight(sequence_value) idx = calculate_idx(sequence_value) last_connection = calculate(sequence_value) shards = @config["shards"][0..idx] - weighted_hash = Hash.new {|h,k| h[k]=0} + weighted_hash = Hash.new { |h, k| h[k] = 0 } prev_max = 0 - shards.each_with_index do |h,idx| + shards.each_with_index do |h, idx| weighted_hash[h["connection"]] += if idx < shards.size - 1 h["less_than"] - prev_max - 1 else @@ -31,7 +31,7 @@ def calculate_used_shards_with_weight(sequence_value) end prev_max = h["less_than"] - 1 end - return weighted_hash + weighted_hash end end end diff --git a/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb b/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb index cf890ac6..38e55063 100644 --- a/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb +++ b/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- -require 'bsearch' +require "bsearch" module ActiveRecord::Turntable::Algorithm class RangeBsearchAlgorithm < Base def initialize(config) @config = config - @config["shards"].sort_by! {|a| a["less_than"]} + @config["shards"].sort_by! { |a| a["less_than"] } end def calculate(key) @@ -25,9 +25,9 @@ def calculate_used_shards_with_weight(sequence_value) idx = calculate_idx(sequence_value) last_connection = calculate(sequence_value) shards = @config["shards"][0..idx] - weighted_hash = Hash.new {|h,k| h[k]=0} + weighted_hash = Hash.new { |h, k| h[k] = 0 } prev_max = 0 - shards.each_with_index do |h,idx| + shards.each_with_index do |h, idx| weighted_hash[h["connection"]] += if idx < shards.size - 1 h["less_than"] - prev_max - 1 else @@ -35,7 +35,7 @@ def calculate_used_shards_with_weight(sequence_value) end prev_max = h["less_than"] - 1 end - return weighted_hash + weighted_hash end end end diff --git a/lib/active_record/turntable/base.rb b/lib/active_record/turntable/base.rb index ad66e17c..8e403f06 100644 --- a/lib/active_record/turntable/base.rb +++ b/lib/active_record/turntable/base.rb @@ -1,4 +1,4 @@ -require 'active_support/lazy_load_hooks' +require "active_support/lazy_load_hooks" module ActiveRecord::Turntable module Base @@ -6,14 +6,14 @@ module Base included do class_attribute :turntable_connections, :turntable_clusters, - :turntable_enabled, :turntable_sequencer_enabled + :turntable_enabled, :turntable_sequencer_enabled self.turntable_connections = {} self.turntable_clusters = {}.with_indifferent_access self.turntable_enabled = false self.turntable_sequencer_enabled = false class << self - delegate :shards_transaction, :with_all, :to => :connection + delegate :shards_transaction, :with_all, to: :connection end ActiveSupport.on_load(:turntable_config_loaded) do @@ -28,20 +28,19 @@ module ClassMethods # @param [Hash] options def turntable(cluster_name, shard_key_name, options = {}) class_attribute :turntable_shard_key, - :turntable_cluster, :turntable_cluster_name + :turntable_cluster, :turntable_cluster_name self.turntable_enabled = true self.turntable_cluster_name = cluster_name self.turntable_shard_key = shard_key_name self.turntable_cluster = self.turntable_clusters[cluster_name] ||= Cluster.new( - turntable_config[:clusters][cluster_name], - options - ) + turntable_config[:clusters][cluster_name], + options + ) turntable_replace_connection_pool end - def turntable_replace_connection_pool ch = connection_handler cp = ConnectionProxy.new(self, turntable_cluster) @@ -67,9 +66,7 @@ def spec_for(config) end def clear_all_connections! - turntable_connections.values.each do |pool| - pool.disconnect! - end + turntable_connections.values.each(&:disconnect!) end def sequencer(sequence_name, *args) diff --git a/lib/active_record/turntable/cluster.rb b/lib/active_record/turntable/cluster.rb index 9f67480a..64e3ed4d 100644 --- a/lib/active_record/turntable/cluster.rb +++ b/lib/active_record/turntable/cluster.rb @@ -1,8 +1,7 @@ -require 'active_support/core_ext/hash/indifferent_access' +require "active_support/core_ext/hash/indifferent_access" module ActiveRecord::Turntable class Cluster - DEFAULT_CONFIG = { "shards" => [], "algorithm" => "range", @@ -15,7 +14,7 @@ def initialize(cluster_spec, options = {}) # setup sequencer seq = (@options[:seq] || @config[:seq]) - if seq + if seq if seq.values.size > 0 && seq.values.first["seq_type"] == "mysql" @seq_shard = SeqShard.new(seq.values.first) end @@ -35,15 +34,13 @@ def seq @seq_shard end - def shards - @shards - end + attr_reader :shards def shard_for(key) @shards[@algorithm.calculate(key)] rescue raise ActiveRecord::Turntable::CannotSpecifyShardError, - "cannot select_shard for key:#{key}" + "cannot select_shard for key:#{key}" end def select_shard(key) @@ -65,7 +62,7 @@ def shards_transaction(shards = [], options = {}, in_recursion = false, &block) end else shard.connection.transaction(options) do - block.call + yield end end end @@ -82,12 +79,12 @@ def to_shard(shard_or_object) shards[shard_or_object] else raise ActiveRecord::Turntable::TurntableError, - "transaction cannot call to object: #{shard_or_object}" + "transaction cannot call to object: #{shard_or_object}" end end def weighted_shards(key = nil) - Hash[@algorithm.calculate_used_shards_with_weight(key).map do |k,v| + Hash[@algorithm.calculate_used_shards_with_weight(key).map do |k, v| [@shards[k], v] end] end diff --git a/lib/active_record/turntable/cluster_helper_methods.rb b/lib/active_record/turntable/cluster_helper_methods.rb index 5d6680fc..305b4b97 100644 --- a/lib/active_record/turntable/cluster_helper_methods.rb +++ b/lib/active_record/turntable/cluster_helper_methods.rb @@ -4,14 +4,14 @@ module ClusterHelperMethods included do ActiveSupport.on_load(:turntable_config_loaded) do - turntable_clusters.each do |name, cluster| + turntable_clusters.each do |name, _cluster| turntable_define_cluster_methods(name) end end end module ClassMethods - def force_transaction_all_shards!(options={}, &block) + def force_transaction_all_shards!(options = {}, &block) force_connect_all_shards! shards = turntable_connections.values shards += [ActiveRecord::Base.connection_pool] @@ -44,7 +44,7 @@ def weighted_random_shard_with(*klasses, &block) shards_weight = self.turntable_cluster.weighted_shards(self.current_sequence) sum = shards_weight.values.inject(&:+) idx = rand(sum) - shard, weight = shards_weight.find {|k,v| + shard, weight = shards_weight.find {|_k, v| (idx -= v) < 0 } self.connection.with_recursive_shards(shard.name, *klasses, &block) diff --git a/lib/active_record/turntable/config.rb b/lib/active_record/turntable/config.rb index 9910ddaf..92bcfa48 100644 --- a/lib/active_record/turntable/config.rb +++ b/lib/active_record/turntable/config.rb @@ -1,5 +1,5 @@ -require 'active_support/lazy_load_hooks' -require 'active_support/core_ext/hash/indifferent_access' +require "active_support/lazy_load_hooks" +require "active_support/core_ext/hash/indifferent_access" module ActiveRecord::Turntable class Config @@ -14,7 +14,7 @@ def [](key) @config[key] end - def self.load!(config_file = ActiveRecord::Base.turntable_config_file, env = (defined?(Rails) ? Rails.env : 'development')) + def self.load!(config_file = ActiveRecord::Base.turntable_config_file, env = (defined?(Rails) ? Rails.env : "development")) instance.load!(config_file, env) end diff --git a/lib/active_record/turntable/connection_proxy.rb b/lib/active_record/turntable/connection_proxy.rb index d83fab01..24d50bdd 100644 --- a/lib/active_record/turntable/connection_proxy.rb +++ b/lib/active_record/turntable/connection_proxy.rb @@ -1,10 +1,10 @@ -require 'active_record/turntable/connection_proxy/mixable' +require "active_record/turntable/connection_proxy/mixable" module ActiveRecord::Turntable class ConnectionProxy include Mixable # for expiring query cache - CLEAR_CACHE_METHODS = [:update, :insert, :delete, :exec_insert, :exec_update, :exec_delete, :insert_many] + CLEAR_CACHE_METHODS = [:update, :insert, :delete, :exec_insert, :exec_update, :exec_delete, :insert_many].freeze attr_reader :klass attr_writer :spec @@ -22,9 +22,9 @@ def initialize(klass, cluster, options = {}) delegate :shards_transaction, to: :cluster delegate :create_table, :rename_table, :drop_table, :add_column, :remove_colomn, - :change_column, :change_column_default, :rename_column, :add_index, - :remove_index, :initialize_schema_information, - :dump_schema_information, :execute_ignore_duplicate, to: :master_connection + :change_column, :change_column_default, :rename_column, :add_index, + :remove_index, :initialize_schema_information, + :dump_schema_information, :execute_ignore_duplicate, to: :master_connection def transaction(options = {}, &block) connection.transaction(options, &block) @@ -38,7 +38,7 @@ def cache end def enable_query_cache! - klass.turntable_connections.each do |k,v| + klass.turntable_connections.each do |_k, v| v.connection.enable_query_cache! end end @@ -48,7 +48,7 @@ def clear_query_cache_if_needed(method) end def clear_query_cache - klass.turntable_connections.each do |k,v| + klass.turntable_connections.each do |_k, v| v.connection.clear_query_cache end end @@ -59,9 +59,11 @@ def method_missing(method, *args, &block) connection.send(method, *args, &block) elsif mixable?(method, *args) fader = @mixer.build_fader(method, *args, &block) - logger.debug { "[ActiveRecord::Turntable] Sending method: #{method}, " + - "sql: #{args.first}, " + - "shards: #{fader.shards_query_hash.keys.map(&:name)}" } + logger.debug { + "[ActiveRecord::Turntable] Sending method: #{method}, " \ + "sql: #{args.first}, " \ + "shards: #{fader.shards_query_hash.keys.map(&:name)}" + } fader.execute else connection.send(method, *args, &block) @@ -76,9 +78,7 @@ def to_sql(arel, binds = []) master.connection.to_sql(arel, binds) end - def cluster - @cluster - end + attr_reader :cluster def shards @cluster.shards @@ -113,7 +113,7 @@ def current_shard end def current_shard=(shard) - logger.debug { "Changing #{klass}'s shard to #{shard.name}"} + logger.debug { "Changing #{klass}'s shard to #{shard.name}" } current_shard_entry[object_id] = shard end @@ -136,7 +136,8 @@ def connection_pool def with_shard(shard) shard = cluster.to_shard(shard) - old_shard, old_fixed = current_shard, fixed_shard + old_shard = current_shard + old_fixed = fixed_shard self.current_shard = shard self.fixed_shard = shard yield @@ -197,7 +198,7 @@ def with_master(&block) end delegate :connected?, :automatic_reconnect, :automatic_reconnect=, :checkout_timeout, :dead_connection_timeout, - :spec, :connections, :size, :reaper, :table_exists?, to: :connection_pool + :spec, :connections, :size, :reaper, :table_exists?, to: :connection_pool %w(columns columns_hash column_defaults primary_keys).each do |name| define_method(name.to_sym) do @@ -239,12 +240,12 @@ def spec private - def fixed_shard_entry - Thread.current[:turntable_fixed_shard] ||= ThreadSafe::Cache.new - end + def fixed_shard_entry + Thread.current[:turntable_fixed_shard] ||= ThreadSafe::Cache.new + end - def current_shard_entry - Thread.current[:turntable_current_shard] ||= ThreadSafe::Cache.new - end + def current_shard_entry + Thread.current[:turntable_current_shard] ||= ThreadSafe::Cache.new + end end end diff --git a/lib/active_record/turntable/connection_proxy/mixable.rb b/lib/active_record/turntable/connection_proxy/mixable.rb index 0e2adfea..247c4cfb 100644 --- a/lib/active_record/turntable/connection_proxy/mixable.rb +++ b/lib/active_record/turntable/connection_proxy/mixable.rb @@ -10,7 +10,7 @@ module Mixable def mixable?(method, *args) (method.to_s =~ METHODS_REGEXP && args.first !~ EXCLUDE_QUERY_REGEXP) || - (method.to_s == 'execute' && args.first =~ QUERY_REGEXP) + (method.to_s == "execute" && args.first =~ QUERY_REGEXP) end end end diff --git a/lib/active_record/turntable/helpers/test_helper.rb b/lib/active_record/turntable/helpers/test_helper.rb index 64fd5448..2160e96d 100644 --- a/lib/active_record/turntable/helpers/test_helper.rb +++ b/lib/active_record/turntable/helpers/test_helper.rb @@ -2,15 +2,15 @@ module ActiveRecord::Turntable module Helpers module TestHelper # all shards - def FabricateAll(name, overrides={}, &block) + def FabricateAll(name, overrides = {}, &block) obj = Fabrication::Fabricator.generate(name, { - :save => true - }, overrides, &block) + save: true, + }, overrides, &block) default_pool = obj.class.connection_pool connection_pools = obj.class.connection_handler.instance_variable_get(:@connection_pools) - ActiveRecord::Base.turntable_connections.each do |conn_name, conn| + ActiveRecord::Base.turntable_connections.each do |_conn_name, conn| new_obj = obj.dup connection_pools[new_obj.class.name] = conn new_obj.id = obj.id diff --git a/lib/active_record/turntable/master_shard.rb b/lib/active_record/turntable/master_shard.rb index 746482b1..4bd26890 100644 --- a/lib/active_record/turntable/master_shard.rb +++ b/lib/active_record/turntable/master_shard.rb @@ -4,7 +4,7 @@ def initialize(klass) (klass and klass.connection_pool) or raise MasterShardNotConnected, "connection_pool is nil" @klass = klass - @name = 'master' + @name = "master" end def connection_pool @@ -14,8 +14,8 @@ def connection_pool # use parentclass connection which is turntable disabled klass = @klass.superclass candidate_connection_pool = nil - while !candidate_connection_pool - if klass == ActiveRecord::Base or !klass.turntable_enabled? + until candidate_connection_pool + if klass == ActiveRecord::Base || !klass.turntable_enabled? candidate_connection_pool = klass.connection_pool else klass = klass.superclass diff --git a/lib/active_record/turntable/migration.rb b/lib/active_record/turntable/migration.rb index 76c4ac98..2ed45087 100644 --- a/lib/active_record/turntable/migration.rb +++ b/lib/active_record/turntable/migration.rb @@ -16,12 +16,12 @@ def clusters(*cluster_names) config = ActiveRecord::Base.turntable_config (self.target_shards ||= []).concat( if cluster_names.first == :all - config['clusters'].map do |name, cluster_conf| - cluster_conf["shards"].map {|shard| shard["connection"]} + config["clusters"].map do |_name, cluster_conf| + cluster_conf["shards"].map { |shard| shard["connection"] } end else cluster_names.map do |cluster_name| - config['clusters'][cluster_name]["shards"].map do |shard| + config["clusters"][cluster_name]["shards"].map do |shard| shard["connection"] end end.flatten @@ -47,19 +47,19 @@ def exec_migration_with_turntable(*args) end module SchemaStatementsExt - def create_sequence_for(table_name, options = { }) - options = options.merge(:id => false) + def create_sequence_for(table_name, options = {}) + options = options.merge(id: false) # TODO: pkname should be pulled from table definitions pkname = "id" sequence_table_name = ActiveRecord::Turntable::Sequencer.sequence_name(table_name, "id") create_table(sequence_table_name, options) do |t| - t.integer :id, :limit => 8 + t.integer :id, limit: 8 end execute "INSERT INTO #{quote_table_name(sequence_table_name)} (`id`) VALUES (0)" end - def drop_sequence_for(table_name, options = { }) + def drop_sequence_for(table_name, options = {}) # TODO: pkname should be pulled from table definitions pkname = "id" sequence_table_name = ActiveRecord::Turntable::Sequencer.sequence_name(table_name, "id") @@ -85,13 +85,13 @@ def rename_sequence_for(*args) private - def invert_create_sequence_for(args) - [:drop_sequence_for, args] - end + def invert_create_sequence_for(args) + [:drop_sequence_for, args] + end - def invert_rename_sequence_for(args) - [:rename_sequence_for, args.reverse] - end + def invert_rename_sequence_for(args) + [:rename_sequence_for, args.reverse] + end end module Migrator diff --git a/lib/active_record/turntable/mixer.rb b/lib/active_record/turntable/mixer.rb index 069ff3ac..e591ff61 100644 --- a/lib/active_record/turntable/mixer.rb +++ b/lib/active_record/turntable/mixer.rb @@ -1,5 +1,5 @@ -require 'active_support/core_ext/object/try' -require 'active_record/turntable/sql_tree_patch' +require "active_support/core_ext/object/try" +require "active_record/turntable/sql_tree_patch" module ActiveRecord::Turntable class Mixer @@ -9,7 +9,7 @@ class Mixer autoload :Fader end - delegate :logger, :to => ActiveRecord::Base + delegate :logger, to: ActiveRecord::Base NOT_USED_FOR_SHARDING_OPERATORS_REGEXP = /\A(NOT IN|IS|IS NOT|BETWEEN|LIKE|\!\=|<<|>>|<>|>\=|<=|[\*\+\-\/\%\|\&><])\z/ @@ -24,7 +24,7 @@ def build_fader(method_name, query, *args, &block) { @proxy.fixed_shard => query }, method, query, *args, &block) end - binds = (method == 'insert') ? args[4] : args[1] + binds = (method == "insert") ? args[4] : args[1] binded_query = bind_sql(query, binds) begin @@ -44,8 +44,8 @@ def build_fader(method_name, query, *args, &block) else # send to master shard Fader::SpecifiedShard.new(@proxy, - { @proxy.master => query }, - method, query, *args, &block) + { @proxy.master => query }, + method, query, *args, &block) end rescue Exception => err logger.warn { "[ActiveRecord::Turntable] Error on Building Fader: #{binded_query}, on_method: #{method_name}, err: #{err}" } @@ -59,7 +59,7 @@ def find_shard_keys(tree, table_name, shard_key) when "OR" lkeys = find_shard_keys(tree.lhs, table_name, shard_key) rkeys = find_shard_keys(tree.rhs, table_name, shard_key) - if lkeys.present? and rkeys.present? + if lkeys.present? && rkeys.present? lkeys + rkeys else [] @@ -67,7 +67,7 @@ def find_shard_keys(tree, table_name, shard_key) when "AND" lkeys = find_shard_keys(tree.lhs, table_name, shard_key) rkeys = find_shard_keys(tree.rhs, table_name, shard_key) - if lkeys.present? or rkeys.present? + if lkeys.present? || rkeys.present? lkeys + rkeys else [] @@ -93,141 +93,141 @@ def find_shard_keys(tree, table_name, shard_key) [] else raise ActiveRecord::Turntable::UnknownOperatorError, - "[ActiveRecord::Turntable] Found Unknown SQL Operator:'#{tree.operator if tree.respond_to?(:operaor)}', Please report this bug." + "[ActiveRecord::Turntable] Found Unknown SQL Operator:'#{tree.operator if tree.respond_to?(:operaor)}', Please report this bug." end end private - def divide_insert_values(tree, shard_key_name) - idx = tree.fields.find_index {|f| f.name == shard_key_name.to_s } - result = {} - tree.values.each do |val| - (result[val[idx].value] ||= []) << val + def divide_insert_values(tree, shard_key_name) + idx = tree.fields.find_index { |f| f.name == shard_key_name.to_s } + result = {} + tree.values.each do |val| + (result[val[idx].value] ||= []) << val + end + result end - return result - end - def build_shards_with_same_query(shards, query) - Hash[shards.map {|s| [s, query] }] - end + def build_shards_with_same_query(shards, query) + Hash[shards.map { |s| [s, query] }] + end - def bind_sql(sql, binds) - # TODO: substitution value should be determined by adapter - query = sql.is_a?(String) ? sql : @proxy.to_sql(sql, binds ? binds.dup : []) - query = if query.include?("\0") and binds.is_a?(Array) and binds[0].is_a?(Array) and binds[0][0].is_a?(ActiveRecord::ConnectionAdapters::Column) - binds = binds.dup - query.gsub("\0") { @proxy.master.connection.quote(*binds.shift.reverse) } - else - query - end - end + def bind_sql(sql, binds) + # TODO: substitution value should be determined by adapter + query = sql.is_a?(String) ? sql : @proxy.to_sql(sql, binds ? binds.dup : []) + query = if query.include?("\0") && binds.is_a?(Array) && binds[0].is_a?(Array) && binds[0][0].is_a?(ActiveRecord::ConnectionAdapters::Column) + binds = binds.dup + query.gsub("\0") { @proxy.master.connection.quote(*binds.shift.reverse) } + else + query + end + end - def build_select_fader(tree, method, query, *args, &block) - shard_keys = if !tree.where and tree.from.size == 1 and SQLTree::Node::SubQuery === tree.from.first.table_reference.table - find_shard_keys(tree.from.first.table_reference.table.where, - @proxy.klass.table_name, - @proxy.klass.turntable_shard_key.to_s) - else - find_shard_keys(tree.where, - @proxy.klass.table_name, - @proxy.klass.turntable_shard_key.to_s) - end - - if shard_keys.size == 1 # shard - return Fader::SpecifiedShard.new(@proxy, - { @proxy.cluster.shard_for(shard_keys.first) => query }, - method, query, *args, &block) - elsif SQLTree::Node::SelectDeclaration === tree.select.first and - tree.select.first.to_sql == '1 AS "one"' # for `SELECT 1 AS one` (AR::Base.exists?) - return Fader::SelectShardsMergeResult.new(@proxy, - build_shards_with_same_query(@proxy.shards.values, query), - method, query, *args, &block - ) - elsif tree.group_by or tree.order_by or tree.limit.try(:value).to_i > 0 - raise CannotSpecifyShardError, "cannot specify shard for query: #{tree.to_sql}" - elsif shard_keys.present? - if SQLTree::Node::SelectDeclaration === tree.select.first and - SQLTree::Node::CountAggregrate === tree.select.first.expression - return Fader::CalculateShardsSumResult.new(@proxy, - build_shards_with_same_query(@proxy.shards.values, query), - method, query, *args, &block) - else + def build_select_fader(tree, method, query, *args, &block) + shard_keys = if !tree.where && tree.from.size == 1 && SQLTree::Node::SubQuery === tree.from.first.table_reference.table + find_shard_keys(tree.from.first.table_reference.table.where, + @proxy.klass.table_name, + @proxy.klass.turntable_shard_key.to_s) + else + find_shard_keys(tree.where, + @proxy.klass.table_name, + @proxy.klass.turntable_shard_key.to_s) + end + + if shard_keys.size == 1 # shard + return Fader::SpecifiedShard.new(@proxy, + { @proxy.cluster.shard_for(shard_keys.first) => query }, + method, query, *args, &block) + elsif SQLTree::Node::SelectDeclaration === tree.select.first && + tree.select.first.to_sql == '1 AS "one"' # for `SELECT 1 AS one` (AR::Base.exists?) return Fader::SelectShardsMergeResult.new(@proxy, - Hash[shard_keys.map {|k| [@proxy.cluster.shard_for(k), query] }], + build_shards_with_same_query(@proxy.shards.values, query), method, query, *args, &block - ) + ) + elsif tree.group_by || tree.order_by || tree.limit.try(:value).to_i > 0 + raise CannotSpecifyShardError, "cannot specify shard for query: #{tree.to_sql}" + elsif shard_keys.present? + if SQLTree::Node::SelectDeclaration === tree.select.first && + SQLTree::Node::CountAggregrate === tree.select.first.expression + return Fader::CalculateShardsSumResult.new(@proxy, + build_shards_with_same_query(@proxy.shards.values, query), + method, query, *args, &block) + else + return Fader::SelectShardsMergeResult.new(@proxy, + Hash[shard_keys.map { |k| [@proxy.cluster.shard_for(k), query] }], + method, query, *args, &block + ) + end + else # scan all shards + if SQLTree::Node::SelectDeclaration === tree.select.first && + SQLTree::Node::CountAggregrate === tree.select.first.expression + + if raise_on_not_specified_shard_query? + raise CannotSpecifyShardError, "[Performance Notice] PLEASE FIX: #{tree.to_sql}" + end + return Fader::CalculateShardsSumResult.new(@proxy, + build_shards_with_same_query(@proxy.shards.values, query), + method, query, *args, &block) + elsif SQLTree::Node::AllFieldsDeclaration === tree.select.first || + SQLTree::Node::Expression::Value === tree.select.first.expression || + SQLTree::Node::Expression::Variable === tree.select.first.expression + + if raise_on_not_specified_shard_query? + raise CannotSpecifyShardError, "[Performance Notice] PLEASE FIX: #{tree.to_sql}" + end + return Fader::SelectShardsMergeResult.new(@proxy, + build_shards_with_same_query(@proxy.shards.values, query), + method, query, *args, &block + ) + else + raise CannotSpecifyShardError, "cannot specify shard for query: #{tree.to_sql}" + end end - else # scan all shards - if SQLTree::Node::SelectDeclaration === tree.select.first and - SQLTree::Node::CountAggregrate === tree.select.first.expression + end - if raise_on_not_specified_shard_query? - raise CannotSpecifyShardError, "[Performance Notice] PLEASE FIX: #{tree.to_sql}" - end - return Fader::CalculateShardsSumResult.new(@proxy, - build_shards_with_same_query(@proxy.shards.values, query), - method, query, *args, &block) - elsif SQLTree::Node::AllFieldsDeclaration === tree.select.first or - SQLTree::Node::Expression::Value === tree.select.first.expression or - SQLTree::Node::Expression::Variable === tree.select.first.expression - - if raise_on_not_specified_shard_query? + def build_update_fader(tree, method, query, *args, &block) + shard_keys = find_shard_keys(tree.where, @proxy.klass.table_name, @proxy.klass.turntable_shard_key.to_s) + shards_with_query = if shard_keys.present? + build_shards_with_same_query(shard_keys.map { |k| @proxy.cluster.shard_for(k) }, query) + else + build_shards_with_same_query(@proxy.shards.values, query) + end + + if shards_with_query.size == 1 + Fader::SpecifiedShard.new(@proxy, + shards_with_query, + method, query, *args, &block) + else + if raise_on_not_specified_shard_update? raise CannotSpecifyShardError, "[Performance Notice] PLEASE FIX: #{tree.to_sql}" end - return Fader::SelectShardsMergeResult.new(@proxy, - build_shards_with_same_query(@proxy.shards.values, query), - method, query, *args, &block - ) - else - raise CannotSpecifyShardError, "cannot specify shard for query: #{tree.to_sql}" + Fader::UpdateShardsMergeResult.new(@proxy, + shards_with_query, + method, query, *args, &block) end end - end - def build_update_fader(tree, method, query, *args, &block) - shard_keys = find_shard_keys(tree.where, @proxy.klass.table_name, @proxy.klass.turntable_shard_key.to_s) - shards_with_query = if shard_keys.present? - build_shards_with_same_query(shard_keys.map {|k| @proxy.cluster.shard_for(k) }, query) - else - build_shards_with_same_query(@proxy.shards.values, query) - end - - if shards_with_query.size == 1 - Fader::SpecifiedShard.new(@proxy, - shards_with_query, - method, query, *args, &block) - else - if raise_on_not_specified_shard_update? - raise CannotSpecifyShardError, "[Performance Notice] PLEASE FIX: #{tree.to_sql}" + def build_insert_fader(tree, method, query, *args, &block) + values_hash = divide_insert_values(tree, @proxy.klass.turntable_shard_key) + shards_with_query = {} + values_hash.each do |k, vs| + tree.values = [[SQLTree::Node::Expression::Variable.new("\\0")]] + sql = tree.to_sql + value_sql = vs.map do |val| + "(#{val.map { |v| "#{v.escape}#{@proxy.connection.quote(v.value)}" }.join(', ')})" + end.join(", ") + sql.gsub!('("\0")') { value_sql } + shards_with_query[@proxy.cluster.shard_for(k)] = sql end - Fader::UpdateShardsMergeResult.new(@proxy, - shards_with_query, - method, query, *args, &block) + Fader::InsertShardsMergeResult.new(@proxy, shards_with_query, method, query, *args, &block) end - end - def build_insert_fader(tree, method, query, *args, &block) - values_hash = divide_insert_values(tree, @proxy.klass.turntable_shard_key) - shards_with_query = {} - values_hash.each do |k,vs| - tree.values = [[SQLTree::Node::Expression::Variable.new("\\0")]] - sql = tree.to_sql - value_sql = vs.map do |val| - "(#{val.map { |v| "#{v.escape}#{@proxy.connection.quote(v.value)}" }.join(', ')})" - end.join(', ') - sql.gsub!('("\0")') { value_sql } - shards_with_query[@proxy.cluster.shard_for(k)] = sql + def raise_on_not_specified_shard_query? + ActiveRecord::Base.turntable_config[:raise_on_not_specified_shard_query] end - Fader::InsertShardsMergeResult.new(@proxy, shards_with_query, method, query, *args, &block) - end - def raise_on_not_specified_shard_query? - ActiveRecord::Base.turntable_config[:raise_on_not_specified_shard_query] - end - - def raise_on_not_specified_shard_update? - ActiveRecord::Base.turntable_config[:raise_on_not_specified_shard_update] - end + def raise_on_not_specified_shard_update? + ActiveRecord::Base.turntable_config[:raise_on_not_specified_shard_update] + end end end diff --git a/lib/active_record/turntable/mixer/fader/calculate_shards_sum_result.rb b/lib/active_record/turntable/mixer/fader/calculate_shards_sum_result.rb index ba6f603e..f83842ca 100644 --- a/lib/active_record/turntable/mixer/fader/calculate_shards_sum_result.rb +++ b/lib/active_record/turntable/mixer/fader/calculate_shards_sum_result.rb @@ -13,13 +13,13 @@ def execute private - def merge_results(results) - ActiveRecord::Result.new( - results.first.columns, - results[0].rows.zip(*results[1..-1].map{|r| r.rows}).map {|r| [r.map {|v| v.first}.inject(&:+)]}, - results.first.column_types - ) - end + def merge_results(results) + ActiveRecord::Result.new( + results.first.columns, + results[0].rows.zip(*results[1..-1].map(&:rows)).map { |r| [r.map(&:first).inject(&:+)] }, + results.first.column_types + ) + end end end end diff --git a/lib/active_record/turntable/mixer/fader/select_shards_merge_result.rb b/lib/active_record/turntable/mixer/fader/select_shards_merge_result.rb index 0ea94e5a..9620e379 100644 --- a/lib/active_record/turntable/mixer/fader/select_shards_merge_result.rb +++ b/lib/active_record/turntable/mixer/fader/select_shards_merge_result.rb @@ -13,20 +13,20 @@ def execute private - def merge_results(results) - if results.any? {|r| r.is_a?(ActiveRecord::Result) } - first_result = results.find {|r| r.present? } - return results.first unless first_result + def merge_results(results) + if results.any? { |r| r.is_a?(ActiveRecord::Result) } + first_result = results.find(&:present?) + return results.first unless first_result - ActiveRecord::Result.new( - first_result.columns, - results.map {|r| r.rows}.flatten(1), - first_result.column_types - ) - else - results.compact.inject(&:+) + ActiveRecord::Result.new( + first_result.columns, + results.flat_map(&:rows), + first_result.column_types + ) + else + results.compact.inject(&:+) + end end - end end end end diff --git a/lib/active_record/turntable/plugin.rb b/lib/active_record/turntable/plugin.rb index dab3a68e..d925e50b 100644 --- a/lib/active_record/turntable/plugin.rb +++ b/lib/active_record/turntable/plugin.rb @@ -1,4 +1,4 @@ -require 'active_record/turntable' +require "active_record/turntable" module ActiveRecord::Turntable module Plugin diff --git a/lib/active_record/turntable/pool_proxy.rb b/lib/active_record/turntable/pool_proxy.rb index a424ab14..c3d95719 100644 --- a/lib/active_record/turntable/pool_proxy.rb +++ b/lib/active_record/turntable/pool_proxy.rb @@ -14,9 +14,7 @@ def initialize(proxy) @proxy = proxy end - def proxy - @proxy - end + attr_reader :proxy alias_method :connection, :proxy def with_connection @@ -24,7 +22,7 @@ def with_connection end delegate :connected?, :automatic_reconnect, :automatic_reconnect=, :checkout_timeout, :dead_connection_timeout, - :spec, :connections, :size, :reaper, :table_exists?, to: :proxy + :spec, :connections, :size, :reaper, :table_exists?, to: :proxy %w(columns_hash column_defaults primary_keys).each do |name| define_method(name.to_sym) do @@ -39,12 +37,12 @@ def with_connection end %w(active_connection?).each do |name| - define_method(name.to_sym) do |*args| + define_method(name.to_sym) do |*_args| @proxy.master.connection_pool.send(name.to_sym) || - @proxy.seq.connection_pool.try(name.to_sym) if @proxy.respond_to?(:seq) || - @proxy.shards.values.any? do |pool| - pool.connection_pool.send(name.to_sym) - end + @proxy.seq.connection_pool.try(name.to_sym) if @proxy.respond_to?(:seq) || + @proxy.shards.values.any? do |pool| + pool.connection_pool.send(name.to_sym) + end end end diff --git a/lib/active_record/turntable/rack/query_cache.rb b/lib/active_record/turntable/rack/query_cache.rb index 4332f868..a1e7fc5d 100644 --- a/lib/active_record/turntable/rack/query_cache.rb +++ b/lib/active_record/turntable/rack/query_cache.rb @@ -1,5 +1,5 @@ -require 'rack/body_proxy' -require 'active_record/query_cache' +require "rack/body_proxy" +require "active_record/query_cache" module ActiveRecord module Turntable @@ -26,14 +26,14 @@ def call(env) private - def restore_query_cache_settings(connection_id, enabled) - klasses = ActiveRecord::Base.turntable_connections.values - klasses.each do |k| - ActiveRecord::Base.connection_id = connection_id - k.connection.clear_query_cache - k.connection.disable_query_cache! unless enabled + def restore_query_cache_settings(connection_id, enabled) + klasses = ActiveRecord::Base.turntable_connections.values + klasses.each do |k| + ActiveRecord::Base.connection_id = connection_id + k.connection.clear_query_cache + k.connection.disable_query_cache! unless enabled + end end - end end end end diff --git a/lib/active_record/turntable/railtie.rb b/lib/active_record/turntable/railtie.rb index 55b9c6c4..6078bea0 100644 --- a/lib/active_record/turntable/railtie.rb +++ b/lib/active_record/turntable/railtie.rb @@ -1,7 +1,7 @@ module ActiveRecord::Turntable class Railtie < Rails::Railtie rake_tasks do - require 'active_record/turntable/active_record_ext/database_tasks' + require "active_record/turntable/active_record_ext/database_tasks" load "active_record/turntable/railties/databases.rake" end diff --git a/lib/active_record/turntable/railties/databases.rake b/lib/active_record/turntable/railties/databases.rake index f9e914ed..6a05fbcd 100644 --- a/lib/active_record/turntable/railties/databases.rake +++ b/lib/active_record/turntable/railties/databases.rake @@ -1,4 +1,4 @@ -require 'active_record/turntable' +require "active_record/turntable" ActiveRecord::SchemaDumper.send(:include, ActiveRecord::Turntable::ActiveRecordExt::SchemaDumper) turntable_namespace = nil @@ -11,9 +11,9 @@ db_namespace = namespace :db do end end - desc 'Create current turntable databases config/database.yml for the current Rails.env' + desc "Create current turntable databases config/database.yml for the current Rails.env" task :create do - unless ENV['DATABASE_URL'] + unless ENV["DATABASE_URL"] ActiveRecord::Tasks::DatabaseTasks.create_current_turntable_cluster end end @@ -24,9 +24,9 @@ db_namespace = namespace :db do end end - desc 'Drops current turntable databases for the current Rails.env' + desc "Drops current turntable databases for the current Rails.env" task :drop do - unless ENV['DATABASE_URL'] + unless ENV["DATABASE_URL"] ActiveRecord::Tasks::DatabaseTasks.drop_current_turntable_cluster end end @@ -34,14 +34,14 @@ db_namespace = namespace :db do namespace :schema do # TODO: implement schema:cache:xxxx task :dump do - require 'active_record/schema_dumper' + require "active_record/schema_dumper" config = ActiveRecord::Base.configurations[Rails.env] shard_configs = config["shards"] shard_configs.merge!(config["seq"]) if config["seq"] if shard_configs shard_configs.each do |name, config| next unless config["database"] - filename = ENV['SCHEMA'] || "#{Rails.root}/db/schema-#{name}.rb" + filename = ENV["SCHEMA"] || "#{Rails.root}/db/schema-#{name}.rb" File.open(filename, "w:utf-8") do |file| ActiveRecord::Base.establish_connection(config) ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file) @@ -49,10 +49,10 @@ db_namespace = namespace :db do end end ActiveRecord::Base.establish_connection(config) - turntable_namespace['schema:dump'].reenable + turntable_namespace["schema:dump"].reenable end - desc 'Load a schema.rb file into the database' + desc "Load a schema.rb file into the database" task :load do config = ActiveRecord::Base.configurations[Rails.env] shard_configs = config["shards"] @@ -61,11 +61,11 @@ db_namespace = namespace :db do shard_configs.each do |name, config| next unless config["database"] ActiveRecord::Base.establish_connection(config) - file = ENV['SCHEMA'] || "#{Rails.root}/db/schema-#{name}.rb" - if File.exists?(file) + file = ENV["SCHEMA"] || "#{Rails.root}/db/schema-#{name}.rb" + if File.exist?(file) load(file) else - abort %{#{file} doesn't exist yet. Run "rake db:migrate" to create it then try again. If you do not intend to use a database, you should instead alter #{Rails.root}/config/application.rb to limit the frameworks that will be loaded'} + abort %(#{file} doesn't exist yet. Run "rake db:migrate" to create it then try again. If you do not intend to use a database, you should instead alter #{Rails.root}/config/application.rb to limit the frameworks that will be loaded') end end end @@ -74,7 +74,7 @@ db_namespace = namespace :db do end namespace :structure do - desc 'Dump the database structure to an SQL file' + desc "Dump the database structure to an SQL file" task :dump do current_config = ActiveRecord::Tasks::DatabaseTasks.current_config shard_configs = current_config["shards"] @@ -86,15 +86,14 @@ db_namespace = namespace :db do filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "structure_#{name}.sql") ActiveRecord::Tasks::DatabaseTasks.structure_dump(config, filename) - if ActiveRecord::Base.connection.supports_migrations? - File.open(filename, "a") do |f| - f.puts ActiveRecord::Base.connection.dump_schema_information - end + next unless ActiveRecord::Base.connection.supports_migrations? + File.open(filename, "a") do |f| + f.puts ActiveRecord::Base.connection.dump_schema_information end end ActiveRecord::Base.establish_connection(current_config) end - turntable_namespace['structure:dump'].reenable + turntable_namespace["structure:dump"].reenable end # desc "Recreate the databases from the structure.sql file" @@ -121,7 +120,7 @@ db_namespace = namespace :db do shard_configs = config["shards"] shard_configs.merge!(config["seq"]) if config["seq"] if shard_configs - shard_configs.each do |name, config| + shard_configs.each do |_name, config| next unless config["database"] ActiveRecord::Tasks::DatabaseTasks.purge config end diff --git a/lib/active_record/turntable/seq_shard.rb b/lib/active_record/turntable/seq_shard.rb index 00ac1616..2629be17 100644 --- a/lib/active_record/turntable/seq_shard.rb +++ b/lib/active_record/turntable/seq_shard.rb @@ -2,20 +2,20 @@ module ActiveRecord::Turntable class SeqShard < Shard private - def create_connection_class - klass = get_or_set_connection_class - klass.remove_connection - klass.establish_connection ActiveRecord::Base.connection_pool.spec.config[:seq][name].with_indifferent_access - klass - end - - def retrieve_connection_pool - ActiveRecord::Base.turntable_connections[name] ||= - begin - config = ActiveRecord::Base.configurations[Rails.env]["seq"][name] - raise ArgumentError, "Unknown database config: #{name}, have #{ActiveRecord::Base.configurations.inspect}" unless config - ActiveRecord::ConnectionAdapters::ConnectionPool.new(spec_for(config)) - end - end + def create_connection_class + klass = get_or_set_connection_class + klass.remove_connection + klass.establish_connection ActiveRecord::Base.connection_pool.spec.config[:seq][name].with_indifferent_access + klass + end + + def retrieve_connection_pool + ActiveRecord::Base.turntable_connections[name] ||= + begin + config = ActiveRecord::Base.configurations[Rails.env]["seq"][name] + raise ArgumentError, "Unknown database config: #{name}, have #{ActiveRecord::Base.configurations.inspect}" unless config + ActiveRecord::ConnectionAdapters::ConnectionPool.new(spec_for(config)) + end + end end end diff --git a/lib/active_record/turntable/sequencer.rb b/lib/active_record/turntable/sequencer.rb index ed91635d..5bc23825 100644 --- a/lib/active_record/turntable/sequencer.rb +++ b/lib/active_record/turntable/sequencer.rb @@ -14,9 +14,9 @@ class Sequencer end @@sequence_types = { - :api => Api, - :mysql => Mysql, - :barrage => Barrage + api: Api, + mysql: Mysql, + barrage: Barrage, } @@sequences = {} @@ -39,7 +39,7 @@ def self.sequence_name(table_name, pk) end def self.table_name(seq_name) - seq_name.split('_').first + seq_name.split("_").first end def next_sequence_value @@ -52,13 +52,13 @@ def current_sequence_value private - def self.current_cluster_config_for(klass_or_name) - cluster_name = if klass_or_name.is_a?(Symbol) - klass_or_name - else - klass_or_name.turntable_cluster_name.to_s - end - ActiveRecord::Base.turntable_config["clusters"][cluster_name] - end + def self.current_cluster_config_for(klass_or_name) + cluster_name = if klass_or_name.is_a?(Symbol) + klass_or_name + else + klass_or_name.turntable_cluster_name.to_s + end + ActiveRecord::Base.turntable_config["clusters"][cluster_name] + end end end diff --git a/lib/active_record/turntable/sequencer/api.rb b/lib/active_record/turntable/sequencer/api.rb index df66529f..fdb9c075 100644 --- a/lib/active_record/turntable/sequencer/api.rb +++ b/lib/active_record/turntable/sequencer/api.rb @@ -2,13 +2,13 @@ # # Sequencer via HTTP API # -require 'httpclient' +require "httpclient" module ActiveRecord::Turntable class Sequencer class Api < Sequencer - API_ENDPOINT = '/sequences/' - NEXT_VALUE_ENDPOINT = '/new' + API_ENDPOINT = "/sequences/".freeze + NEXT_VALUE_ENDPOINT = "/new".freeze def initialize(klass, options = {}) @klass = klass @@ -22,14 +22,14 @@ def next_sequence_value(sequence_name) res = @client.get_content("http://#{@host}:#{@port}#{API_ENDPOINT}#{sequence_name}#{NEXT_VALUE_ENDPOINT}") new_id = res.to_i raise SequenceNotFoundError if new_id.zero? - return new_id + new_id end def current_sequence_value(sequence_name) res = @client.get_content("http://#{@host}:#{@port}#{API_ENDPOINT}#{sequence_name}") current_id = res.to_i raise SequenceNotFoundError if current_id.zero? - return current_id + current_id end end end diff --git a/lib/active_record/turntable/sequencer/barrage.rb b/lib/active_record/turntable/sequencer/barrage.rb index 74facc9a..b5e417cb 100644 --- a/lib/active_record/turntable/sequencer/barrage.rb +++ b/lib/active_record/turntable/sequencer/barrage.rb @@ -4,7 +4,7 @@ class Barrage < Sequencer @@unique_barrage_instance = {} def initialize(klass, options = {}) - require 'barrage' + require "barrage" @klass = klass @options = options["options"] @barrage = get_barrage_instance @@ -20,9 +20,9 @@ def current_sequence_value(sequence_name) private - def get_barrage_instance - @@unique_barrage_instance[@options] ||= ::Barrage.new(@options) - end + def get_barrage_instance + @@unique_barrage_instance[@options] ||= ::Barrage.new(@options) + end end end end diff --git a/lib/active_record/turntable/sequencer/mysql.rb b/lib/active_record/turntable/sequencer/mysql.rb index 82d0db3b..5e4576a5 100644 --- a/lib/active_record/turntable/sequencer/mysql.rb +++ b/lib/active_record/turntable/sequencer/mysql.rb @@ -17,7 +17,7 @@ def next_sequence_value(sequence_name) res = conn.execute("SELECT LAST_INSERT_ID()") new_id = res.first.first.to_i raise SequenceNotFoundError if new_id.zero? - return new_id + new_id end def current_sequence_value(sequence_name) @@ -25,7 +25,7 @@ def current_sequence_value(sequence_name) conn.execute "UPDATE #{@klass.connection.quote_table_name(sequence_name)} SET id=LAST_INSERT_ID(id)" res = conn.execute("SELECT LAST_INSERT_ID()") current_id = res.first.first.to_i - return current_id + current_id end end end diff --git a/lib/active_record/turntable/shard.rb b/lib/active_record/turntable/shard.rb index f1b3db81..0d717605 100644 --- a/lib/active_record/turntable/shard.rb +++ b/lib/active_record/turntable/shard.rb @@ -3,7 +3,7 @@ class Shard module Connections; end DEFAULT_CONFIG = { - "connection" => (defined?(Rails) ? Rails.env : "development") + "connection" => (defined?(Rails) ? Rails.env : "development"), }.with_indifferent_access attr_reader :name @@ -26,26 +26,26 @@ def connection private - def connection_klass - @connection_klass ||= create_connection_class - end + def connection_klass + @connection_klass ||= create_connection_class + end - def get_or_set_connection_class - if Connections.const_defined?(name.classify) - klass = Connections.const_get(name.classify) - else - klass = Class.new(ActiveRecord::Base) - Connections.const_set(name.classify, klass) - klass.abstract_class = true + def get_or_set_connection_class + if Connections.const_defined?(name.classify) + klass = Connections.const_get(name.classify) + else + klass = Class.new(ActiveRecord::Base) + Connections.const_set(name.classify, klass) + klass.abstract_class = true + end + klass end - klass - end - def create_connection_class - klass = get_or_set_connection_class - klass.remove_connection - klass.establish_connection ActiveRecord::Base.connection_pool.spec.config[:shards][name].with_indifferent_access - klass - end + def create_connection_class + klass = get_or_set_connection_class + klass.remove_connection + klass.establish_connection ActiveRecord::Base.connection_pool.spec.config[:shards][name].with_indifferent_access + klass + end end end diff --git a/lib/active_record/turntable/sql_tree_patch.rb b/lib/active_record/turntable/sql_tree_patch.rb index c1754b67..b3e1b1d3 100644 --- a/lib/active_record/turntable/sql_tree_patch.rb +++ b/lib/active_record/turntable/sql_tree_patch.rb @@ -1,22 +1,22 @@ -require 'sql_tree' -require 'active_support/core_ext/kernel/reporting' +require "sql_tree" +require "active_support/core_ext/kernel/reporting" module SQLTree class << self attr_accessor :identifier_quote_field_char end - self.identifier_quote_field_char = '`' + self.identifier_quote_field_char = "`" end class SQLTree::Token - extended_keywords = ['BINARY', 'LIMIT', 'OFFSET', 'INDEX', 'KEY', 'USE', 'FORCE', 'IGNORE'] + extended_keywords = %w(BINARY LIMIT OFFSET INDEX KEY USE FORCE IGNORE) KEYWORDS.concat(extended_keywords) extended_keywords.each do |kwd| const_set(kwd, Class.new(SQLTree::Token::Keyword)) end - BINARY_ESCAPE = Class.new(SQLTree::Token).new('x') + BINARY_ESCAPE = Class.new(SQLTree::Token).new("x") def possible_index_hint? [SQLTree::Token::USE, SQLTree::Token::FORCE, SQLTree::Token::IGNORE].include?(self.class) @@ -29,7 +29,7 @@ def index_keyword? class SQLTree::Tokenizer def tokenize_quoted_string(&block) # :yields: SQLTree::Token::String - string = '' + string = "" until next_char.nil? || current_char == "'" string << (current_char == "\\" ? instance_eval("%@\\#{next_char.gsub('@', '\@')}@") : current_char) end @@ -38,34 +38,33 @@ def tokenize_quoted_string(&block) # :yields: SQLTree::Token::String # @note Override to handle x'..' binary string def each_token(&block) # :yields: SQLTree::Token - while next_char case current_char - when /^\s?$/; # whitespace, go to next character - when '('; handle_token(SQLTree::Token::LPAREN, &block) - when ')'; handle_token(SQLTree::Token::RPAREN, &block) - when '.'; handle_token(SQLTree::Token::DOT, &block) - when ','; handle_token(SQLTree::Token::COMMA, &block) - when /\d/; tokenize_number(&block) - when "'"; tokenize_quoted_string(&block) - when 'E', 'x', 'X'; tokenize_possible_escaped_string(&block) - when /\w/; tokenize_keyword(&block) - when OPERATOR_CHARS; tokenize_operator(&block) - when SQLTree.identifier_quote_char; tokenize_quoted_identifier(&block) + when /^\s?$/ then # whitespace, go to next character + when "(" then handle_token(SQLTree::Token::LPAREN, &block) + when ")" then handle_token(SQLTree::Token::RPAREN, &block) + when "." then handle_token(SQLTree::Token::DOT, &block) + when "," then handle_token(SQLTree::Token::COMMA, &block) + when /\d/ then tokenize_number(&block) + when "'" then tokenize_quoted_string(&block) + when "E", "x", 'X' then tokenize_possible_escaped_string(&block) + when /\w/ then tokenize_keyword(&block) + when OPERATOR_CHARS then tokenize_operator(&block) + when SQLTree.identifier_quote_char then tokenize_quoted_identifier(&block) end end # Make sure to yield any tokens that are still stashed on the queue. empty_keyword_queue!(&block) end - alias :each :each_token + alias_method :each, :each_token def tokenize_possible_escaped_string(&block) if peek_char == "'" token = case current_char - when 'E' + when "E" SQLTree::Token::STRING_ESCAPE - when 'x', 'X' + when "x", "X" SQLTree::Token::BINARY_ESCAPE end handle_token(token, &block) @@ -87,16 +86,16 @@ class SelectQuery < Base def to_sql(options = {}) raise "At least one SELECT expression is required" if self.select.empty? - sql = (self.distinct) ? "SELECT DISTINCT " : "SELECT " - sql << select.map { |s| s.to_sql(options) }.join(', ') - sql << " FROM " << from.map { |f| f.to_sql(options) }.join(', ') if from + sql = self.distinct ? "SELECT DISTINCT " : "SELECT " + sql << select.map { |s| s.to_sql(options) }.join(", ") + sql << " FROM " << from.map { |f| f.to_sql(options) }.join(", ") if from sql << " WHERE " << where.to_sql(options) if where - sql << " GROUP BY " << group_by.map { |g| g.to_sql(options) }.join(', ') if group_by - sql << " ORDER BY " << order_by.map { |o| o.to_sql(options) }.join(', ') if order_by + sql << " GROUP BY " << group_by.map { |g| g.to_sql(options) }.join(", ") if group_by + sql << " ORDER BY " << order_by.map { |o| o.to_sql(options) }.join(", ") if order_by sql << " HAVING " << having.to_sql(options) if having - sql << " LIMIT " << Array(limit).map {|f| f.to_sql(options) }.join(', ') if limit + sql << " LIMIT " << Array(limit).map { |f| f.to_sql(options) }.join(", ") if limit sql << " OFFSET " << offset.to_sql(options) if offset - return sql + sql end def self.parse(tokens) @@ -116,12 +115,12 @@ def self.parse(tokens) select_node.having = self.parse_having_clause(tokens) if SQLTree::Token::HAVING === tokens.peek end select_node.order_by = self.parse_order_clause(tokens) if SQLTree::Token::ORDER === tokens.peek - if SQLTree::Token::LIMIT === tokens.peek and list = self.parse_limit_clause(tokens) + if SQLTree::Token::LIMIT === tokens.peek && (list = self.parse_limit_clause(tokens)) select_node.offset = list.shift if list.size > 1 select_node.limit = list.shift end select_node.offset = self.parse_offset_clause(tokens) if SQLTree::Token::OFFSET === tokens.peek - return select_node + select_node end def self.parse_limit_clause(tokens) @@ -137,14 +136,14 @@ def self.parse_offset_clause(tokens) class SubQuery < SelectQuery def to_sql(options = {}) - "("+super(options)+")" + "(" + super(options) + ")" end def self.parse(tokens) tokens.consume(SQLTree::Token::LPAREN) select_node = super(tokens) tokens.consume(SQLTree::Token::RPAREN) - return select_node + select_node end end @@ -152,14 +151,16 @@ class TableReference < Base leaf :index_hint def initialize(table, table_alias = nil, index_hint = nil) - @table, @table_alias, @index_hint = table, table_alias, index_hint + @table = table + @table_alias = table_alias + @index_hint = index_hint end - def to_sql(options={}) + def to_sql(options = {}) sql = (SQLTree::Node::SubQuery === table) ? table.to_sql : quote_field_name(table) sql << " AS " << quote_field_name(table_alias) if table_alias sql << " " << index_hint.to_sql if index_hint - return sql + sql end def self.parse(tokens) @@ -167,7 +168,7 @@ def self.parse(tokens) tokens.next table_reference = self.new(tokens.current.literal) if tokens.peek && !tokens.peek.possible_index_hint? && - (SQLTree::Token::AS === tokens.peek || SQLTree::Token::Identifier === tokens.peek) + (SQLTree::Token::AS === tokens.peek || SQLTree::Token::Identifier === tokens.peek) tokens.consume(SQLTree::Token::AS) if SQLTree::Token::AS === tokens.peek table_reference.table_alias = tokens.next.literal end @@ -194,12 +195,14 @@ class IndexHint < Base leaf :index_list def initialize(hint_method, hint_key, index_list) - @hint_method, @hint_key, @index_list = hint_method, hint_key, index_list + @hint_method = hint_method + @hint_key = hint_key + @index_list = index_list end - def to_sql(options={}) + def to_sql(options = {}) sql = "#{hint_method} #{hint_key} " - sql << "(#{index_list.map {|idx| idx.to_sql }.join(' ')})" + sql << "(#{index_list.map(&:to_sql).join(' ')})" sql end @@ -225,20 +228,20 @@ class BinaryOperator < SQLTree::Node::Expression end def self.parse_rhs(tokens, precedence, operator = nil) - if ['IN', 'NOT IN'].include?(operator) + if ["IN", "NOT IN"].include?(operator) if SQLTree::Token::SELECT === tokens.peek(2) return SQLTree::Node::SubQuery.parse(tokens) else return List.parse(tokens) end - elsif ['IS', 'IS NOT'].include?(operator) + elsif ["IS", "IS NOT"].include?(operator) tokens.consume(SQLTree::Token::NULL) return SQLTree::Node::Expression::Value.new(nil) - elsif ['BETWEEN'].include?(operator) + elsif ["BETWEEN"].include?(operator) expr = parse_atomic(tokens) operator = parse_operator(tokens) rhs = parse_rhs(tokens, precedence, operator) - expr = self.new(:operator => operator, :lhs => expr, :rhs => rhs) + expr = self.new(operator: operator, lhs: expr, rhs: rhs) return expr else return parse(tokens, precedence + 1) @@ -252,7 +255,7 @@ class PrefixOperator < SQLTree::Node::Expression class Field < Variable def to_sql(options = {}) - @table.nil? ? quote_field_name(@name) : quote_field_name(@table) + '.' + quote_field_name(@name) + @table.nil? ? quote_field_name(@name) : quote_field_name(@table) + "." + quote_field_name(@name) end end @@ -268,11 +271,11 @@ def initialize(value, escape = nil) def to_sql(options = {}) case value - when nil; 'NULL' - when String; "#{escape_string}#{quote_str(@value)}" - when Numeric; @value.to_s - when Date; @value.strftime("'%Y-%m-%d'") - when DateTime, Time; @value.strftime("'%Y-%m-%d %H:%M:%S'") + when nil then "NULL" + when String then "#{escape_string}#{quote_str(@value)}" + when Numeric then @value.to_s + when Date then @value.strftime("'%Y-%m-%d'") + when DateTime, Time then @value.strftime("'%Y-%m-%d %H:%M:%S'") else raise "Don't know how te represent this value in SQL!" end end @@ -321,14 +324,13 @@ def self.parse_atomic(tokens) end class InsertQuery < Base - - def to_sql(options = { }) - sql = "INSERT INTO #{ table.to_sql(options)} " - sql << '(' + fields.map { |f| f.to_sql(options) }.join(', ') + ') ' if fields - sql << 'VALUES' + def to_sql(options = {}) + sql = "INSERT INTO #{table.to_sql(options)} " + sql << "(" + fields.map { |f| f.to_sql(options) }.join(", ") + ") " if fields + sql << "VALUES" sql << values.map do |value| - ' (' + value.map { |v| v.to_sql(options) }.join(', ') + ')' - end.join(',') + " (" + value.map { |v| v.to_sql(options) }.join(", ") + ")" + end.join(",") sql end @@ -344,7 +346,7 @@ def self.parse_value_list(tokens) values << parse_list(tokens) tokens.consume(SQLTree::Token::RPAREN) end - return values + values end end end diff --git a/lib/active_record/turntable/util.rb b/lib/active_record/turntable/util.rb index c4223d69..cda3f476 100644 --- a/lib/active_record/turntable/util.rb +++ b/lib/active_record/turntable/util.rb @@ -31,7 +31,7 @@ def earlier_than_ar42? end def ar_version - ActiveRecord::gem_version + ActiveRecord.gem_version end end end diff --git a/lib/active_record/turntable/version.rb b/lib/active_record/turntable/version.rb index 18eef6df..fb6cd13e 100644 --- a/lib/active_record/turntable/version.rb +++ b/lib/active_record/turntable/version.rb @@ -1,5 +1,5 @@ module ActiveRecord module Turntable - VERSION = "2.3.3" + VERSION = "2.3.3".freeze end end diff --git a/lib/activerecord-turntable.rb b/lib/activerecord-turntable.rb index 913108ed..cb6196ac 100644 --- a/lib/activerecord-turntable.rb +++ b/lib/activerecord-turntable.rb @@ -1,2 +1,2 @@ -require 'active_record' -require 'active_record/turntable' +require "active_record" +require "active_record/turntable" diff --git a/script/performance/algorithm b/script/performance/algorithm index 37033b79..687cd2fe 100755 --- a/script/performance/algorithm +++ b/script/performance/algorithm @@ -1,13 +1,13 @@ #!/usr/bin/env ruby -require 'rspec' -require File.join(File.dirname(__FILE__), '../../../spec/spec_helper') -require 'benchmark' +require "rspec" +require File.join(File.dirname(__FILE__), "../../../spec/spec_helper") +require "benchmark" def setup_algorithm(n, alg = "Range") config = { "shards" => n.times.map do |i| - {"connection" => "connection_#{i}", "less_than" => (i+1) * 100} - end + { "connection" => "connection_#{i}", "less_than" => (i + 1) * 100 } + end, } "ActiveRecord::Turntable::Algorithm::#{alg}Algorithm".constantize.new(config) end @@ -18,15 +18,14 @@ Benchmark.bm(40) do |x| algorithm = setup_algorithm(n, alg) x.report("#{alg}: selrand(#{n}) * 1000") { 1000.times do - algorithm.calculate(rand(n*100)) + algorithm.calculate(rand(n * 100)) end } x.report("#{alg}: sellast(#{n}) * 1000") { 1000.times do - algorithm.calculate(n*100-1) + algorithm.calculate(n * 100 - 1) end } end end end - diff --git a/spec/active_record/turntable/active_record_ext/association_preloader_spec.rb b/spec/active_record/turntable/active_record_ext/association_preloader_spec.rb index 31f9381c..d51c4a5a 100644 --- a/spec/active_record/turntable/active_record_ext/association_preloader_spec.rb +++ b/spec/active_record/turntable/active_record_ext/association_preloader_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" describe ActiveRecord::Turntable::ActiveRecordExt::Association do before(:all) do @@ -11,7 +11,7 @@ end let!(:user) do - user = User.new({:nickname => 'user1'}) + user = User.new({ nickname: "user1" }) user.id = 1 user.save user @@ -49,7 +49,7 @@ end it "its has_many targets should be assigned all related object" do - expect(subject.cards_users_histories).to include(*cards_users_histories.select { |history| history.cards_user_id == subject.id} ) + expect(subject.cards_users_histories).to include(*cards_users_histories.select { |history| history.cards_user_id == subject.id }) end end @@ -64,7 +64,7 @@ end it "its has_many targets should be assigned all related object" do - expect(subject.events_users_histories_with_foreign_shard_key).to include(*events_users_histories.select { |history| history.cards_user_id == subject.id} ) + expect(subject.events_users_histories_with_foreign_shard_key).to include(*events_users_histories.select { |history| history.cards_user_id == subject.id }) end end diff --git a/spec/active_record/turntable/active_record_ext/association_spec.rb b/spec/active_record/turntable/active_record_ext/association_spec.rb index b853dd71..8c8b1e69 100644 --- a/spec/active_record/turntable/active_record_ext/association_spec.rb +++ b/spec/active_record/turntable/active_record_ext/association_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" describe ActiveRecord::Turntable::ActiveRecordExt::Association do before(:all) do @@ -11,7 +11,7 @@ end let!(:user) do - user = User.new({:nickname => 'user1'}) + user = User.new({ nickname: "user1" }) user.id = 1 user.save user diff --git a/spec/active_record/turntable/active_record_ext/clever_load_spec.rb b/spec/active_record/turntable/active_record_ext/clever_load_spec.rb index dbaa04ea..089b38b9 100644 --- a/spec/active_record/turntable/active_record_ext/clever_load_spec.rb +++ b/spec/active_record/turntable/active_record_ext/clever_load_spec.rb @@ -1,5 +1,5 @@ -require 'spec_helper' -require 'logger' +require "spec_helper" +require "logger" describe ActiveRecord::Turntable::ActiveRecordExt::CleverLoad do before(:all) do @@ -10,14 +10,14 @@ establish_connection_to(:test) truncate_shard - @user1 = User.new({:nickname => 'user1'}) + @user1 = User.new({ nickname: "user1" }) @user1.id = 1 @user1.save - @user1_status = @user1.create_user_status(:hp => 10, :mp => 10) - @user2 = User.new({:nickname => 'user2'}) + @user1_status = @user1.create_user_status(hp: 10, mp: 10) + @user2 = User.new({ nickname: "user2" }) @user2.id = 2 @user2.save - @user2_status = @user2.create_user_status(:hp => 20, :mp => 10) + @user2_status = @user2.create_user_status(hp: 20, mp: 10) end context "When a model has has_one relation" do diff --git a/spec/active_record/turntable/active_record_ext/fixture_set_spec.rb b/spec/active_record/turntable/active_record_ext/fixture_set_spec.rb index cc7a5b2a..00ddb0e3 100644 --- a/spec/active_record/turntable/active_record_ext/fixture_set_spec.rb +++ b/spec/active_record/turntable/active_record_ext/fixture_set_spec.rb @@ -1,7 +1,7 @@ -require 'spec_helper' +require "spec_helper" -require 'active_record' -require 'active_record/turntable/active_record_ext/fixtures' +require "active_record" +require "active_record/turntable/active_record_ext/fixtures" describe ActiveRecord::FixtureSet do before(:all) do @@ -21,7 +21,7 @@ subject { ActiveRecord::FixtureSet.create_fixtures(fixtures_root, "cards") } it { is_expected.to be_instance_of(Array) } it "creates card records" do - expect {subject}.to change {Card.count}.from(0).to(cards.size) + expect { subject }.to change { Card.count }.from(0).to(cards.size) end end end diff --git a/spec/active_record/turntable/active_record_ext/locking_optimistic_spec.rb b/spec/active_record/turntable/active_record_ext/locking_optimistic_spec.rb index 45720e64..c5ced86d 100644 --- a/spec/active_record/turntable/active_record_ext/locking_optimistic_spec.rb +++ b/spec/active_record/turntable/active_record_ext/locking_optimistic_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" describe ActiveRecord::Turntable::ActiveRecordExt::LockingOptimistic do before(:all) do diff --git a/spec/active_record/turntable/active_record_ext/migration_spec.rb b/spec/active_record/turntable/active_record_ext/migration_spec.rb index e585d566..5b4c4cf5 100644 --- a/spec/active_record/turntable/active_record_ext/migration_spec.rb +++ b/spec/active_record/turntable/active_record_ext/migration_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" describe ActiveRecord::Turntable::Migration do before(:all) do @@ -16,7 +16,7 @@ context "With clusters definitions" do let(:migration_class) { klass = Class.new(ActiveRecord::Migration) { - clusters :user_cluster + clusters :user_cluster } } let(:cluster_config) { ActiveRecord::Base.turntable_config["clusters"]["user_cluster"] } diff --git a/spec/active_record/turntable/active_record_ext/persistence_spec.rb b/spec/active_record/turntable/active_record_ext/persistence_spec.rb index f056b552..53e2a389 100644 --- a/spec/active_record/turntable/active_record_ext/persistence_spec.rb +++ b/spec/active_record/turntable/active_record_ext/persistence_spec.rb @@ -1,5 +1,5 @@ -require 'spec_helper' -require 'logger' +require "spec_helper" +require "logger" describe ActiveRecord::Turntable::ActiveRecordExt::Persistence do before(:all) do @@ -19,20 +19,20 @@ end let(:user) { - u = User.new({:nickname => 'foobar'}) + u = User.new({ nickname: "foobar" }) u.id = 1 u.updated_at = Time.current - 1.day u.save u } let(:user_status){ - stat = user.create_user_status(:hp => 10, :mp => 10) + stat = user.create_user_status(hp: 10, mp: 10) stat.updated_at = Time.current - 1.day stat.save stat } let(:card){ - Card.create!(:name => 'foobar') + Card.create!(name: "foobar") } let(:cards_user){ user.cards_users.create(card: card) @@ -41,7 +41,7 @@ context "with blob column" do let(:blob_value) { "\123\123\123" } let(:user) { - u = User.new(:nickname => 'x', :blob => blob_value ) + u = User.new(nickname: "x", blob: blob_value) u.id = 1 u.save u @@ -148,7 +148,7 @@ def on_update expect { cards_user.reload }.to_not raise_error - expect(strio.string.split("\n").select {|stmt| stmt =~ /SELECT/ and stmt !~ /Turntable/ }).to have(1).items + expect(strio.string.split("\n").select { |stmt| stmt =~ /SELECT/ and stmt !~ /Turntable/ }).to have(1).items end it "should execute one query when touching" do @@ -157,7 +157,7 @@ def on_update ActiveRecord::Base.logger = Logger.new(strio) expect { cards_user.touch }.to_not raise_error - expect(strio.string.split("\n").select {|stmt| stmt =~ /UPDATE/ and stmt !~ /Turntable/ }).to have(1).items + expect(strio.string.split("\n").select { |stmt| stmt =~ /UPDATE/ and stmt !~ /Turntable/ }).to have(1).items end it "should execute one query when locking" do @@ -166,7 +166,7 @@ def on_update ActiveRecord::Base.logger = Logger.new(strio) expect { cards_user.lock! }.to_not raise_error - expect(strio.string.split("\n").select {|stmt| stmt =~ /SELECT/ and stmt !~ /Turntable/ }).to have(1).items + expect(strio.string.split("\n").select { |stmt| stmt =~ /SELECT/ and stmt !~ /Turntable/ }).to have(1).items end it "should execute one query when update_columns" do @@ -175,7 +175,7 @@ def on_update ActiveRecord::Base.logger = Logger.new(strio) expect { cards_user.update_columns(num: 10) }.to_not raise_error - expect(strio.string.split("\n").select {|stmt| stmt =~ /UPDATE/ and stmt !~ /Turntable/ }).to have(1).items + expect(strio.string.split("\n").select { |stmt| stmt =~ /UPDATE/ and stmt !~ /Turntable/ }).to have(1).items end end @@ -205,5 +205,4 @@ def on_update it { is_expected.to be_instance_of(CardsUser) } it { is_expected.to eq(cards_user) } end - end diff --git a/spec/active_record/turntable/active_record_ext/sequencer_spec.rb b/spec/active_record/turntable/active_record_ext/sequencer_spec.rb index 726b1bbc..37e7f3f8 100644 --- a/spec/active_record/turntable/active_record_ext/sequencer_spec.rb +++ b/spec/active_record/turntable/active_record_ext/sequencer_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" describe ActiveRecord::Turntable::ActiveRecordExt::Sequencer do before(:all) do diff --git a/spec/active_record/turntable/active_record_ext/test_fixtures_spec.rb b/spec/active_record/turntable/active_record_ext/test_fixtures_spec.rb index 4e8bbea8..fcd90bdb 100644 --- a/spec/active_record/turntable/active_record_ext/test_fixtures_spec.rb +++ b/spec/active_record/turntable/active_record_ext/test_fixtures_spec.rb @@ -1,7 +1,7 @@ -require 'spec_helper' +require "spec_helper" -require 'active_record' -require 'active_record/turntable/active_record_ext/fixtures' +require "active_record" +require "active_record/turntable/active_record_ext/fixtures" describe ActiveRecord::TestFixtures do before(:all) do diff --git a/spec/active_record/turntable/algorithm/modulo_algorithm_spec.rb b/spec/active_record/turntable/algorithm/modulo_algorithm_spec.rb index 610f78b7..347bdc5d 100644 --- a/spec/active_record/turntable/algorithm/modulo_algorithm_spec.rb +++ b/spec/active_record/turntable/algorithm/modulo_algorithm_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" describe ActiveRecord::Turntable::Algorithm::ModuloAlgorithm do before(:all) do @@ -27,9 +27,8 @@ context "#calculate with a value that is not a number" do it "raises ActiveRecord::Turntable::CannotSpecifyShardError" do - expect { @alg.calculate('a') }.to raise_error(ActiveRecord::Turntable::CannotSpecifyShardError) + expect { @alg.calculate("a") }.to raise_error(ActiveRecord::Turntable::CannotSpecifyShardError) end end end - end diff --git a/spec/active_record/turntable/algorithm/range_algorithm_spec.rb b/spec/active_record/turntable/algorithm/range_algorithm_spec.rb index 16ac5b92..10d346d3 100644 --- a/spec/active_record/turntable/algorithm/range_algorithm_spec.rb +++ b/spec/active_record/turntable/algorithm/range_algorithm_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" describe ActiveRecord::Turntable::Algorithm::RangeAlgorithm do before(:all) do @@ -27,9 +27,8 @@ context "#calculate with 10000000" do it "raises ActiveRecord::Turntable::CannotSpecifyShardError" do - expect { @alg.calculate(10000000) }.to raise_error(ActiveRecord::Turntable::CannotSpecifyShardError) + expect { @alg.calculate(10_000_000) }.to raise_error(ActiveRecord::Turntable::CannotSpecifyShardError) end end end - end diff --git a/spec/active_record/turntable/algorithm/range_bsearch_algorithm_spec.rb b/spec/active_record/turntable/algorithm/range_bsearch_algorithm_spec.rb index bd77eac8..2c81acc2 100644 --- a/spec/active_record/turntable/algorithm/range_bsearch_algorithm_spec.rb +++ b/spec/active_record/turntable/algorithm/range_bsearch_algorithm_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" describe ActiveRecord::Turntable::Algorithm::RangeBsearchAlgorithm do before(:all) do @@ -27,9 +27,8 @@ context "#calculate with 10000000" do it "raises ActiveRecord::Turntable::CannotSpecifyShardError" do - expect { @alg.calculate(10000000) }.to raise_error(ActiveRecord::Turntable::CannotSpecifyShardError) + expect { @alg.calculate(10_000_000) }.to raise_error(ActiveRecord::Turntable::CannotSpecifyShardError) end end end - end diff --git a/spec/active_record/turntable/algorithm_spec.rb b/spec/active_record/turntable/algorithm_spec.rb index a87685d8..979e4bf6 100644 --- a/spec/active_record/turntable/algorithm_spec.rb +++ b/spec/active_record/turntable/algorithm_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" describe ActiveRecord::Turntable::Algorithm do before(:all) do @@ -31,7 +31,7 @@ end it "called with 10 returns {\"user_shard_1\" => 10}" do - expect(algorithm.calculate_used_shards_with_weight(10)).to eq({"user_shard_1" => 10}) + expect(algorithm.calculate_used_shards_with_weight(10)).to eq({ "user_shard_1" => 10 }) end it "called with 65000 returns 2 items" do @@ -39,7 +39,7 @@ end it "called with 65000 returns {\"user_shard_1\" => 39999, \"user_shard_2\" => 25001}" do - expect(algorithm.calculate_used_shards_with_weight(65000)).to eq({"user_shard_1" => 39999, "user_shard_2" => 25001}) + expect(algorithm.calculate_used_shards_with_weight(65000)).to eq({ "user_shard_1" => 39999, "user_shard_2" => 25001 }) end end end @@ -70,7 +70,7 @@ end it "called with 10 returns {\"user_shard_1\" => 10}" do - expect(algorithm.calculate_used_shards_with_weight(10)).to eq({"user_shard_1" => 10}) + expect(algorithm.calculate_used_shards_with_weight(10)).to eq({ "user_shard_1" => 10 }) end it "called with 65000 returns 2 items" do @@ -78,7 +78,7 @@ end it "called with 65000 returns {\"user_shard_1\" => 39999, \"user_shard_2\" => 25001}" do - expect(algorithm.calculate_used_shards_with_weight(65000)).to eq({"user_shard_1" => 39999, "user_shard_2" => 25001}) + expect(algorithm.calculate_used_shards_with_weight(65000)).to eq({ "user_shard_1" => 39999, "user_shard_2" => 25001 }) end end end diff --git a/spec/active_record/turntable/base_spec.rb b/spec/active_record/turntable/base_spec.rb index 9851a16d..0fd28615 100644 --- a/spec/active_record/turntable/base_spec.rb +++ b/spec/active_record/turntable/base_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" describe ActiveRecord::Turntable::Base do before(:all) do diff --git a/spec/active_record/turntable/cluster_spec.rb b/spec/active_record/turntable/cluster_spec.rb index cb81a1e0..74612ea9 100644 --- a/spec/active_record/turntable/cluster_spec.rb +++ b/spec/active_record/turntable/cluster_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" describe ActiveRecord::Turntable::Cluster do before(:all) do diff --git a/spec/active_record/turntable/config_spec.rb b/spec/active_record/turntable/config_spec.rb index 74814219..19fa50b3 100644 --- a/spec/active_record/turntable/config_spec.rb +++ b/spec/active_record/turntable/config_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" describe ActiveRecord::Turntable::Config do before(:all) do diff --git a/spec/active_record/turntable/connection_proxy_spec.rb b/spec/active_record/turntable/connection_proxy_spec.rb index a4255d29..fa7d49a8 100644 --- a/spec/active_record/turntable/connection_proxy_spec.rb +++ b/spec/active_record/turntable/connection_proxy_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" describe ActiveRecord::Turntable::ConnectionProxy do before(:all) do @@ -91,7 +91,6 @@ expect { @user1.save! }.not_to raise_error - end it "should be saved to user_shard_2 with id = 30000" do @@ -102,7 +101,7 @@ end it "User.where('id IN (1, 30000)') returns 2 record" do - expect(User.where(:id => [1, 30000]).all.size).to eq(2) + expect(User.where(id: [1, 30000]).all.size).to eq(2) end it "count should be 2" do @@ -120,11 +119,11 @@ truncate_shard @user1 = User.new @user1.id = 1 - @user1.nickname = 'user1' + @user1.nickname = "user1" @user1.save! @user2 = User.new @user2.id = 30000 - @user2.nickname = 'user2' + @user2.nickname = "user2" @user2.save! end @@ -167,11 +166,11 @@ truncate_shard @user1 = User.new @user1.id = 1 - @user1.nickname = 'user1' + @user1.nickname = "user1" @user1.save! @user2 = User.new @user2.id = 30000 - @user2.nickname = 'user2' + @user2.nickname = "user2" @user2.save! end @@ -185,11 +184,11 @@ truncate_shard @user1 = User.new @user1.id = 1 - @user1.nickname = 'user1' + @user1.nickname = "user1" @user1.save! @user2 = User.new @user2.id = 30000 - @user2.nickname = 'user2' + @user2.nickname = "user2" @user2.save! end @@ -203,15 +202,15 @@ truncate_shard @user1 = User.new @user1.id = 1 - @user1.nickname = 'user1' + @user1.nickname = "user1" @user1.save! @user2 = User.new @user2.id = 30000 - @user2.nickname = 'user2' + @user2.nickname = "user2" @user2.save! end - subject { User.exists?(nickname: 'user2') } + subject { User.exists?(nickname: "user2") } it { is_expected.to be_truthy } end @@ -221,15 +220,15 @@ truncate_shard @user1 = User.new @user1.id = 1 - @user1.nickname = 'user1' + @user1.nickname = "user1" @user1.save! @user2 = User.new @user2.id = 30000 - @user2.nickname = 'user2' + @user2.nickname = "user2" @user2.save! end - subject { User.exists?(nickname: 'user999') } + subject { User.exists?(nickname: "user999") } it { is_expected.to be_falsey } end @@ -239,11 +238,11 @@ truncate_shard @user1 = User.new @user1.id = 1 - @user1.nickname = 'user1' + @user1.nickname = "user1" @user1.save! @user2 = User.new @user2.id = 30000 - @user2.nickname = 'user2' + @user2.nickname = "user2" @user2.save! end diff --git a/spec/active_record/turntable/finder_spec.rb b/spec/active_record/turntable/finder_spec.rb index 05124a14..2072dfb4 100644 --- a/spec/active_record/turntable/finder_spec.rb +++ b/spec/active_record/turntable/finder_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" describe "ActiveRecord::FinderMethods" do before(:all) do diff --git a/spec/active_record/turntable/mixer/fader_spec.rb b/spec/active_record/turntable/mixer/fader_spec.rb index 05085a3c..d3d40aec 100644 --- a/spec/active_record/turntable/mixer/fader_spec.rb +++ b/spec/active_record/turntable/mixer/fader_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" describe ActiveRecord::Turntable::Mixer::Fader do end diff --git a/spec/active_record/turntable/mixer_spec.rb b/spec/active_record/turntable/mixer_spec.rb index a76070d2..d2d450dd 100644 --- a/spec/active_record/turntable/mixer_spec.rb +++ b/spec/active_record/turntable/mixer_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" describe ActiveRecord::Turntable::Mixer do before(:all) do @@ -85,7 +85,7 @@ } it { is_expected.to be_instance_of Array } - it { is_expected.to eq([1,2,3,4,5]) } + it { is_expected.to eq([1, 2, 3, 4, 5]) } end context "When call find_shard_keys with not determine shardkey condition" do @@ -108,7 +108,5 @@ it { is_expected.to eq([]) } end end - end - end diff --git a/spec/active_record/turntable/rack/query_cache_spec.rb b/spec/active_record/turntable/rack/query_cache_spec.rb index 759b6f78..843b06e6 100644 --- a/spec/active_record/turntable/rack/query_cache_spec.rb +++ b/spec/active_record/turntable/rack/query_cache_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" describe ActiveRecord::Turntable::Rack::QueryCache do before(:all) do @@ -10,7 +10,7 @@ truncate_shard end - let(:mw) { ActiveRecord::Turntable::Rack::QueryCache.new lambda {|env| [200, {}]} } + let(:mw) { ActiveRecord::Turntable::Rack::QueryCache.new lambda { |_env| [200, {}] } } subject { mw.call({}) } it "should returns 200 response" do diff --git a/spec/active_record/turntable/sequencer/api_spec.rb b/spec/active_record/turntable/sequencer/api_spec.rb index a7bf9595..1a0bf9cc 100644 --- a/spec/active_record/turntable/sequencer/api_spec.rb +++ b/spec/active_record/turntable/sequencer/api_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" describe ActiveRecord::Turntable::Sequencer::Api do before(:all) do @@ -18,7 +18,7 @@ describe "#next_sequence_value" do before do - stub_request(:get, next_sequence_uri).to_return(:body => api_response.to_s) + stub_request(:get, next_sequence_uri).to_return(body: api_response.to_s) end subject { sequencer.next_sequence_value(sequence_name) } @@ -28,7 +28,7 @@ describe "#current_sequence_value" do before do - stub_request(:get, current_sequence_uri).to_return(:body => api_response.to_s) + stub_request(:get, current_sequence_uri).to_return(body: api_response.to_s) end subject { sequencer.current_sequence_value(sequence_name) } diff --git a/spec/active_record/turntable/sequencer/barrage_spec.rb b/spec/active_record/turntable/sequencer/barrage_spec.rb index 2489b998..68d8dab0 100644 --- a/spec/active_record/turntable/sequencer/barrage_spec.rb +++ b/spec/active_record/turntable/sequencer/barrage_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" describe ActiveRecord::Turntable::Sequencer::Barrage do before(:all) do @@ -7,7 +7,7 @@ let(:sequencer) { ActiveRecord::Turntable::Sequencer::Barrage.new(klass, options) } let(:sequence_name) { "hogefuga" } - let(:options) { { "options" => { "generators" => [ {"name" => "sequence", "length" => 16} ] } } } + let(:options) { { "options" => { "generators" => [{ "name" => "sequence", "length" => 16 }] } } } let(:klass) { Class.new } describe "#next_sequence_value" do diff --git a/spec/active_record/turntable/sequencer/mysql_spec.rb b/spec/active_record/turntable/sequencer/mysql_spec.rb index a9831043..2128671f 100644 --- a/spec/active_record/turntable/sequencer/mysql_spec.rb +++ b/spec/active_record/turntable/sequencer/mysql_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" describe ActiveRecord::Turntable::Sequencer::Mysql do before(:all) do diff --git a/spec/active_record/turntable/shard_spec.rb b/spec/active_record/turntable/shard_spec.rb index 00bb8238..ef24f3af 100644 --- a/spec/active_record/turntable/shard_spec.rb +++ b/spec/active_record/turntable/shard_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" describe ActiveRecord::Turntable::Shard do before(:all) do diff --git a/spec/active_record/turntable/sql_tree_patch_spec.rb b/spec/active_record/turntable/sql_tree_patch_spec.rb index 24524c8a..1a197507 100644 --- a/spec/active_record/turntable/sql_tree_patch_spec.rb +++ b/spec/active_record/turntable/sql_tree_patch_spec.rb @@ -1,5 +1,5 @@ -require 'spec_helper' -require 'active_record/turntable/sql_tree_patch' +require "spec_helper" +require "active_record/turntable/sql_tree_patch" describe SQLTree do before(:all) do diff --git a/spec/active_record/turntable/transaction_spec.rb b/spec/active_record/turntable/transaction_spec.rb index bc5eff34..762c5490 100644 --- a/spec/active_record/turntable/transaction_spec.rb +++ b/spec/active_record/turntable/transaction_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" describe "transaction" do before(:all) do @@ -13,7 +13,7 @@ describe "all_cluster_transaction" do let(:all_clusters) { clusters.values } - let(:shards) { all_clusters.map { |c| c.shards.values }.flatten(1) } + let(:shards) { all_clusters.flat_map { |c| c.shards.values } } it "all shards should begin transaction" do User.all_cluster_transaction { diff --git a/spec/active_record/turntable_spec.rb b/spec/active_record/turntable_spec.rb index 1461adae..ddd1dec0 100644 --- a/spec/active_record/turntable_spec.rb +++ b/spec/active_record/turntable_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" describe ActiveRecord::Turntable do before(:all) do diff --git a/spec/migrations/002_create_user_statuses.rb b/spec/migrations/002_create_user_statuses.rb index 8599d526..b5b5fce6 100644 --- a/spec/migrations/002_create_user_statuses.rb +++ b/spec/migrations/002_create_user_statuses.rb @@ -1,10 +1,10 @@ class CreateUserStatuses < ActiveRecord::Migration def self.up create_table :user_statuses do |t| - t.belongs_to :user, :null => false - t.integer :hp, :null => false, :default => 0 - t.integer :mp, :null => false, :default => 0 - t.datetime :deleted_at, :default => nil + t.belongs_to :user, null: false + t.integer :hp, null: false, default: 0 + t.integer :mp, null: false, default: 0 + t.datetime :deleted_at, default: nil t.timestamps end diff --git a/spec/migrations/003_create_cards.rb b/spec/migrations/003_create_cards.rb index a10be7f2..678922c3 100644 --- a/spec/migrations/003_create_cards.rb +++ b/spec/migrations/003_create_cards.rb @@ -1,9 +1,9 @@ class CreateCards < ActiveRecord::Migration def self.up create_table :cards do |t| - t.string :name, :null => false - t.integer :hp, :null => false, :default => 0 - t.integer :mp, :null => false, :default => 0 + t.string :name, null: false + t.integer :hp, null: false, default: 0 + t.integer :mp, null: false, default: 0 t.timestamps end end diff --git a/spec/migrations/004_create_cards_users.rb b/spec/migrations/004_create_cards_users.rb index 91b93d4a..6cfeae12 100644 --- a/spec/migrations/004_create_cards_users.rb +++ b/spec/migrations/004_create_cards_users.rb @@ -1,8 +1,8 @@ class CreateCardsUsers < ActiveRecord::Migration def self.up create_table :cards_users do |t| - t.belongs_to :card, :null => false - t.belongs_to :user, :null => false + t.belongs_to :card, null: false + t.belongs_to :user, null: false t.datetime :deleted_at t.timestamps diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 1623c18b..495b1dd2 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,29 +1,29 @@ -$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) +$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib")) $LOAD_PATH.unshift(File.dirname(__FILE__)) -require 'rubygems' -require 'bundler/setup' -require 'rspec/its' -require 'rspec/collection_matchers' -require 'webmock/rspec' -require 'pry' +require "rubygems" +require "bundler/setup" +require "rspec/its" +require "rspec/collection_matchers" +require "webmock/rspec" +require "pry" begin - require 'pry-byebug' + require "pry-byebug" rescue LoadError end -require 'activerecord-turntable' +require "activerecord-turntable" -require 'coveralls' +require "coveralls" Coveralls.wear! -MIGRATIONS_ROOT = File.expand_path(File.join(File.dirname(__FILE__), 'migrations')) +MIGRATIONS_ROOT = File.expand_path(File.join(File.dirname(__FILE__), "migrations")) # Requires supporting files with custom matchers and macros, etc, # in ./support/ and its subdirectories. -ActiveRecord::Base.configurations = YAML.load_file(File.join(File.dirname(__FILE__), 'config/database.yml')) +ActiveRecord::Base.configurations = YAML.load_file(File.join(File.dirname(__FILE__), "config/database.yml")) ActiveRecord::Base.establish_connection(:test) -Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f} +Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f } RSpec.configure do |config| include TurntableHelper @@ -32,6 +32,6 @@ config.run_all_when_everything_filtered = true config.before(:each) do - Dir[File.join(File.dirname(File.dirname(__FILE__)), 'spec/models/*.rb')].each { |f| require f } + Dir[File.join(File.dirname(File.dirname(__FILE__)), "spec/models/*.rb")].each { |f| require f } end end diff --git a/spec/support/turntable_helper.rb b/spec/support/turntable_helper.rb index eab68582..2b1e0ba5 100644 --- a/spec/support/turntable_helper.rb +++ b/spec/support/turntable_helper.rb @@ -1,4 +1,4 @@ -require 'active_record' +require "active_record" module TurntableHelper def reload_turntable!(config_file_name = nil) @@ -9,8 +9,8 @@ def reload_turntable!(config_file_name = nil) def establish_connection_to(env = :test) silence_warnings { - Object.const_set('RAILS_ENV', env.to_s) - Object.const_set('Rails', Object.new) + Object.const_set("RAILS_ENV", env.to_s) + Object.const_set("Rails", Object.new) allow(Rails).to receive(:env) { ActiveSupport::StringInquirer.new(RAILS_ENV) } ActiveRecord::Base.logger = Logger.new("/dev/null") } From 376b57378226b45cbe1e89d7562b47d193f632a6 Mon Sep 17 00:00:00 2001 From: gussan Date: Fri, 22 Apr 2016 11:27:25 +0900 Subject: [PATCH 004/125] Prefer hash keys than string keys on fetching turntable configuration values --- .../turntable/algorithm/modulo_algorithm.rb | 2 +- .../turntable/algorithm/range_algorithm.rb | 12 ++++++------ .../algorithm/range_bsearch_algorithm.rb | 16 ++++++++-------- lib/active_record/turntable/cluster.rb | 6 +++--- .../turntable/cluster_helper_methods.rb | 6 +++--- lib/active_record/turntable/migration.rb | 8 ++++---- lib/active_record/turntable/sequencer.rb | 8 ++++---- lib/active_record/turntable/sequencer/barrage.rb | 7 +++---- lib/active_record/turntable/shard.rb | 2 +- .../active_record_ext/migration_spec.rb | 4 ++-- 10 files changed, 35 insertions(+), 36 deletions(-) diff --git a/lib/active_record/turntable/algorithm/modulo_algorithm.rb b/lib/active_record/turntable/algorithm/modulo_algorithm.rb index 0ec4f918..048ffc3b 100644 --- a/lib/active_record/turntable/algorithm/modulo_algorithm.rb +++ b/lib/active_record/turntable/algorithm/modulo_algorithm.rb @@ -6,7 +6,7 @@ def initialize(config) end def calculate(key) - @config["shards"][key % @config["shards"].size]["connection"] + @config[:shards][key % @config[:shards].size][:connection] rescue raise ActiveRecord::Turntable::CannotSpecifyShardError, "cannot specify shard for key:#{key}" end diff --git a/lib/active_record/turntable/algorithm/range_algorithm.rb b/lib/active_record/turntable/algorithm/range_algorithm.rb index b468dee3..0d2ae7d7 100644 --- a/lib/active_record/turntable/algorithm/range_algorithm.rb +++ b/lib/active_record/turntable/algorithm/range_algorithm.rb @@ -7,29 +7,29 @@ def initialize(config) def calculate(key) idx = calculate_idx(key) - @config["shards"][idx]["connection"] + @config[:shards][idx][:connection] rescue raise ActiveRecord::Turntable::CannotSpecifyShardError, "cannot specify shard for key:#{key}" end def calculate_idx(key) - @config["shards"].find_index { |h| h["less_than"] > key } + @config[:shards].find_index { |h| h[:less_than] > key } end # { connection_name => weight, ... } def calculate_used_shards_with_weight(sequence_value) idx = calculate_idx(sequence_value) last_connection = calculate(sequence_value) - shards = @config["shards"][0..idx] + shards = @config[:shards][0..idx] weighted_hash = Hash.new { |h, k| h[k] = 0 } prev_max = 0 shards.each_with_index do |h, idx| - weighted_hash[h["connection"]] += if idx < shards.size - 1 - h["less_than"] - prev_max - 1 + weighted_hash[h[:connection]] += if idx < shards.size - 1 + h[:less_than] - prev_max - 1 else sequence_value - prev_max end - prev_max = h["less_than"] - 1 + prev_max = h[:less_than] - 1 end weighted_hash end diff --git a/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb b/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb index 38e55063..f69139bc 100644 --- a/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb +++ b/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb @@ -4,19 +4,19 @@ module ActiveRecord::Turntable::Algorithm class RangeBsearchAlgorithm < Base def initialize(config) @config = config - @config["shards"].sort_by! { |a| a["less_than"] } + @config[:shards].sort_by! { |a| a[:less_than] } end def calculate(key) idx = calculate_idx(key) - @config["shards"][idx]["connection"] + @config[:shards][idx][:connection] rescue raise ActiveRecord::Turntable::CannotSpecifyShardError, "cannot specify shard for key:#{key}" end def calculate_idx(key) - @config["shards"].bsearch_upper_boundary { |h| - h["less_than"] <=> key + @config[:shards].bsearch_upper_boundary { |h| + h[:less_than] <=> key } end @@ -24,16 +24,16 @@ def calculate_idx(key) def calculate_used_shards_with_weight(sequence_value) idx = calculate_idx(sequence_value) last_connection = calculate(sequence_value) - shards = @config["shards"][0..idx] + shards = @config[:shards][0..idx] weighted_hash = Hash.new { |h, k| h[k] = 0 } prev_max = 0 shards.each_with_index do |h, idx| - weighted_hash[h["connection"]] += if idx < shards.size - 1 - h["less_than"] - prev_max - 1 + weighted_hash[h[:connection]] += if idx < shards.size - 1 + h[:less_than] - prev_max - 1 else sequence_value - prev_max end - prev_max = h["less_than"] - 1 + prev_max = h[:less_than] - 1 end weighted_hash end diff --git a/lib/active_record/turntable/cluster.rb b/lib/active_record/turntable/cluster.rb index 64e3ed4d..72d2662c 100644 --- a/lib/active_record/turntable/cluster.rb +++ b/lib/active_record/turntable/cluster.rb @@ -15,18 +15,18 @@ def initialize(cluster_spec, options = {}) # setup sequencer seq = (@options[:seq] || @config[:seq]) if seq - if seq.values.size > 0 && seq.values.first["seq_type"] == "mysql" + if seq.values.size > 0 && seq.values.first[:seq_type] == "mysql" @seq_shard = SeqShard.new(seq.values.first) end end # setup shards @config[:shards].each do |spec| - @shards[spec["connection"]] ||= Shard.new(spec) + @shards[spec[:connection]] ||= Shard.new(spec) end # setup algorithm - alg_name = "ActiveRecord::Turntable::Algorithm::#{@config["algorithm"].camelize}Algorithm" + alg_name = "ActiveRecord::Turntable::Algorithm::#{@config[:algorithm].camelize}Algorithm" @algorithm = alg_name.constantize.new(@config) end diff --git a/lib/active_record/turntable/cluster_helper_methods.rb b/lib/active_record/turntable/cluster_helper_methods.rb index 305b4b97..d1bfcffc 100644 --- a/lib/active_record/turntable/cluster_helper_methods.rb +++ b/lib/active_record/turntable/cluster_helper_methods.rb @@ -31,9 +31,9 @@ def recursive_transaction(pools, options, &block) def force_connect_all_shards! conf = configurations[Rails.env] - shards = {} - shards = shards.merge(conf["shards"]) if conf["shards"] - shards = shards.merge(conf["seq"]) if conf["seq"] + shards = HashWithIndifferentAccess.new + shards = shards.merge(conf[:shards]) if conf[:shards] + shards = shards.merge(conf[:seq]) if conf[:seq] shards.each do |name, config| turntable_connections[name] ||= ActiveRecord::ConnectionAdapters::ConnectionPool.new(spec_for(config)) diff --git a/lib/active_record/turntable/migration.rb b/lib/active_record/turntable/migration.rb index 2ed45087..15c40fb7 100644 --- a/lib/active_record/turntable/migration.rb +++ b/lib/active_record/turntable/migration.rb @@ -16,13 +16,13 @@ def clusters(*cluster_names) config = ActiveRecord::Base.turntable_config (self.target_shards ||= []).concat( if cluster_names.first == :all - config["clusters"].map do |_name, cluster_conf| - cluster_conf["shards"].map { |shard| shard["connection"] } + config[:clusters].map do |_name, cluster_conf| + cluster_conf[:shards].map { |shard| shard[:connection] } end else cluster_names.map do |cluster_name| - config["clusters"][cluster_name]["shards"].map do |shard| - shard["connection"] + config[:clusters][cluster_name][:shards].map do |shard| + shard[:connection] end end.flatten end diff --git a/lib/active_record/turntable/sequencer.rb b/lib/active_record/turntable/sequencer.rb index 5bc23825..a012a866 100644 --- a/lib/active_record/turntable/sequencer.rb +++ b/lib/active_record/turntable/sequencer.rb @@ -24,9 +24,9 @@ class Sequencer cattr_reader :sequences, :tables def self.build(klass, sequence_name = nil, cluster_name = nil) - sequence_name ||= current_cluster_config_for(cluster_name || klass)["seq"].keys.first - seq_config = current_cluster_config_for(cluster_name || klass)["seq"][sequence_name] - seq_type = (seq_config["seq_type"] ? seq_config["seq_type"].to_sym : :mysql) + sequence_name ||= current_cluster_config_for(cluster_name || klass)[:seq].keys.first + seq_config = current_cluster_config_for(cluster_name || klass)[:seq][sequence_name] + seq_type = (seq_config[:seq_type] ? seq_config[:seq_type].to_sym : :mysql) @@tables[klass.table_name] ||= (@@sequences[sequence_name(klass.table_name, klass.primary_key)] ||= @@sequence_types[seq_type].new(klass, seq_config)) end @@ -58,7 +58,7 @@ def self.current_cluster_config_for(klass_or_name) else klass_or_name.turntable_cluster_name.to_s end - ActiveRecord::Base.turntable_config["clusters"][cluster_name] + ActiveRecord::Base.turntable_config[:clusters][cluster_name] end end end diff --git a/lib/active_record/turntable/sequencer/barrage.rb b/lib/active_record/turntable/sequencer/barrage.rb index b5e417cb..3e673e41 100644 --- a/lib/active_record/turntable/sequencer/barrage.rb +++ b/lib/active_record/turntable/sequencer/barrage.rb @@ -7,20 +7,19 @@ def initialize(klass, options = {}) require "barrage" @klass = klass @options = options["options"] - @barrage = get_barrage_instance end def next_sequence_value(sequence_name) - @barrage.next + barrage.next end def current_sequence_value(sequence_name) - @barrage.current + barrage.current end private - def get_barrage_instance + def barrage @@unique_barrage_instance[@options] ||= ::Barrage.new(@options) end end diff --git a/lib/active_record/turntable/shard.rb b/lib/active_record/turntable/shard.rb index 0d717605..f4ef165a 100644 --- a/lib/active_record/turntable/shard.rb +++ b/lib/active_record/turntable/shard.rb @@ -10,7 +10,7 @@ module Connections; end def initialize(shard_spec) @config = DEFAULT_CONFIG.merge(shard_spec) - @name = @config["connection"] + @name = @config[:connection] ActiveRecord::Base.turntable_connections[name] = connection_pool end diff --git a/spec/active_record/turntable/active_record_ext/migration_spec.rb b/spec/active_record/turntable/active_record_ext/migration_spec.rb index 5b4c4cf5..19cc09ab 100644 --- a/spec/active_record/turntable/active_record_ext/migration_spec.rb +++ b/spec/active_record/turntable/active_record_ext/migration_spec.rb @@ -19,8 +19,8 @@ clusters :user_cluster } } - let(:cluster_config) { ActiveRecord::Base.turntable_config["clusters"]["user_cluster"] } - let(:user_cluster_shards) { cluster_config["shards"].map { |s| s["connection"] } } + let(:cluster_config) { ActiveRecord::Base.turntable_config[:clusters][:user_cluster] } + let(:user_cluster_shards) { cluster_config[:shards].map { |s| s[:connection] } } it { is_expected.to eq(user_cluster_shards) } end From 47d6ffb770580719c5407415b5aab93339fdfc29 Mon Sep 17 00:00:00 2001 From: gussan Date: Fri, 22 Apr 2016 15:07:14 +0900 Subject: [PATCH 005/125] Drop support rails versions earlier than 4.2 --- .travis.yml | 5 - activerecord-turntable.gemspec | 4 +- gemfiles/rails4_0.gemfile | 7 - gemfiles/rails4_1.gemfile | 7 - .../activerecord_import_ext.rb | 4 +- .../active_record_ext/association.rb | 120 ++++------- .../active_record_ext/clever_load.rb | 2 +- .../turntable/active_record_ext/fixtures.rb | 42 +--- .../active_record_ext/locking_optimistic.rb | 187 ++++------------- .../active_record_ext/persistence.rb | 193 +++++------------- .../turntable/active_record_ext/relation.rb | 57 ++---- .../active_record_ext/transactions.rb | 6 +- lib/active_record/turntable/util.rb | 20 -- 13 files changed, 162 insertions(+), 492 deletions(-) delete mode 100644 gemfiles/rails4_0.gemfile delete mode 100644 gemfiles/rails4_1.gemfile diff --git a/.travis.yml b/.travis.yml index f0c22056..1228b038 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,9 @@ language: ruby rvm: - - 1.9.3 - - 2.0.0 - - 2.1 - 2.2 - 2.3.0 - ruby-head gemfile: - - gemfiles/rails4_0.gemfile - - gemfiles/rails4_1.gemfile - gemfiles/rails4_2.gemfile before_script: - bundle exec rake turntable:db:reset diff --git a/activerecord-turntable.gemspec b/activerecord-turntable.gemspec index 6dc1e39c..6d430de0 100644 --- a/activerecord-turntable.gemspec +++ b/activerecord-turntable.gemspec @@ -23,8 +23,8 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] spec.required_ruby_version = ">= 2.2" - spec.add_runtime_dependency "activerecord", ">= 4.0.0", "< 5.0" - spec.add_runtime_dependency "activesupport", ">= 4.0.0", "< 5.0" + spec.add_runtime_dependency "activerecord", ">= 4.2.0", "< 5.0" + spec.add_runtime_dependency "activesupport", ">= 4.2.0", "< 5.0" spec.add_runtime_dependency "sql_tree", "= 0.2.0" spec.add_runtime_dependency "bsearch", "~> 1.5" spec.add_runtime_dependency "httpclient", ">= 0" diff --git a/gemfiles/rails4_0.gemfile b/gemfiles/rails4_0.gemfile deleted file mode 100644 index 63315513..00000000 --- a/gemfiles/rails4_0.gemfile +++ /dev/null @@ -1,7 +0,0 @@ -source "https://rubygems.org" - -gem "activerecord", "~> 4.0.0" -gem "activesupport", "~> 4.0.0" -gem "mysql2", "~> 0.3.20" - -gemspec :path => "../" diff --git a/gemfiles/rails4_1.gemfile b/gemfiles/rails4_1.gemfile deleted file mode 100644 index 41543316..00000000 --- a/gemfiles/rails4_1.gemfile +++ /dev/null @@ -1,7 +0,0 @@ -source "https://rubygems.org" - -gem "activerecord", "~> 4.1.0" -gem "activesupport", "~> 4.1.0" -gem "mysql2", "~> 0.3.20" - -gemspec :path => "../" diff --git a/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb b/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb index 2bc6fae9..80f66e42 100644 --- a/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb +++ b/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb @@ -28,10 +28,8 @@ def values_sql_for_columns_and_attributes_with_turntable(columns, array_of_attri elsif column if respond_to?(:type_caster) && type_caster.respond_to?(:type_cast_for_database) # Rails 5.0 and higher connection_memo.quote(type_caster.type_cast_for_database(column.name, val)) - elsif column.respond_to?(:type_cast_from_user) # Rails 4.2 and higher + else # Rails 4.2 and higher connection_memo.quote(column.type_cast_from_user(val), column) - else # Rails 3.1, 3.2, and 4.1 - connection_memo.quote(column.type_cast(val), column) end end end diff --git a/lib/active_record/turntable/active_record_ext/association.rb b/lib/active_record/turntable/active_record_ext/association.rb index 8f4b80f6..909bf5ee 100644 --- a/lib/active_record/turntable/active_record_ext/association.rb +++ b/lib/active_record/turntable/active_record_ext/association.rb @@ -24,46 +24,30 @@ module SingularAssociationExt extend ActiveSupport::Concern included do - if Util.ar42_or_later? - alias_method_chain :get_records, :turntable - else - alias_method_chain :find_target, :turntable - end + alias_method_chain :get_records, :turntable end # @note Override to add sharding condition for singular association - if Util.ar42_or_later? - def get_records_with_turntable - if reflection.scope_chain.any?(&:any?) || - scope.eager_loading? || - klass.current_scope || - klass.default_scopes.any? || - should_use_shard_key? # OPTIMIZE: Use bind values if cachable scope - - return turntable_scope(scope).limit(1).to_a - end - - conn = klass.connection - sc = reflection.association_scope_cache(conn, owner) do - ActiveRecord::StatementCache.create(conn) { |params| - as = ActiveRecord::Associations::AssociationScope.create { params.bind } - target_scope.merge(as.scope(self, conn)).limit(1) - } - end - - binds = ActiveRecord::Associations::AssociationScope.get_bind_values(owner, reflection.chain) - sc.execute binds, klass, klass.connection - end - elsif Util.ar41_or_later? - def find_target_with_turntable - if record = turntable_scope(scope).take - set_inverse_instance record - end + def get_records_with_turntable + if reflection.scope_chain.any?(&:any?) || + scope.eager_loading? || + klass.current_scope || + klass.default_scopes.any? || + should_use_shard_key? # OPTIMIZE: Use bind values if cachable scope + + return turntable_scope(scope).limit(1).to_a end - else - def find_target_with_turntable - turntable_scope(scope).take.tap { |record| set_inverse_instance(record) } + + conn = klass.connection + sc = reflection.association_scope_cache(conn, owner) do + ActiveRecord::StatementCache.create(conn) { |params| + as = ActiveRecord::Associations::AssociationScope.create { params.bind } + target_scope.merge(as.scope(self, conn)).limit(1) + } end + + binds = ActiveRecord::Associations::AssociationScope.get_bind_values(owner, reflection.chain) + sc.execute binds, klass, klass.connection end end @@ -71,57 +55,35 @@ module CollectionAssociationExt extend ActiveSupport::Concern included do - if Util.ar42_or_later? - alias_method_chain :get_records, :turntable - else - alias_method_chain :find_target, :turntable - end + alias_method_chain :get_records, :turntable end private - if Util.ar42_or_later? - def get_records_with_turntable - if reflection.scope_chain.any?(&:any?) || - scope.eager_loading? || - klass.current_scope || - klass.default_scopes.any? || - should_use_shard_key? # OPTIMIZE: Use bind values if cachable scope - - return turntable_scope(scope).to_a - end - - conn = klass.connection - sc = reflection.association_scope_cache(conn, owner) do - ActiveRecord::StatementCache.create(conn) { |params| - as = ActiveRecord::Associations::AssociationScope.create { params.bind } - target_scope.merge as.scope(self, conn) - } - end - - binds = ActiveRecord::Associations::AssociationScope.get_bind_values(owner, reflection.chain) - sc.execute binds, klass, klass.connection - end - else - # @note Override to add sharding condition for collection association - def find_target_with_turntable - records = - if options[:finder_sql] - reflection.klass.find_by_sql(custom_finder_sql) - else - current_scope = scope - if should_use_shard_key? - current_scope = current_scope.where(klass.turntable_shard_key => owner.send(foreign_shard_key)) - end - current_scope.to_a - end - records.each { |record| set_inverse_instance(record) } - records - end + def get_records_with_turntable + if reflection.scope_chain.any?(&:any?) || + scope.eager_loading? || + klass.current_scope || + klass.default_scopes.any? || + should_use_shard_key? # OPTIMIZE: Use bind values if cachable scope + + return turntable_scope(scope).to_a end + + conn = klass.connection + sc = reflection.association_scope_cache(conn, owner) do + ActiveRecord::StatementCache.create(conn) { |params| + as = ActiveRecord::Associations::AssociationScope.create { params.bind } + target_scope.merge as.scope(self, conn) + } + end + + binds = ActiveRecord::Associations::AssociationScope.get_bind_values(owner, reflection.chain) + sc.execute binds, klass, klass.connection + end end - private + private def foreign_shard_key options[:foreign_shard_key] || owner.turntable_shard_key diff --git a/lib/active_record/turntable/active_record_ext/clever_load.rb b/lib/active_record/turntable/active_record_ext/clever_load.rb index 6abaa5fa..21abd63a 100644 --- a/lib/active_record/turntable/active_record_ext/clever_load.rb +++ b/lib/active_record/turntable/active_record_ext/clever_load.rb @@ -13,7 +13,7 @@ def clever_load!(association_name) # load records records = self.to_a klass = records.first.class - association_key = Util.ar42_or_later? ? association_name.to_s : association_name + association_key = association_name.to_s reflection = klass.reflections[association_key] if reflection diff --git a/lib/active_record/turntable/active_record_ext/fixtures.rb b/lib/active_record/turntable/active_record_ext/fixtures.rb index c934602d..dc47a28b 100644 --- a/lib/active_record/turntable/active_record_ext/fixtures.rb +++ b/lib/active_record/turntable/active_record_ext/fixtures.rb @@ -9,11 +9,7 @@ class FixtureSet def self.create_fixtures(fixtures_directory, fixture_set_names, class_names = {}, config = ActiveRecord::Base) fixture_set_names = Array(fixture_set_names).map(&:to_s) - class_names = if ar41_or_later? - ClassCache.new class_names, config - else - class_names = class_names.stringify_keys - end + class_names = ClassCache.new class_names, config # FIXME: Apparently JK uses this. connection = block_given? ? yield : ActiveRecord::Base.connection @@ -27,11 +23,7 @@ def self.create_fixtures(fixtures_directory, fixture_set_names, class_names = {} fixtures_map = {} fixture_sets = files_to_read.map do |fs_name| - klass = if ar41_or_later? - class_names[fs_name] - else - class_names[fs_name] || default_fixture_model_name(fs_name) - end + klass = class_names[fs_name] conn = klass.is_a?(String) ? connection : klass.connection fixtures_map[fs_name] = new( # ActiveRecord::FixtureSet.new conn, @@ -40,11 +32,7 @@ def self.create_fixtures(fixtures_directory, fixture_set_names, class_names = {} ::File.join(fixtures_directory, fs_name)) end - if ar42_or_later? - update_all_loaded_fixtures fixtures_map - else - all_loaded_fixtures.update(fixtures_map) - end + update_all_loaded_fixtures fixtures_map ActiveRecord::Base.force_transaction_all_shards!(requires_new: true) do fixture_sets.each do |fs| @@ -96,7 +84,7 @@ def setup_fixtures(config = ActiveRecord::Base) if @@already_loaded_fixtures[self.class] @loaded_fixtures = @@already_loaded_fixtures[self.class] else - @loaded_fixtures = turntable_load_fixtures(config) + @loaded_fixtures = load_fixtures(config) @@already_loaded_fixtures[self.class] = @loaded_fixtures end ActiveRecord::Base.force_connect_all_shards! @@ -108,34 +96,16 @@ def setup_fixtures(config = ActiveRecord::Base) else ActiveRecord::Fixtures.reset_cache @@already_loaded_fixtures[self.class] = nil - @loaded_fixtures = turntable_load_fixtures(config) + @loaded_fixtures = load_fixtures(config) end # Instantiate fixtures for every test if requested. - turntable_instantiate_fixtures(config) if use_instantiated_fixtures + instantiate_fixtures(config) if use_instantiated_fixtures end def enlist_fixture_connections ActiveRecord::Base.connection_handler.connection_pool_list.map(&:connection) + ActiveRecord::Base.turntable_connections.values.map(&:connection) end - - private - - def turntable_load_fixtures(config) - if ar41_or_later? - load_fixtures(config) - else - load_fixtures - end - end - - def turntable_instantiate_fixtures(config) - if ar41_or_later? - instantiate_fixtures(config) - else - instantiate_fixtures - end - end end end diff --git a/lib/active_record/turntable/active_record_ext/locking_optimistic.rb b/lib/active_record/turntable/active_record_ext/locking_optimistic.rb index 0856eba1..ea4aa14e 100644 --- a/lib/active_record/turntable/active_record_ext/locking_optimistic.rb +++ b/lib/active_record/turntable/active_record_ext/locking_optimistic.rb @@ -1,160 +1,57 @@ module ActiveRecord::Turntable module ActiveRecordExt module LockingOptimistic - # @note Override to add sharding condition on optimistic locking - ::ActiveRecord::Locking::Optimistic.class_eval do - ar_version = ActiveRecord::VERSION::STRING - if Util.earlier_than_ar41? - method_name = Util.ar_version_earlier_than?("4.0.6") ? "update_record" : "_update_record" - - class_eval <<-EOD - def #{method_name}(attribute_names = @attributes.keys) #:nodoc: - return super unless locking_enabled? - return 0 if attribute_names.empty? - - klass = self.class - lock_col = self.class.locking_column - previous_lock_value = send(lock_col).to_i - increment_lock - - attribute_names += [lock_col] - attribute_names.uniq! - - begin - relation = self.class.unscoped - - condition_scope = relation.where( - relation.table[self.class.primary_key].eq(id).and( - relation.table[lock_col].eq(self.class.quote_value(previous_lock_value, column_for_attribute(lock_col))) - ) + ::ActiveRecord::Locking::Optimistic.class_eval <<-EOD + private + # @note Override to add sharding condition on optimistic locking + def _update_record(attribute_names = self.attribute_names) #:nodoc: + return super unless locking_enabled? + return 0 if attribute_names.empty? + + klass = self.class + lock_col = self.class.locking_column + previous_lock_value = send(lock_col).to_i + increment_lock + + attribute_names += [lock_col] + attribute_names.uniq! + + begin + relation = self.class.unscoped + + condition_scope = relation.where( + relation.table[self.class.primary_key].eq(id).and( + relation.table[lock_col].eq(self.class.quote_value(previous_lock_value, column_for_attribute(lock_col))) + ) + ) + if klass.turntable_enabled? and klass.primary_key != klass.turntable_shard_key.to_s + condition_scope = condition_scope.where( + relation.table[klass.turntable_shard_key].eq( + self.class.quote_value(self.send(turntable_shard_key), column_for_attribute(klass.turntable_shard_key)) ) - if klass.turntable_enabled? and klass.primary_key != klass.turntable_shard_key.to_s - condition_scope = condition_scope.where( - relation.table[klass.turntable_shard_key].eq( - self.class.quote_value(self.send(turntable_shard_key), column_for_attribute(klass.turntable_shard_key)) - ) - ) - end - stmt = condition_scope.arel.compile_update(arel_attributes_with_values_for_update(attribute_names)) - - affected_rows = self.class.connection.update stmt - - unless affected_rows == 1 - raise ActiveRecord::StaleObjectError.new(self, "update") - end - - affected_rows - - # If something went wrong, revert the version. - rescue Exception - send(lock_col + '=', previous_lock_value) - raise - end + ) end - EOD - elsif Util.earlier_than_ar42? - method_name = Util.ar_version_earlier_than?("4.1.2") ? "update_record" : "_update_record" - - class_eval <<-EOD - def _update_record(attribute_names = @attributes.keys) #:nodoc: - return super unless locking_enabled? - return 0 if attribute_names.empty? - - klass = self.class - lock_col = self.class.locking_column - previous_lock_value = send(lock_col).to_i - increment_lock - - attribute_names += [lock_col] - attribute_names.uniq! - - begin - relation = self.class.unscoped - condition_scope = relation.where( - relation.table[self.class.primary_key].eq(id).and( - relation.table[lock_col].eq(self.class.quote_value(previous_lock_value, column_for_attribute(lock_col))) - ) - ) - if klass.turntable_enabled? and klass.primary_key != klass.turntable_shard_key.to_s - condition_scope = condition_scope.where( - relation.table[klass.turntable_shard_key].eq( - self.class.quote_value(self.send(turntable_shard_key), column_for_attribute(klass.turntable_shard_key)) - ) - ) - end - stmt = condition_scope.arel.compile_update( - arel_attributes_with_values_for_update(attribute_names), - self.class.primary_key - ) - - affected_rows = self.class.connection.update stmt + stmt = condition_scope.arel.compile_update( + arel_attributes_with_values_for_update(attribute_names), + self.class.primary_key + ) - unless affected_rows == 1 - raise ActiveRecord::StaleObjectError.new(self, "update") - end + affected_rows = self.class.connection.update stmt - affected_rows - - # If something went wrong, revert the version. - rescue Exception - send(lock_col + '=', previous_lock_value) - raise - end + unless affected_rows == 1 + raise ActiveRecord::StaleObjectError.new(self, "update") end - EOD - else - class_eval <<-EOD - def _update_record(attribute_names = self.attribute_names) #:nodoc: - return super unless locking_enabled? - return 0 if attribute_names.empty? - - klass = self.class - lock_col = self.class.locking_column - previous_lock_value = send(lock_col).to_i - increment_lock - attribute_names += [lock_col] - attribute_names.uniq! - - begin - relation = self.class.unscoped - - condition_scope = relation.where( - relation.table[self.class.primary_key].eq(id).and( - relation.table[lock_col].eq(self.class.quote_value(previous_lock_value, column_for_attribute(lock_col))) - ) - ) - if klass.turntable_enabled? and klass.primary_key != klass.turntable_shard_key.to_s - condition_scope = condition_scope.where( - relation.table[klass.turntable_shard_key].eq( - self.class.quote_value(self.send(turntable_shard_key), column_for_attribute(klass.turntable_shard_key)) - ) - ) - end + affected_rows - stmt = condition_scope.arel.compile_update( - arel_attributes_with_values_for_update(attribute_names), - self.class.primary_key - ) - - affected_rows = self.class.connection.update stmt - - unless affected_rows == 1 - raise ActiveRecord::StaleObjectError.new(self, "update") - end - - affected_rows - - # If something went wrong, revert the version. - rescue Exception - send(lock_col + '=', previous_lock_value) - raise - end - end - EOD + # If something went wrong, revert the version. + rescue Exception + send(lock_col + '=', previous_lock_value) + raise + end end - end + EOD end end end diff --git a/lib/active_record/turntable/active_record_ext/persistence.rb b/lib/active_record/turntable/active_record_ext/persistence.rb index 12b0c258..45866e29 100644 --- a/lib/active_record/turntable/active_record_ext/persistence.rb +++ b/lib/active_record/turntable/active_record_ext/persistence.rb @@ -22,83 +22,41 @@ def reload(options = nil) finder_scope.find(id) end - if Util.ar42_or_later? - @attributes = fresh_object.instance_variable_get("@attributes") - else - @attributes.update(fresh_object.instance_variable_get("@attributes")) - - @column_types = self.class.column_types - @column_types_override = fresh_object.instance_variable_get("@column_types_override") - @attributes_cache = {} - end + @attributes = fresh_object.instance_variable_get("@attributes") @new_record = false self end # @note Override to add sharding scope on `touch` - if Util.ar42_or_later? - def touch(*names) - raise ActiveRecordError, "cannot touch on a new record object" unless persisted? - - attributes = timestamp_attributes_for_update_in_model - attributes.concat(names) - - unless attributes.empty? - current_time = current_time_from_proper_timezone - changes = {} - - attributes.each do |column| - column = column.to_s - changes[column] = write_attribute(column, current_time) - end + def touch(*names) + raise ActiveRecordError, "cannot touch on a new record object" unless persisted? - changes[self.class.locking_column] = increment_lock if locking_enabled? + attributes = timestamp_attributes_for_update_in_model + attributes.concat(names) - clear_attribute_changes(changes.keys) - primary_key = self.class.primary_key + unless attributes.empty? + current_time = current_time_from_proper_timezone + changes = {} - finder_scope = if turntable_enabled? && primary_key != self.class.turntable_shard_key.to_s - self.class.unscoped.where(self.class.turntable_shard_key => self.send(turntable_shard_key)) - else - self.class.unscoped - end - - finder_scope.where(primary_key => self[primary_key]).update_all(changes) == 1 - else - true + attributes.each do |column| + column = column.to_s + changes[column] = write_attribute(column, current_time) end - end - else - def touch(name = nil) - raise ActiveRecordError, "can not touch on a new record object" unless persisted? - - attributes = timestamp_attributes_for_update_in_model - attributes << name if name - - unless attributes.empty? - current_time = current_time_from_proper_timezone - changes = {} - attributes.each do |column| - column = column.to_s - changes[column] = write_attribute(column, current_time) - end + changes[self.class.locking_column] = increment_lock if locking_enabled? - changes[self.class.locking_column] = increment_lock if locking_enabled? + clear_attribute_changes(changes.keys) + primary_key = self.class.primary_key - @changed_attributes.except!(*changes.keys) - primary_key = self.class.primary_key + finder_scope = if turntable_enabled? && primary_key != self.class.turntable_shard_key.to_s + self.class.unscoped.where(self.class.turntable_shard_key => self.send(turntable_shard_key)) + else + self.class.unscoped + end - finder_scope = if turntable_enabled? && primary_key != self.class.turntable_shard_key.to_s - self.class.unscoped.where(self.class.turntable_shard_key => self.send(turntable_shard_key)) - else - self.class.unscoped - end - - finder_scope.where(primary_key => self[primary_key]).update_all(changes) == 1 - else - true - end + finder_scope.where(primary_key => self[primary_key]).update_all(changes) == 1 + else + true end end @@ -129,89 +87,38 @@ def update_columns(attributes) private # @note Override to add sharding scope on destroying - if Util.ar42_or_later? - def relation_for_destroy - pk = self.class.primary_key - column = self.class.columns_hash[pk] - substitute = self.class.connection.substitute_at(column, 0) - klass = self.class - - relation = self.class.unscoped.where( - self.class.arel_table[pk].eq(substitute)) - relation.bind_values = [[column, id]] - - if klass.turntable_enabled? && klass.primary_key != klass.turntable_shard_key.to_s - shard_key_column = klass.columns_hash[klass.turntable_shard_key] - shard_key_substitute = klass.connection.substitute_at(shard_key_column) - - relation = relation.where(self.class.arel_table[klass.turntable_shard_key].eq(shard_key_substitute)) - relation.bind_values << [shard_key_column, self[klass.turntable_shard_key]] - end - relation - end - else - def relation_for_destroy - pk = self.class.primary_key - column = self.class.columns_hash[pk] - substitute = self.class.connection.substitute_at(column, 0) - klass = self.class - - relation = self.class.unscoped.where( - self.class.arel_table[pk].eq(substitute)) - if klass.turntable_enabled? && klass.primary_key != klass.turntable_shard_key.to_s - relation = relation.where(klass.turntable_shard_key => self.send(turntable_shard_key)) - end - relation.bind_values = [[column, id]] - relation + def relation_for_destroy + pk = self.class.primary_key + column = self.class.columns_hash[pk] + substitute = self.class.connection.substitute_at(column, 0) + klass = self.class + + relation = self.class.unscoped.where( + self.class.arel_table[pk].eq(substitute)) + relation.bind_values = [[column, id]] + + if klass.turntable_enabled? && klass.primary_key != klass.turntable_shard_key.to_s + shard_key_column = klass.columns_hash[klass.turntable_shard_key] + shard_key_substitute = klass.connection.substitute_at(shard_key_column) + + relation = relation.where(self.class.arel_table[klass.turntable_shard_key].eq(shard_key_substitute)) + relation.bind_values << [shard_key_column, self[klass.turntable_shard_key]] end + relation end # @note Override to add sharding scope on updating - if Util.earlier_than_ar41? - method_name = Util.ar_version_earlier_than?("4.0.6") ? "update_record" : "_update_record" - class_eval <<-EOD - def #{method_name}(attribute_names = @attributes.keys) - attributes_with_values = arel_attributes_with_values_for_update(attribute_names) - if attributes_with_values.empty? - 0 - else - klass = self.class - column_hash = klass.connection.schema_cache.columns_hash klass.table_name - db_columns_with_values = attributes_with_values.map { |attr,value| - real_column = column_hash[attr.name] - [real_column, value] - } - bind_attrs = attributes_with_values.dup - bind_attrs.keys.each_with_index do |column, i| - real_column = db_columns_with_values[i].first - bind_attrs[column] = klass.connection.substitute_at(real_column, i) - end - condition_scope = klass.unscoped.where(klass.arel_table[klass.primary_key].eq(id_was || id)) - if klass.turntable_enabled? and klass.primary_key != klass.turntable_shard_key.to_s - condition_scope = condition_scope.where(klass.turntable_shard_key => self.send(turntable_shard_key)) - end - stmt = condition_scope.arel.compile_update(bind_attrs) - klass.connection.update stmt, 'SQL', db_columns_with_values - end - end - EOD - else - method_name = Util.ar_version_earlier_than?("4.1.2") ? "update_record" : "_update_record" - attributes_method_name = Util.ar42_or_later? ? "self.attribute_names" : "@attributes.keys" - class_eval <<-EOD - def #{method_name}(attribute_names = #{attributes_method_name}) - klass = self.class - attributes_values = arel_attributes_with_values_for_update(attribute_names) - if attributes_values.empty? - 0 - else - scope = if klass.turntable_enabled? and klass.primary_key != klass.turntable_shard_key.to_s - klass.unscoped.where(klass.turntable_shard_key => self.send(turntable_shard_key)) - end - klass.unscoped.#{method_name} attributes_values, id, id_was, scope - end - end - EOD + def _update_record(attribute_names = self.attribute_names) + klass = self.class + attributes_values = arel_attributes_with_values_for_update(attribute_names) + if attributes_values.empty? + 0 + else + scope = if klass.turntable_enabled? and klass.primary_key != klass.turntable_shard_key.to_s + klass.unscoped.where(klass.turntable_shard_key => self.send(turntable_shard_key)) + end + klass.unscoped._update_record attributes_values, id, id_was, scope + end end end end diff --git a/lib/active_record/turntable/active_record_ext/relation.rb b/lib/active_record/turntable/active_record_ext/relation.rb index 67c7738d..238cf6f8 100644 --- a/lib/active_record/turntable/active_record_ext/relation.rb +++ b/lib/active_record/turntable/active_record_ext/relation.rb @@ -4,53 +4,32 @@ module Relation extend ActiveSupport::Concern included do - if Util.ar41_or_later? - if Util.ar_version_earlier_than?("4.1.2") - alias_method :_update_record_without_turntable, :update_record - alias_method :update_record, :_update_record_with_turntable - else - alias_method_chain :_update_record, :turntable - end - end + alias_method_chain :_update_record, :turntable end # @note Override to add sharding scope on updating - if Util.ar42_or_later? - def _update_record_with_turntable(values, id, id_was, turntable_scope = nil) # :nodoc: - substitutes, binds = substitute_values values + def _update_record_with_turntable(values, id, id_was, turntable_scope = nil) # :nodoc: + substitutes, binds = substitute_values values - scope = @klass.unscoped + scope = @klass.unscoped - if @klass.finder_needs_type_condition? - scope.unscope!(where: @klass.inheritance_column) - end + if @klass.finder_needs_type_condition? + scope.unscope!(where: @klass.inheritance_column) + end - relation = scope.where(@klass.primary_key => (id_was || id)) - relation = relation.merge(turntable_scope) if turntable_scope + relation = scope.where(@klass.primary_key => (id_was || id)) + relation = relation.merge(turntable_scope) if turntable_scope - bvs = binds + relation.bind_values - um = relation. - arel. - compile_update(substitutes, @klass.primary_key) + bvs = binds + relation.bind_values + um = relation. + arel. + compile_update(substitutes, @klass.primary_key) - @klass.connection.update( - um, - "SQL", - bvs - ) - end - else - def _update_record_with_turntable(values, id, id_was, turntable_scope = nil) # :nodoc: - substitutes, binds = substitute_values values - condition_scope = @klass.unscoped.where(@klass.arel_table[@klass.primary_key].eq(id_was || id)) - condition_scope = condition_scope.merge(turntable_scope) if turntable_scope - um = condition_scope.arel.compile_update(substitutes, @klass.primary_key) - - @klass.connection.update( - um, - "SQL", - binds) - end + @klass.connection.update( + um, + "SQL", + bvs + ) end end end diff --git a/lib/active_record/turntable/active_record_ext/transactions.rb b/lib/active_record/turntable/active_record_ext/transactions.rb index ee5d8da7..668a5d6d 100644 --- a/lib/active_record/turntable/active_record_ext/transactions.rb +++ b/lib/active_record/turntable/active_record_ext/transactions.rb @@ -14,11 +14,7 @@ def with_transaction_returning_status begin status = yield rescue ActiveRecord::Rollback - if Util.ar42_or_later? - clear_transaction_record_state - else - @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1 - end + clear_transaction_record_state status = nil end diff --git a/lib/active_record/turntable/util.rb b/lib/active_record/turntable/util.rb index cda3f476..a88e786b 100644 --- a/lib/active_record/turntable/util.rb +++ b/lib/active_record/turntable/util.rb @@ -10,26 +10,6 @@ def ar_version_earlier_than?(version) ar_version < Gem::Version.new(version) end - def ar4? - ActiveRecord::VERSION::MAJOR == 4 - end - - def ar41_or_later? - ar_version_equals_or_later?("4.1") - end - - def earlier_than_ar41? - ar_version_earlier_than?("4.1") - end - - def ar42_or_later? - ar_version_equals_or_later?("4.2") - end - - def earlier_than_ar42? - ar_version_earlier_than?("4.2") - end - def ar_version ActiveRecord.gem_version end From 3d2ab495225504fd62255fe3139d4ff00c422cc0 Mon Sep 17 00:00:00 2001 From: gussan Date: Fri, 22 Apr 2016 15:40:12 +0900 Subject: [PATCH 006/125] Remove unused ActiveRecordConnectionMethods module --- lib/active_record/turntable/pool_proxy.rb | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/lib/active_record/turntable/pool_proxy.rb b/lib/active_record/turntable/pool_proxy.rb index c3d95719..5061cbfe 100644 --- a/lib/active_record/turntable/pool_proxy.rb +++ b/lib/active_record/turntable/pool_proxy.rb @@ -1,14 +1,4 @@ module ActiveRecord::Turntable - module ActiveRecordConnectionMethods - def self.included(base) - base.alias_method_chain :reload, :master - end - - def reload_with_master(*args, &block) - connection.with_master { reload_without_master } - end - end - class PoolProxy def initialize(proxy) @proxy = proxy From 095f21da3ad1662ec9890ee5c48686116413b8d6 Mon Sep 17 00:00:00 2001 From: gussan Date: Fri, 22 Apr 2016 16:10:25 +0900 Subject: [PATCH 007/125] Remove 4.0.x patch --- lib/active_record/turntable.rb | 9 --------- 1 file changed, 9 deletions(-) diff --git a/lib/active_record/turntable.rb b/lib/active_record/turntable.rb index 12d0c78e..1e7a7dbf 100644 --- a/lib/active_record/turntable.rb +++ b/lib/active_record/turntable.rb @@ -12,15 +12,6 @@ require "logger" require "singleton" -# for 4.0.x series -module ActiveRecord - unless respond_to?(:gem_version) - class << self - alias_method :gem_version, :version - end - end -end - module ActiveRecord::Turntable extend ActiveSupport::Concern extend ActiveSupport::Autoload From 5edf42f9a1476f34b1956e4154739861e2b234d9 Mon Sep 17 00:00:00 2001 From: gussan Date: Fri, 22 Apr 2016 16:13:24 +0900 Subject: [PATCH 008/125] Use `Module#prepend` instead of `alias_method_chain` --- lib/active_record/turntable/active_record_ext.rb | 2 +- .../active_record_ext/association_preloader.rb | 10 ++-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/lib/active_record/turntable/active_record_ext.rb b/lib/active_record/turntable/active_record_ext.rb index 8c8c161f..db9d4b8c 100644 --- a/lib/active_record/turntable/active_record_ext.rb +++ b/lib/active_record/turntable/active_record_ext.rb @@ -30,7 +30,7 @@ module ActiveRecordExt ActiveRecord::ConnectionAdapters::ConnectionHandler.instance_exec do include ConnectionHandlerExtension end - ActiveRecord::Associations::Preloader::Association.send(:include, AssociationPreloader) + ActiveRecord::Associations::Preloader::Association.prepend(AssociationPreloader) ActiveRecord::Associations::Association.send(:include, Association) require "active_record/turntable/active_record_ext/fixtures" require "active_record/turntable/active_record_ext/migration_proxy" diff --git a/lib/active_record/turntable/active_record_ext/association_preloader.rb b/lib/active_record/turntable/active_record_ext/association_preloader.rb index 9f7e7f80..f5b5ad3d 100644 --- a/lib/active_record/turntable/active_record_ext/association_preloader.rb +++ b/lib/active_record/turntable/active_record_ext/association_preloader.rb @@ -3,15 +3,9 @@ module ActiveRecord::Turntable module ActiveRecordExt module AssociationPreloader - extend ActiveSupport::Concern - - included do - alias_method_chain :records_for, :turntable - end - # @note Override to add sharding condition on preload - def records_for_with_turntable(ids) - returning_scope = records_for_without_turntable(ids) + def records_for(ids) + returning_scope = super if should_use_shard_key? returning_scope = returning_scope.where(klass.turntable_shard_key => owners.map(&foreign_shard_key.to_sym).uniq) end From c00aab7b14f0383e3afefe966e1fdfddce488ca7 Mon Sep 17 00:00:00 2001 From: gussan Date: Fri, 22 Apr 2016 16:22:30 +0900 Subject: [PATCH 009/125] `Module#include` is a public method on ruby 2.1 or later --- Rakefile | 4 ++-- lib/active_record/turntable/active_record_ext.rb | 16 ++++++++-------- .../active_record_ext/activerecord_import_ext.rb | 2 +- .../turntable/active_record_ext/association.rb | 4 ++-- lib/active_record/turntable/migration.rb | 6 +++--- lib/active_record/turntable/railtie.rb | 2 +- .../turntable/railties/databases.rake | 2 +- spec/active_record/turntable_spec.rb | 4 ++-- spec/support/turntable_helper.rb | 2 +- 9 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Rakefile b/Rakefile index 9ab8a7bf..74eee64f 100644 --- a/Rakefile +++ b/Rakefile @@ -39,8 +39,8 @@ namespace :turntable do task :migrate => :load_config do ActiveRecord::Base.establish_connection RAILS_ENV.to_sym require "active_record/turntable" - ActiveRecord::Base.send(:include, ActiveRecord::Turntable) - ActiveRecord::ConnectionAdapters::SchemaStatements.send(:include, ActiveRecord::Turntable::Migration::SchemaStatementsExt) + ActiveRecord::Base.include(ActiveRecord::Turntable) + ActiveRecord::ConnectionAdapters::SchemaStatements.include(ActiveRecord::Turntable::Migration::SchemaStatementsExt) configurations = [ActiveRecord::Base.configurations[RAILS_ENV]] configurations += ActiveRecord::Tasks::DatabaseTasks.current_turntable_cluster_configurations(RAILS_ENV).map { |v| v[1] }.flatten.uniq diff --git a/lib/active_record/turntable/active_record_ext.rb b/lib/active_record/turntable/active_record_ext.rb index db9d4b8c..0d120ec4 100644 --- a/lib/active_record/turntable/active_record_ext.rb +++ b/lib/active_record/turntable/active_record_ext.rb @@ -20,18 +20,18 @@ module ActiveRecordExt included do include Transactions - ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:include, Sequencer) - ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:include, AbstractAdapter) - ActiveRecord::LogSubscriber.send(:include, LogSubscriber) - ActiveRecord::Persistence.send(:include, Persistence) - ActiveRecord::Locking::Optimistic.send(:include, LockingOptimistic) - ActiveRecord::Relation.send(:include, CleverLoad, Relation) - ActiveRecord::Migration.send(:include, ActiveRecord::Turntable::Migration) + ActiveRecord::ConnectionAdapters::AbstractAdapter.include(Sequencer) + ActiveRecord::ConnectionAdapters::AbstractAdapter.include(AbstractAdapter) + ActiveRecord::LogSubscriber.include(LogSubscriber) + ActiveRecord::Persistence.include(Persistence) + ActiveRecord::Locking::Optimistic.include(LockingOptimistic) + ActiveRecord::Relation.include(CleverLoad, Relation) + ActiveRecord::Migration.include(ActiveRecord::Turntable::Migration) ActiveRecord::ConnectionAdapters::ConnectionHandler.instance_exec do include ConnectionHandlerExtension end ActiveRecord::Associations::Preloader::Association.prepend(AssociationPreloader) - ActiveRecord::Associations::Association.send(:include, Association) + ActiveRecord::Associations::Association.include(Association) require "active_record/turntable/active_record_ext/fixtures" require "active_record/turntable/active_record_ext/migration_proxy" require "active_record/turntable/active_record_ext/activerecord_import_ext" diff --git a/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb b/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb index 80f66e42..74cbb7b6 100644 --- a/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb +++ b/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb @@ -41,7 +41,7 @@ def values_sql_for_columns_and_attributes_with_turntable(columns, array_of_attri begin require "activerecord-import" require "activerecord-import/base" - (class << ActiveRecord::Base; self; end).send(:include, ActiverecordImportExt) + (class << ActiveRecord::Base; self; end).include(ActiverecordImportExt) rescue LoadError end end diff --git a/lib/active_record/turntable/active_record_ext/association.rb b/lib/active_record/turntable/active_record_ext/association.rb index 909bf5ee..943bd708 100644 --- a/lib/active_record/turntable/active_record_ext/association.rb +++ b/lib/active_record/turntable/active_record_ext/association.rb @@ -6,8 +6,8 @@ module Association extend ActiveSupport::Concern included do - ActiveRecord::Associations::SingularAssociation.send(:include, SingularAssociationExt) - ActiveRecord::Associations::CollectionAssociation.send(:include, CollectionAssociationExt) + ActiveRecord::Associations::SingularAssociation.include(SingularAssociationExt) + ActiveRecord::Associations::CollectionAssociation.include(CollectionAssociationExt) ActiveRecord::Associations::Builder::Association.valid_options += [:foreign_shard_key] end diff --git a/lib/active_record/turntable/migration.rb b/lib/active_record/turntable/migration.rb index 15c40fb7..610a84fd 100644 --- a/lib/active_record/turntable/migration.rb +++ b/lib/active_record/turntable/migration.rb @@ -6,9 +6,9 @@ module ActiveRecord::Turntable::Migration class_attribute :target_shards, :current_shard alias_method_chain :announce, :turntable alias_method_chain :exec_migration, :turntable - ::ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:include, SchemaStatementsExt) - ::ActiveRecord::Migration::CommandRecorder.send(:include, CommandRecorder) - ::ActiveRecord::Migrator.send(:include, Migrator) + ::ActiveRecord::ConnectionAdapters::AbstractAdapter.include(SchemaStatementsExt) + ::ActiveRecord::Migration::CommandRecorder.include(CommandRecorder) + ::ActiveRecord::Migrator.include(Migrator) end module ShardDefinition diff --git a/lib/active_record/turntable/railtie.rb b/lib/active_record/turntable/railtie.rb index 6078bea0..b4ab3d01 100644 --- a/lib/active_record/turntable/railtie.rb +++ b/lib/active_record/turntable/railtie.rb @@ -8,7 +8,7 @@ class Railtie < Rails::Railtie # rails loading hook ActiveSupport.on_load(:before_initialize) do ActiveSupport.on_load(:active_record) do - ActiveRecord::Base.send(:include, ActiveRecord::Turntable) + ActiveRecord::Base.include(ActiveRecord::Turntable) end end diff --git a/lib/active_record/turntable/railties/databases.rake b/lib/active_record/turntable/railties/databases.rake index 6a05fbcd..8e79bbf6 100644 --- a/lib/active_record/turntable/railties/databases.rake +++ b/lib/active_record/turntable/railties/databases.rake @@ -1,5 +1,5 @@ require "active_record/turntable" -ActiveRecord::SchemaDumper.send(:include, ActiveRecord::Turntable::ActiveRecordExt::SchemaDumper) +ActiveRecord::SchemaDumper.include(ActiveRecord::Turntable::ActiveRecordExt::SchemaDumper) turntable_namespace = nil diff --git a/spec/active_record/turntable_spec.rb b/spec/active_record/turntable_spec.rb index ddd1dec0..ad53c60a 100644 --- a/spec/active_record/turntable_spec.rb +++ b/spec/active_record/turntable_spec.rb @@ -2,7 +2,7 @@ describe ActiveRecord::Turntable do before(:all) do - ActiveRecord::Base.send(:include, ActiveRecord::Turntable) + ActiveRecord::Base.include(ActiveRecord::Turntable) end context "#config_file" do @@ -16,7 +16,7 @@ context "#config_file=" do it "should set config_file" do - ActiveRecord::Base.send(:include, ActiveRecord::Turntable) + ActiveRecord::Base.include(ActiveRecord::Turntable) filename = "hogefuga" ActiveRecord::Base.turntable_config_file = filename expect(ActiveRecord::Base.turntable_config_file).to eq(filename) diff --git a/spec/support/turntable_helper.rb b/spec/support/turntable_helper.rb index 2b1e0ba5..d3a19a12 100644 --- a/spec/support/turntable_helper.rb +++ b/spec/support/turntable_helper.rb @@ -2,7 +2,7 @@ module TurntableHelper def reload_turntable!(config_file_name = nil) - ActiveRecord::Base.send(:include, ActiveRecord::Turntable) + ActiveRecord::Base.include(ActiveRecord::Turntable) ActiveRecord::Base.turntable_config_file = config_file_name ActiveRecord::Turntable::Config.load!(ActiveRecord::Base.turntable_config_file, :test) end From a41844db6be9c8d36d9787dcf43c6934b796d7bd Mon Sep 17 00:00:00 2001 From: gussan Date: Thu, 12 Feb 2015 16:31:41 +0900 Subject: [PATCH 010/125] Start developing v3.0 --- CHANGELOG.md | 2 ++ Gemfile | 4 ++++ activerecord-turntable.gemspec | 4 ++-- gemfiles/rails4_0.gemfile | 7 ------- gemfiles/rails4_1.gemfile | 7 ------- gemfiles/rails4_2.gemfile | 7 ------- gemfiles/rails5_0.gemfile | 7 +++++++ lib/active_record/turntable/version.rb | 2 +- 8 files changed, 16 insertions(+), 24 deletions(-) delete mode 100644 gemfiles/rails4_0.gemfile delete mode 100644 gemfiles/rails4_1.gemfile delete mode 100644 gemfiles/rails4_2.gemfile create mode 100644 gemfiles/rails5_0.gemfile diff --git a/CHANGELOG.md b/CHANGELOG.md index 4eb57b2c..f32c9450 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +## activerecord-turntable 3.0.0.alpha (unreleased) ## + ## activerecord-turntable 2.3.3 ## ### Bugfix diff --git a/Gemfile b/Gemfile index b4e2a20b..d7ee3f7c 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,7 @@ source "https://rubygems.org" gemspec + +gem "activerecord", "5.0.0.alpha", github: "rails/rails" +gem "activesupport", "5.0.0.alpha", github: "rails/rails" +gem "arel", '7.0.0.alpha', github: "rails/arel" diff --git a/activerecord-turntable.gemspec b/activerecord-turntable.gemspec index efe805c5..032f9dd0 100644 --- a/activerecord-turntable.gemspec +++ b/activerecord-turntable.gemspec @@ -23,8 +23,8 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] spec.required_ruby_version = '>= 1.9.3' - spec.add_runtime_dependency "activerecord", ">= 4.0.0", "< 5.0" - spec.add_runtime_dependency "activesupport", ">= 4.0.0", "< 5.0" + spec.add_runtime_dependency "activerecord", "= 5.0.0.alpha", "< 6.0" + spec.add_runtime_dependency "activesupport", "= 5.0.0.alpha", "< 6.0" spec.add_runtime_dependency "sql_tree", "= 0.2.0" spec.add_runtime_dependency "bsearch", "~> 1.5" spec.add_runtime_dependency "httpclient", ">= 0" diff --git a/gemfiles/rails4_0.gemfile b/gemfiles/rails4_0.gemfile deleted file mode 100644 index 63315513..00000000 --- a/gemfiles/rails4_0.gemfile +++ /dev/null @@ -1,7 +0,0 @@ -source "https://rubygems.org" - -gem "activerecord", "~> 4.0.0" -gem "activesupport", "~> 4.0.0" -gem "mysql2", "~> 0.3.20" - -gemspec :path => "../" diff --git a/gemfiles/rails4_1.gemfile b/gemfiles/rails4_1.gemfile deleted file mode 100644 index 41543316..00000000 --- a/gemfiles/rails4_1.gemfile +++ /dev/null @@ -1,7 +0,0 @@ -source "https://rubygems.org" - -gem "activerecord", "~> 4.1.0" -gem "activesupport", "~> 4.1.0" -gem "mysql2", "~> 0.3.20" - -gemspec :path => "../" diff --git a/gemfiles/rails4_2.gemfile b/gemfiles/rails4_2.gemfile deleted file mode 100644 index 27a5133d..00000000 --- a/gemfiles/rails4_2.gemfile +++ /dev/null @@ -1,7 +0,0 @@ -source "https://rubygems.org" - -gem "activerecord", "~> 4.2.0" -gem "activesupport", "~> 4.2.0" -gem "mysql2", "~> 0.3.20" - -gemspec :path => "../" diff --git a/gemfiles/rails5_0.gemfile b/gemfiles/rails5_0.gemfile new file mode 100644 index 00000000..3f05e4e4 --- /dev/null +++ b/gemfiles/rails5_0.gemfile @@ -0,0 +1,7 @@ +source "https://rubygems.org" + +gem "activerecord", "5.0.0.alpha", github: "rails/rails" +gem "activesupport", "5.0.0.alpha", github: "rails/rails" +gem "arel", '7.0.0.alpha', github: "rails/arel" + +gemspec :path => '../' diff --git a/lib/active_record/turntable/version.rb b/lib/active_record/turntable/version.rb index 18eef6df..bed436e3 100644 --- a/lib/active_record/turntable/version.rb +++ b/lib/active_record/turntable/version.rb @@ -1,5 +1,5 @@ module ActiveRecord module Turntable - VERSION = "2.3.3" + VERSION = "3.0.0.alpha" end end From 1a673a7c9b204b86594724c45f9b67b3df2e3875 Mon Sep 17 00:00:00 2001 From: gussan Date: Thu, 12 Feb 2015 18:29:06 +0900 Subject: [PATCH 011/125] Update travis.yml --- .travis.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index f0c22056..3e678094 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,10 @@ language: ruby rvm: - - 1.9.3 - - 2.0.0 - - 2.1 - 2.2 - 2.3.0 - ruby-head gemfile: - - gemfiles/rails4_0.gemfile - - gemfiles/rails4_1.gemfile - - gemfiles/rails4_2.gemfile + - gemfiles/rails5_0.gemfile before_script: - bundle exec rake turntable:db:reset script: bundle exec rake spec From e5c3adaeec5129b206a09a871b930a15a25427da Mon Sep 17 00:00:00 2001 From: gussan Date: Fri, 22 Apr 2016 17:04:23 +0900 Subject: [PATCH 012/125] Refactor Association extensions --- lib/active_record/turntable.rb | 1 + .../active_record_ext/association.rb | 82 +++---------------- .../association_preloader.rb | 18 +--- .../turntable/sharding_condition.rb | 23 ++++++ 4 files changed, 36 insertions(+), 88 deletions(-) create mode 100644 lib/active_record/turntable/sharding_condition.rb diff --git a/lib/active_record/turntable.rb b/lib/active_record/turntable.rb index 1e7a7dbf..263aef05 100644 --- a/lib/active_record/turntable.rb +++ b/lib/active_record/turntable.rb @@ -29,6 +29,7 @@ module ActiveRecord::Turntable autoload :Mixer autoload :PoolProxy autoload :Shard + autoload :ShardingCondition autoload :SeqShard autoload :Sequencer end diff --git a/lib/active_record/turntable/active_record_ext/association.rb b/lib/active_record/turntable/active_record_ext/association.rb index 943bd708..b4ff8b74 100644 --- a/lib/active_record/turntable/active_record_ext/association.rb +++ b/lib/active_record/turntable/active_record_ext/association.rb @@ -4,10 +4,11 @@ module ActiveRecord::Turntable module ActiveRecordExt module Association extend ActiveSupport::Concern + include ShardingCondition included do - ActiveRecord::Associations::SingularAssociation.include(SingularAssociationExt) - ActiveRecord::Associations::CollectionAssociation.include(CollectionAssociationExt) + ActiveRecord::Associations::SingularAssociation.prepend(AssociationExt) + ActiveRecord::Associations::CollectionAssociation.prepend(AssociationExt) ActiveRecord::Associations::Builder::Association.valid_options += [:foreign_shard_key] end @@ -20,82 +21,19 @@ def turntable_scope(scope, bind = nil) scope end - module SingularAssociationExt - extend ActiveSupport::Concern - - included do - alias_method_chain :get_records, :turntable - end - - # @note Override to add sharding condition for singular association - def get_records_with_turntable - if reflection.scope_chain.any?(&:any?) || - scope.eager_loading? || - klass.current_scope || - klass.default_scopes.any? || - should_use_shard_key? # OPTIMIZE: Use bind values if cachable scope - - return turntable_scope(scope).limit(1).to_a - end - - conn = klass.connection - sc = reflection.association_scope_cache(conn, owner) do - ActiveRecord::StatementCache.create(conn) { |params| - as = ActiveRecord::Associations::AssociationScope.create { params.bind } - target_scope.merge(as.scope(self, conn)).limit(1) - } - end - - binds = ActiveRecord::Associations::AssociationScope.get_bind_values(owner, reflection.chain) - sc.execute binds, klass, klass.connection - end - end - - module CollectionAssociationExt - extend ActiveSupport::Concern - - included do - alias_method_chain :get_records, :turntable - end - + module AssociationExt private - def get_records_with_turntable - if reflection.scope_chain.any?(&:any?) || - scope.eager_loading? || - klass.current_scope || - klass.default_scopes.any? || - should_use_shard_key? # OPTIMIZE: Use bind values if cachable scope - - return turntable_scope(scope).to_a - end - - conn = klass.connection - sc = reflection.association_scope_cache(conn, owner) do - ActiveRecord::StatementCache.create(conn) { |params| - as = ActiveRecord::Associations::AssociationScope.create { params.bind } - target_scope.merge as.scope(self, conn) - } + # @note Inject to add sharding condition for association + def get_records + # OPTIMIZE: Use bind values if cachable scope + if should_use_shard_key? + return turntable_scope(scope).limit(1).to_a end - binds = ActiveRecord::Associations::AssociationScope.get_bind_values(owner, reflection.chain) - sc.execute binds, klass, klass.connection + super end end - - private - - def foreign_shard_key - options[:foreign_shard_key] || owner.turntable_shard_key - end - - def should_use_shard_key? - same_association_shard_key? || !!options[:foreign_shard_key] - end - - def same_association_shard_key? - owner.class.turntable_enabled? && klass.turntable_enabled? && foreign_shard_key == klass.turntable_shard_key - end end end end diff --git a/lib/active_record/turntable/active_record_ext/association_preloader.rb b/lib/active_record/turntable/active_record_ext/association_preloader.rb index f5b5ad3d..b23fd6f3 100644 --- a/lib/active_record/turntable/active_record_ext/association_preloader.rb +++ b/lib/active_record/turntable/active_record_ext/association_preloader.rb @@ -3,6 +3,8 @@ module ActiveRecord::Turntable module ActiveRecordExt module AssociationPreloader + include ShardingCondition + # @note Override to add sharding condition on preload def records_for(ids) returning_scope = super @@ -11,22 +13,6 @@ def records_for(ids) end returning_scope end - - private - - def foreign_shard_key - options[:foreign_shard_key] || model.turntable_shard_key - end - - def should_use_shard_key? - sharded_by_same_key? || !!options[:foreign_shard_key] - end - - def sharded_by_same_key? - model.turntable_enabled? && - klass.turntable_enabled? && - model.turntable_shard_key == klass.turntable_shard_key - end end end end diff --git a/lib/active_record/turntable/sharding_condition.rb b/lib/active_record/turntable/sharding_condition.rb new file mode 100644 index 00000000..31c9cb11 --- /dev/null +++ b/lib/active_record/turntable/sharding_condition.rb @@ -0,0 +1,23 @@ +module ActiveRecord::Turntable + module ShardingCondition + private + + def foreign_shard_key + options[:foreign_shard_key] || foreign_target_model.turntable_shard_key + end + + def foreign_target_model + respond_to?(:model) ? model : owner + end + + def should_use_shard_key? + sharded_by_same_key? || !!options[:foreign_shard_key] + end + + def sharded_by_same_key? + foreign_target_model.turntable_enabled? && + klass.turntable_enabled? && + foreign_shard_key == klass.turntable_shard_key + end + end +end From f65e6a4280070dee0c2ce87430ceba32183c5c0a Mon Sep 17 00:00:00 2001 From: gussan Date: Fri, 22 Apr 2016 17:22:40 +0900 Subject: [PATCH 013/125] Use Module#prepend on AR::Relation extension --- lib/active_record/turntable/active_record_ext.rb | 3 ++- .../turntable/active_record_ext/relation.rb | 9 +-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/lib/active_record/turntable/active_record_ext.rb b/lib/active_record/turntable/active_record_ext.rb index 0d120ec4..4e5af0bc 100644 --- a/lib/active_record/turntable/active_record_ext.rb +++ b/lib/active_record/turntable/active_record_ext.rb @@ -25,7 +25,8 @@ module ActiveRecordExt ActiveRecord::LogSubscriber.include(LogSubscriber) ActiveRecord::Persistence.include(Persistence) ActiveRecord::Locking::Optimistic.include(LockingOptimistic) - ActiveRecord::Relation.include(CleverLoad, Relation) + ActiveRecord::Relation.include(CleverLoad) + ActiveRecord::Relation.prepend(Relation) ActiveRecord::Migration.include(ActiveRecord::Turntable::Migration) ActiveRecord::ConnectionAdapters::ConnectionHandler.instance_exec do include ConnectionHandlerExtension diff --git a/lib/active_record/turntable/active_record_ext/relation.rb b/lib/active_record/turntable/active_record_ext/relation.rb index 238cf6f8..30ea868c 100644 --- a/lib/active_record/turntable/active_record_ext/relation.rb +++ b/lib/active_record/turntable/active_record_ext/relation.rb @@ -1,14 +1,8 @@ module ActiveRecord::Turntable module ActiveRecordExt module Relation - extend ActiveSupport::Concern - - included do - alias_method_chain :_update_record, :turntable - end - # @note Override to add sharding scope on updating - def _update_record_with_turntable(values, id, id_was, turntable_scope = nil) # :nodoc: + def _update_record(values, id, id_was, turntable_scope = nil) # :nodoc: substitutes, binds = substitute_values values scope = @klass.unscoped @@ -19,7 +13,6 @@ def _update_record_with_turntable(values, id, id_was, turntable_scope = nil) # : relation = scope.where(@klass.primary_key => (id_was || id)) relation = relation.merge(turntable_scope) if turntable_scope - bvs = binds + relation.bind_values um = relation. arel. From 61c5be84ee074e16f954c4cdccae6b8a7171eb3c Mon Sep 17 00:00:00 2001 From: gussan Date: Fri, 22 Apr 2016 17:27:27 +0900 Subject: [PATCH 014/125] Remove alias_methods from ConnectionHandlerExtension --- lib/active_record/turntable/active_record_ext.rb | 4 +--- .../active_record_ext/connection_handler_extension.rb | 5 ----- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/lib/active_record/turntable/active_record_ext.rb b/lib/active_record/turntable/active_record_ext.rb index 4e5af0bc..4ad00009 100644 --- a/lib/active_record/turntable/active_record_ext.rb +++ b/lib/active_record/turntable/active_record_ext.rb @@ -28,9 +28,7 @@ module ActiveRecordExt ActiveRecord::Relation.include(CleverLoad) ActiveRecord::Relation.prepend(Relation) ActiveRecord::Migration.include(ActiveRecord::Turntable::Migration) - ActiveRecord::ConnectionAdapters::ConnectionHandler.instance_exec do - include ConnectionHandlerExtension - end + ActiveRecord::ConnectionAdapters::ConnectionHandler.prepend(ConnectionHandlerExtension) ActiveRecord::Associations::Preloader::Association.prepend(AssociationPreloader) ActiveRecord::Associations::Association.include(Association) require "active_record/turntable/active_record_ext/fixtures" diff --git a/lib/active_record/turntable/active_record_ext/connection_handler_extension.rb b/lib/active_record/turntable/active_record_ext/connection_handler_extension.rb index 67810c0a..b0e33517 100644 --- a/lib/active_record/turntable/active_record_ext/connection_handler_extension.rb +++ b/lib/active_record/turntable/active_record_ext/connection_handler_extension.rb @@ -1,11 +1,6 @@ module ActiveRecord::Turntable module ActiveRecordExt module ConnectionHandlerExtension - extend ActiveSupport::Concern - - included do - alias_method_chain :pool_for, :turntable - end private From c60f75e4ee63df61acc69fbf91fb091f0d65830f Mon Sep 17 00:00:00 2001 From: gussan Date: Fri, 22 Apr 2016 17:39:09 +0900 Subject: [PATCH 015/125] Use `Module#prepend` on sequencer extension --- .../turntable/active_record_ext.rb | 2 +- .../turntable/active_record_ext/sequencer.rb | 21 ++++++------------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/lib/active_record/turntable/active_record_ext.rb b/lib/active_record/turntable/active_record_ext.rb index 4ad00009..49ff4b6f 100644 --- a/lib/active_record/turntable/active_record_ext.rb +++ b/lib/active_record/turntable/active_record_ext.rb @@ -20,7 +20,7 @@ module ActiveRecordExt included do include Transactions - ActiveRecord::ConnectionAdapters::AbstractAdapter.include(Sequencer) + ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend(Sequencer) ActiveRecord::ConnectionAdapters::AbstractAdapter.include(AbstractAdapter) ActiveRecord::LogSubscriber.include(LogSubscriber) ActiveRecord::Persistence.include(Persistence) diff --git a/lib/active_record/turntable/active_record_ext/sequencer.rb b/lib/active_record/turntable/active_record_ext/sequencer.rb index f5169357..ec28a44f 100644 --- a/lib/active_record/turntable/active_record_ext/sequencer.rb +++ b/lib/active_record/turntable/active_record_ext/sequencer.rb @@ -1,23 +1,14 @@ module ActiveRecord::Turntable::ActiveRecordExt module Sequencer - extend ActiveSupport::Concern - - included do - include DatabaseStatements - alias_method_chain :prefetch_primary_key?, :turntable - end - - module DatabaseStatements - def default_sequence_name(table_name, pk = nil) - if ActiveRecord::Turntable::Sequencer.has_sequencer?(table_name) - ActiveRecord::Turntable::Sequencer.sequence_name(table_name, pk) - else - super - end + def default_sequence_name(table_name, pk = nil) + if ActiveRecord::Turntable::Sequencer.has_sequencer?(table_name) + ActiveRecord::Turntable::Sequencer.sequence_name(table_name, pk) + else + super end end - def prefetch_primary_key_with_turntable?(table_name = nil) + def prefetch_primary_key?(table_name = nil) ActiveRecord::Turntable::Sequencer.has_sequencer?(table_name) end From c221322737ea6c45ac9053e20bcc33bbeb3f0a31 Mon Sep 17 00:00:00 2001 From: gussan Date: Fri, 22 Apr 2016 17:39:31 +0900 Subject: [PATCH 016/125] Use `Module#prepend` on LogSubscriber extension --- lib/active_record/turntable/active_record_ext.rb | 2 +- .../turntable/active_record_ext/log_subscriber.rb | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/lib/active_record/turntable/active_record_ext.rb b/lib/active_record/turntable/active_record_ext.rb index 49ff4b6f..f1b4401d 100644 --- a/lib/active_record/turntable/active_record_ext.rb +++ b/lib/active_record/turntable/active_record_ext.rb @@ -22,7 +22,7 @@ module ActiveRecordExt include Transactions ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend(Sequencer) ActiveRecord::ConnectionAdapters::AbstractAdapter.include(AbstractAdapter) - ActiveRecord::LogSubscriber.include(LogSubscriber) + ActiveRecord::LogSubscriber.prepend(LogSubscriber) ActiveRecord::Persistence.include(Persistence) ActiveRecord::Locking::Optimistic.include(LockingOptimistic) ActiveRecord::Relation.include(CleverLoad) diff --git a/lib/active_record/turntable/active_record_ext/log_subscriber.rb b/lib/active_record/turntable/active_record_ext/log_subscriber.rb index 49e2deed..2fab407f 100644 --- a/lib/active_record/turntable/active_record_ext/log_subscriber.rb +++ b/lib/active_record/turntable/active_record_ext/log_subscriber.rb @@ -3,16 +3,11 @@ module ActiveRecord::Turntable module ActiveRecordExt module LogSubscriber - extend ActiveSupport::Concern - - included do - alias_method_chain :sql, :turntable - end protected # @note Override to add shard name logging - def sql_with_turntable(event) + def sql(event) self.class.runtime += event.duration return unless logger.debug? From 51a256f4c0516368500862fbc5def479714276e4 Mon Sep 17 00:00:00 2001 From: gussan Date: Fri, 22 Apr 2016 17:46:06 +0900 Subject: [PATCH 017/125] Cleanup and update SchemaDumper extension --- .../active_record_ext/schema_dumper.rb | 35 ++++++++----------- .../turntable/railties/databases.rake | 2 +- 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/lib/active_record/turntable/active_record_ext/schema_dumper.rb b/lib/active_record/turntable/active_record_ext/schema_dumper.rb index df2ad381..a1f40b25 100644 --- a/lib/active_record/turntable/active_record_ext/schema_dumper.rb +++ b/lib/active_record/turntable/active_record_ext/schema_dumper.rb @@ -2,44 +2,37 @@ module ActiveRecord::Turntable module ActiveRecordExt module SchemaDumper - extend ActiveSupport::Concern - - included do - alias_method_chain :table, :turntable - end private # @note Override to dump database sequencer method - def table_with_turntable(table, stream) + def table(table, stream) columns = @connection.columns(table) begin tbl = StringIO.new # first dump primary key column - if @connection.respond_to?(:pk_and_sequence_for) - pk, = @connection.pk_and_sequence_for(table) - elsif @connection.respond_to?(:primary_key) - pk = @connection.primary_key(table) - end + pk = @connection.primary_key(table) - if table =~ /\A(.*)_id_seq\z/ - tbl.print " create_sequence_for #{remove_prefix_and_suffix($1).inspect}" - else - tbl.print " create_table #{remove_prefix_and_suffix(table).inspect}" - end + tbl.print = if table =~ /\A(.*)_id_seq\z/ + " create_sequence_for #{remove_prefix_and_suffix($1).inspect}" + else + " create_table #{remove_prefix_and_suffix(table).inspect}" + end pkcol = columns.detect { |c| c.name == pk } if pkcol - if pk != "id" - tbl.print %(, primary_key: "#{pk}") - elsif pkcol.sql_type == "uuid" + if pk != 'id' + tbl.print %Q(, primary_key: "#{pk}") + elsif pkcol.sql_type == 'bigint' + tbl.print ", id: :bigserial" + elsif pkcol.sql_type == 'uuid' tbl.print ", id: :uuid" - tbl.print %(, default: "#{pkcol.default_function}") if pkcol.default_function + tbl.print %Q(, default: #{pkcol.default_function.inspect}) end else tbl.print ", id: false" end - tbl.print ", force: true" + tbl.print ", force: :cascade" tbl.puts " do |t|" # then dump all non-primary key columns diff --git a/lib/active_record/turntable/railties/databases.rake b/lib/active_record/turntable/railties/databases.rake index 8e79bbf6..9e896fb6 100644 --- a/lib/active_record/turntable/railties/databases.rake +++ b/lib/active_record/turntable/railties/databases.rake @@ -1,5 +1,5 @@ require "active_record/turntable" -ActiveRecord::SchemaDumper.include(ActiveRecord::Turntable::ActiveRecordExt::SchemaDumper) +ActiveRecord::SchemaDumper.prepend(ActiveRecord::Turntable::ActiveRecordExt::SchemaDumper) turntable_namespace = nil From ddaf54332b704694d57f2b351b4ffc0a6e591131 Mon Sep 17 00:00:00 2001 From: gussan Date: Fri, 22 Apr 2016 18:56:56 +0900 Subject: [PATCH 018/125] Remove alias_method_chain from Migration extensions --- lib/active_record/turntable/migration.rb | 56 +++++++++++------------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/lib/active_record/turntable/migration.rb b/lib/active_record/turntable/migration.rb index 610a84fd..0f31afd6 100644 --- a/lib/active_record/turntable/migration.rb +++ b/lib/active_record/turntable/migration.rb @@ -3,12 +3,11 @@ module ActiveRecord::Turntable::Migration included do extend ShardDefinition + prepend OverrideMethods class_attribute :target_shards, :current_shard - alias_method_chain :announce, :turntable - alias_method_chain :exec_migration, :turntable ::ActiveRecord::ConnectionAdapters::AbstractAdapter.include(SchemaStatementsExt) ::ActiveRecord::Migration::CommandRecorder.include(CommandRecorder) - ::ActiveRecord::Migrator.include(Migrator) + ::ActiveRecord::Migrator.prepend(Migrator) end module ShardDefinition @@ -34,16 +33,18 @@ def shards(*connection_names) end end - def target_shard?(shard_name) - target_shards.blank? or target_shards.include?(shard_name) - end + module OverrideMethods + def announce(message) + super("#{message} - Shard: #{current_shard}") + end - def announce_with_turntable(message) - announce_without_turntable("#{message} - Shard: #{current_shard}") - end + def exec_migration(*args) + super(*args) if target_shard?(current_shard) + end - def exec_migration_with_turntable(*args) - exec_migration_without_turntable(*args) if target_shard?(current_shard) + def target_shard?(shard_name) + target_shards.blank? or target_shards.include?(shard_name) + end end module SchemaStatementsExt @@ -97,44 +98,37 @@ def invert_rename_sequence_for(args) module Migrator extend ActiveSupport::Concern - included do - klass = self - (class << klass; self; end).instance_eval { - [:up, :down, :run].each do |method_name| - original_method_alias = "_original_#{method_name}" - unless klass.respond_to?(original_method_alias) - alias_method original_method_alias, method_name - end - alias_method_chain method_name, :turntable - end - } + def self.prepended(base) + class << base + prepend ClassMethods + end end module ClassMethods - def up_with_turntable(migrations_paths, target_version = nil) - up_without_turntable(migrations_paths, target_version) + def up(migrations_paths, target_version = nil) + super ActiveRecord::Tasks::DatabaseTasks.each_current_turntable_cluster_connected do |name, configuration| puts "[turntable] *** Migrating database: #{configuration['database']}(Shard: #{name})" - _original_up(migrations_paths, target_version) + super(migrations_paths, target_version) end end - def down_with_turntable(migrations_paths, target_version = nil, &block) - down_without_turntable(migrations_paths, target_version, &block) + def down(migrations_paths, target_version = nil, &block) + super ActiveRecord::Tasks::DatabaseTasks.each_current_turntable_cluster_connected do |name, configuration| puts "[turntable] *** Migrating database: #{configuration['database']}(Shard: #{name})" - _original_down(migrations_paths, target_version, &block) + super(migrations_paths, target_version, &block) end end - def run_with_turntable(*args) - run_without_turntable(*args) + def run(*args) + super ActiveRecord::Tasks::DatabaseTasks.each_current_turntable_cluster_connected do |name, configuration| puts "[turntable] *** Migrating database: #{configuration['database']}(Shard: #{name})" - _original_run(*args) + super(*args) end end end From 74a92b813fa43b455c2629578c69ce585879bd13 Mon Sep 17 00:00:00 2001 From: gussan Date: Fri, 22 Apr 2016 19:00:54 +0900 Subject: [PATCH 019/125] Remove alias_method_chain from ar-import extension --- .../active_record_ext/activerecord_import_ext.rb | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb b/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb index 74cbb7b6..6ebf7a1b 100644 --- a/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb +++ b/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb @@ -2,17 +2,12 @@ module ActiveRecord::Turntable module ActiveRecordExt # activerecord-import extension module ActiverecordImportExt - extend ActiveSupport::Concern - - included do - alias_method_chain :values_sql_for_columns_and_attributes, :turntable - end private # @note override for sequencer injection # @see https://github.com/zdennis/activerecord-import/blob/ba909fed5a4785fe9c7cce89e48e1242bb6804ea/lib/activerecord-import/import.rb#L558-L581 - def values_sql_for_columns_and_attributes_with_turntable(columns, array_of_attributes) + def values_sql_for_columns_and_attributes(columns, array_of_attributes) connection_memo = connection array_of_attributes.map do |arr| my_values = arr.each_with_index.map do |val, j| @@ -41,7 +36,7 @@ def values_sql_for_columns_and_attributes_with_turntable(columns, array_of_attri begin require "activerecord-import" require "activerecord-import/base" - (class << ActiveRecord::Base; self; end).include(ActiverecordImportExt) + (class << ActiveRecord::Base; self; end).prepend(ActiverecordImportExt) rescue LoadError end end From 946e6992a5ae005e1fbfd93921814a7b2b273648 Mon Sep 17 00:00:00 2001 From: gussan Date: Fri, 22 Apr 2016 19:18:51 +0900 Subject: [PATCH 020/125] Remove alias_method_chain from acts_as_archive extension --- .../acts_as_archive_extension.rb | 41 +++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/lib/active_record/turntable/active_record_ext/acts_as_archive_extension.rb b/lib/active_record/turntable/active_record_ext/acts_as_archive_extension.rb index 1e18c2a7..ad56e16d 100644 --- a/lib/active_record/turntable/active_record_ext/acts_as_archive_extension.rb +++ b/lib/active_record/turntable/active_record_ext/acts_as_archive_extension.rb @@ -1,22 +1,31 @@ -begin - require "acts_as_archive" - # acts_as_archive extension - class ActsAsArchive - class << self - # @note use the same shard which `from` shard using - def move_with_turntable(config, where, merge_options = {}) - if [config[:to], config[:from]].all? { |k| k.try(:turntable_enabled?) } - current_shard = config[:from].connection.current_shard.name.to_sym - config[:to].connection.with_shard(current_shard) { - move_without_turntable(config, where, merge_options) - } - else - move_without_turntable(config, where, merge_options) +module ActiveRecord::Turntable + module ActiveRecordExt + module ActsAsArchiveExt + def self.prepended(base) + class << base + prepend ClassMethods end end - alias_method_chain :move, :turntable + module ClassMethods + # @note use the same shard which `from` shard using + def move(config, where, merge_options = {}) + if [config[:to], config[:from]].all? { |k| k.try(:turntable_enabled?) } + current_shard = config[:from].connection.current_shard.name.to_sym + config[:to].connection.with_shard(current_shard) { + super + } + else + super + end + end + end + end + + begin + require 'acts_as_archive' + ActsAsArchive.prepend ActsAsArchiveExt + rescue LoadError end end -rescue LoadError end From abe82e7f3f41ee5c1d2dd4989d1e50f3869ea3c5 Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 25 Apr 2016 15:15:08 +0900 Subject: [PATCH 021/125] Use with_indifferent_access on accessing turntable configuration --- lib/active_record/turntable/sequencer/api.rb | 4 ++-- script/performance/algorithm | 6 +++--- spec/active_record/turntable/sequencer/api_spec.rb | 2 +- spec/active_record/turntable/sequencer/barrage_spec.rb | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/active_record/turntable/sequencer/api.rb b/lib/active_record/turntable/sequencer/api.rb index fdb9c075..1b7f2e69 100644 --- a/lib/active_record/turntable/sequencer/api.rb +++ b/lib/active_record/turntable/sequencer/api.rb @@ -13,8 +13,8 @@ class Api < Sequencer def initialize(klass, options = {}) @klass = klass @options = options - @host = @options["api_host"] - @port = @options["api_port"] + @host = @options[:api_host] + @port = @options[:api_port] @client = HTTPClient.new end diff --git a/script/performance/algorithm b/script/performance/algorithm index 687cd2fe..b56d4bc5 100755 --- a/script/performance/algorithm +++ b/script/performance/algorithm @@ -1,14 +1,14 @@ #!/usr/bin/env ruby require "rspec" -require File.join(File.dirname(__FILE__), "../../../spec/spec_helper") +require File.join(File.dirname(__FILE__), "../../spec/spec_helper") require "benchmark" def setup_algorithm(n, alg = "Range") config = { "shards" => n.times.map do |i| - { "connection" => "connection_#{i}", "less_than" => (i + 1) * 100 } + { connection: "connection_#{i}", less_than: (i + 1) * 100 } end, - } + }.with_indifferent_access "ActiveRecord::Turntable::Algorithm::#{alg}Algorithm".constantize.new(config) end diff --git a/spec/active_record/turntable/sequencer/api_spec.rb b/spec/active_record/turntable/sequencer/api_spec.rb index 1a0bf9cc..340043e4 100644 --- a/spec/active_record/turntable/sequencer/api_spec.rb +++ b/spec/active_record/turntable/sequencer/api_spec.rb @@ -10,7 +10,7 @@ let(:klass) { Class.new } let(:api_host) { "example.example" } let(:api_port) { 80 } - let(:options) { { "api_host" => api_host, "api_port" => api_port } } + let(:options) { { api_host: api_host, api_port: api_port }.with_indifferent_access } let(:api_response) { 1024 } let(:next_sequence_uri) { "http://#{api_host}/sequences/#{sequence_name}/new" } diff --git a/spec/active_record/turntable/sequencer/barrage_spec.rb b/spec/active_record/turntable/sequencer/barrage_spec.rb index 68d8dab0..7dc0f2b3 100644 --- a/spec/active_record/turntable/sequencer/barrage_spec.rb +++ b/spec/active_record/turntable/sequencer/barrage_spec.rb @@ -7,7 +7,7 @@ let(:sequencer) { ActiveRecord::Turntable::Sequencer::Barrage.new(klass, options) } let(:sequence_name) { "hogefuga" } - let(:options) { { "options" => { "generators" => [{ "name" => "sequence", "length" => 16 }] } } } + let(:options) { { options: { generators: [{ name: "sequence", length: 16 }] } }.with_indifferent_access } let(:klass) { Class.new } describe "#next_sequence_value" do From ce20efd34031805e268462060d03cf6645158eec Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 25 Apr 2016 16:01:04 +0900 Subject: [PATCH 022/125] Remove unnecessary an option argument --- lib/active_record/turntable/base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/active_record/turntable/base.rb b/lib/active_record/turntable/base.rb index 8e403f06..a1257cfe 100644 --- a/lib/active_record/turntable/base.rb +++ b/lib/active_record/turntable/base.rb @@ -51,7 +51,7 @@ def turntable_replace_connection_pool def initialize_clusters! turntable_config[:clusters].each do |name, spec| - self.turntable_clusters[name] ||= Cluster.new(spec, {}) + self.turntable_clusters[name] ||= Cluster.new(spec) end end From 6c39b802e500cab9a6e252483f28fd8741a02e08 Mon Sep 17 00:00:00 2001 From: gussan Date: Fri, 7 Oct 2016 13:42:25 +0900 Subject: [PATCH 023/125] Update rails version dependency to 5 --- Gemfile | 5 ++--- activerecord-turntable.gemspec | 4 ++-- gemfiles/rails5_0.gemfile | 5 ++--- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Gemfile b/Gemfile index d7ee3f7c..be420c57 100644 --- a/Gemfile +++ b/Gemfile @@ -2,6 +2,5 @@ source "https://rubygems.org" gemspec -gem "activerecord", "5.0.0.alpha", github: "rails/rails" -gem "activesupport", "5.0.0.alpha", github: "rails/rails" -gem "arel", '7.0.0.alpha', github: "rails/arel" +gem "activerecord", "5.0.0.1" +gem "activesupport", "5.0.0.1" diff --git a/activerecord-turntable.gemspec b/activerecord-turntable.gemspec index 76bb8166..167cc5f3 100644 --- a/activerecord-turntable.gemspec +++ b/activerecord-turntable.gemspec @@ -23,8 +23,8 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] spec.required_ruby_version = ">= 2.2" - spec.add_runtime_dependency "activerecord", "= 5.0.0.alpha", "< 6.0" - spec.add_runtime_dependency "activesupport", "= 5.0.0.alpha", "< 6.0" + spec.add_runtime_dependency "activerecord", ">= 5.0", "< 6.0" + spec.add_runtime_dependency "activesupport", ">= 5.0", "< 6.0" spec.add_runtime_dependency "sql_tree", "= 0.2.0" spec.add_runtime_dependency "bsearch", "~> 1.5" spec.add_runtime_dependency "httpclient", ">= 0" diff --git a/gemfiles/rails5_0.gemfile b/gemfiles/rails5_0.gemfile index 3f05e4e4..fcfe1be0 100644 --- a/gemfiles/rails5_0.gemfile +++ b/gemfiles/rails5_0.gemfile @@ -1,7 +1,6 @@ source "https://rubygems.org" -gem "activerecord", "5.0.0.alpha", github: "rails/rails" -gem "activesupport", "5.0.0.alpha", github: "rails/rails" -gem "arel", '7.0.0.alpha', github: "rails/arel" +gem "activerecord", "5.0.0.1" +gem "activesupport", "5.0.0.1" gemspec :path => '../' From 6fdd42b181d45ef678c5aa4ef1056ec54c4e6c67 Mon Sep 17 00:00:00 2001 From: gussan Date: Fri, 7 Oct 2016 17:04:57 +0900 Subject: [PATCH 024/125] Follow `valid_options` api change --- lib/active_record/turntable/active_record_ext/association.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/active_record/turntable/active_record_ext/association.rb b/lib/active_record/turntable/active_record_ext/association.rb index b4ff8b74..111dae38 100644 --- a/lib/active_record/turntable/active_record_ext/association.rb +++ b/lib/active_record/turntable/active_record_ext/association.rb @@ -9,7 +9,7 @@ module Association included do ActiveRecord::Associations::SingularAssociation.prepend(AssociationExt) ActiveRecord::Associations::CollectionAssociation.prepend(AssociationExt) - ActiveRecord::Associations::Builder::Association.valid_options += [:foreign_shard_key] + ActiveRecord::Associations::Builder::Association::VALID_OPTIONS << :foreign_shard_key end private From 55f6877825ded80dfe6d6fb9fb2d9f8c689ecf66 Mon Sep 17 00:00:00 2001 From: gussan Date: Fri, 7 Oct 2016 18:58:18 +0900 Subject: [PATCH 025/125] Override connection_specification_name to use proxied connection on turntablized model --- lib/active_record/turntable/base.rb | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/active_record/turntable/base.rb b/lib/active_record/turntable/base.rb index a1257cfe..989cffc8 100644 --- a/lib/active_record/turntable/base.rb +++ b/lib/active_record/turntable/base.rb @@ -22,6 +22,13 @@ class << self include ClusterHelperMethods end + module ConnectionExtension + def connection_specification_name + return super unless turntable_enabled? + "turntable_pool_proxy::#{name}" + end + end + module ClassMethods # @param [Symbol] cluster_name cluster name for this class # @param [Symbol] shard_key_name shard key attribute name @@ -37,7 +44,8 @@ def turntable(cluster_name, shard_key_name, options = {}) self.turntable_clusters[cluster_name] ||= Cluster.new( turntable_config[:clusters][cluster_name], options - ) + ) + prepend ConnectionExtension turntable_replace_connection_pool end @@ -45,8 +53,8 @@ def turntable_replace_connection_pool ch = connection_handler cp = ConnectionProxy.new(self, turntable_cluster) pp = PoolProxy.new(cp) - ch.class_to_pool.clear if defined?(ch.class_to_pool) - ch.send(:class_to_pool)[name] = ch.send(:owner_to_pool)[name] = pp + + ch.send(:owner_to_pool)[connection_specification_name] = pp end def initialize_clusters! From c3439e96df6d5271609eea64730009d7f23289a9 Mon Sep 17 00:00:00 2001 From: gussan Date: Sun, 9 Oct 2016 16:39:37 +0900 Subject: [PATCH 026/125] Fixes `connection_specification_name` overrides --- lib/active_record/turntable/base.rb | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/active_record/turntable/base.rb b/lib/active_record/turntable/base.rb index 989cffc8..f12d061b 100644 --- a/lib/active_record/turntable/base.rb +++ b/lib/active_record/turntable/base.rb @@ -23,9 +23,17 @@ class << self end module ConnectionExtension - def connection_specification_name - return super unless turntable_enabled? - "turntable_pool_proxy::#{name}" + module ClassMethods + def connection_specification_name + return super unless turntable_enabled? + self.connection_specification_name = "turntable_pool_proxy::#{name}" + end + end + + def self.prepended(base) + class << base + prepend ClassMethods + end end end From 72e1a7f08f5390fc10e2383f0320fb5289afcf38 Mon Sep 17 00:00:00 2001 From: gussan Date: Sun, 9 Oct 2016 16:40:50 +0900 Subject: [PATCH 027/125] Follow ConnectionHandler changes --- .../connection_handler_extension.rb | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/lib/active_record/turntable/active_record_ext/connection_handler_extension.rb b/lib/active_record/turntable/active_record_ext/connection_handler_extension.rb index b0e33517..fb2db0d7 100644 --- a/lib/active_record/turntable/active_record_ext/connection_handler_extension.rb +++ b/lib/active_record/turntable/active_record_ext/connection_handler_extension.rb @@ -1,27 +1,28 @@ module ActiveRecord::Turntable module ActiveRecordExt module ConnectionHandlerExtension - - private - - # @note Override not to establish_connection destroy existing connection pool proxy object - def pool_for_with_turntable(owner) - owner_to_pool.fetch(owner.name) { - if ancestor_pool = pool_from_any_process_for(owner) - if ancestor_pool.is_a?(ActiveRecord::ConnectionAdapters::ConnectionPool) - # A connection was established in an ancestor process that must have - # subsequently forked. We can't reuse the connection, but we can copy - # the specification and establish a new connection with it. - establish_connection owner, ancestor_pool.spec - else - # Use same PoolProxy object - owner_to_pool[owner.name] = ancestor_pool + # @note Override not to establish_connection destroy existing connection pool proxy object + def retrieve_connection_pool(spec_name) + owner_to_pool.fetch(spec_name) do + # Check if a connection was previously established in an ancestor process, + # which may have been forked. + if ancestor_pool = pool_from_any_process_for(spec_name) + if ancestor_pool.is_a?(ActiveRecord::ConnectionAdapters::ConnectionPool) + # A connection was established in an ancestor process that must have + # subsequently forked. We can't reuse the connection, but we can copy + # the specification and establish a new connection with it. + establish_connection(ancestor_pool.spec.to_hash).tap do |pool| + pool.schema_cache = ancestor_pool.schema_cache if ancestor_pool.schema_cache end else - owner_to_pool[owner.name] = nil + # Use same PoolProxy object + owner_to_pool[spec_name] = ancestor_pool end - } + else + owner_to_pool[spec_name] = nil + end end + end end end end From 53ba7ef4cc52127f4877f471f175749b776f21ef Mon Sep 17 00:00:00 2001 From: gussan Date: Sun, 9 Oct 2016 16:41:44 +0900 Subject: [PATCH 028/125] Stop infinite loop on searching a connction pool --- lib/active_record/turntable/master_shard.rb | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/active_record/turntable/master_shard.rb b/lib/active_record/turntable/master_shard.rb index 4bd26890..8c0b4569 100644 --- a/lib/active_record/turntable/master_shard.rb +++ b/lib/active_record/turntable/master_shard.rb @@ -1,7 +1,7 @@ module ActiveRecord::Turntable class MasterShard < Shard def initialize(klass) - (klass and klass.connection_pool) or + (klass and original_connection_pool(klass)) or raise MasterShardNotConnected, "connection_pool is nil" @klass = klass @name = "master" @@ -11,8 +11,14 @@ def connection_pool if ActiveRecord::Base == @klass ActiveRecord::Base.connection_pool else - # use parentclass connection which is turntable disabled - klass = @klass.superclass + # use original parent class connection which is turntable disabled + original_connection_pool + end + end + + private + + def original_connection_pool(klass = @klass) candidate_connection_pool = nil until candidate_connection_pool if klass == ActiveRecord::Base || !klass.turntable_enabled? @@ -23,6 +29,5 @@ def connection_pool end candidate_connection_pool end - end end end From 2ad357dab40aedde25d12838e208f56442f9f555 Mon Sep 17 00:00:00 2001 From: gussan Date: Sun, 9 Oct 2016 23:58:32 +0900 Subject: [PATCH 029/125] Follow LogSubscriber changes and clean up --- .../active_record_ext/log_subscriber.rb | 40 ++++--------------- 1 file changed, 7 insertions(+), 33 deletions(-) diff --git a/lib/active_record/turntable/active_record_ext/log_subscriber.rb b/lib/active_record/turntable/active_record_ext/log_subscriber.rb index 2fab407f..5f23f509 100644 --- a/lib/active_record/turntable/active_record_ext/log_subscriber.rb +++ b/lib/active_record/turntable/active_record_ext/log_subscriber.rb @@ -3,40 +3,14 @@ module ActiveRecord::Turntable module ActiveRecordExt module LogSubscriber - - protected - - # @note Override to add shard name logging - def sql(event) - self.class.runtime += event.duration - return unless logger.debug? - - payload = event.payload - - return if ActiveRecord::LogSubscriber::IGNORE_PAYLOAD_NAMES.include?(payload[:name]) - - name = "#{payload[:name]} (#{event.duration.round(1)}ms)" - shard = "[Shard: %s]" % (event.payload[:turntable_shard_name] ? event.payload[:turntable_shard_name] : nil) - sql = payload[:sql].squeeze(" ") - binds = nil - - unless (payload[:binds] || []).empty? - binds = " " + payload[:binds].map { |col, v| - render_bind(col, v) - }.inspect - end - - if odd? - name = color(name, ActiveRecord::LogSubscriber::CYAN, true) - shard = color(shard, ActiveRecord::LogSubscriber::CYAN, true) - sql = color(sql, nil, true) - else - name = color(name, ActiveRecord::LogSubscriber::MAGENTA, true) - shard = color(shard, ActiveRecord::LogSubscriber::MAGENTA, true) - end - - debug " #{name} #{shard} #{sql}#{binds}" + # @note prepend to add shard name logging + def sql(event) + payload = event.payload + if payload[:turntable_shard_name] + payload[:name] = "#{payload[:name]} [Shard: #{payload[:turntable_shard_name]}]" end + super + end end end end From 13e4eecc327e6e2711c8867860bbf9104575bbda Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 10 Oct 2016 00:00:21 +0900 Subject: [PATCH 030/125] Follow transactions impl changes --- .../turntable/active_record_ext/transactions.rb | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/active_record/turntable/active_record_ext/transactions.rb b/lib/active_record/turntable/active_record_ext/transactions.rb index 668a5d6d..e2e19c9c 100644 --- a/lib/active_record/turntable/active_record_ext/transactions.rb +++ b/lib/active_record/turntable/active_record_ext/transactions.rb @@ -24,13 +24,22 @@ def with_transaction_returning_status else super end + + ensure + if @transaction_state && @transaction_state.committed? + clear_transaction_record_state + end end def add_to_transaction if self.class.turntable_enabled? - if self.turntable_shard.connection.add_transaction_record(self) - remember_transaction_record_state + if has_transactional_callbacks? + self.turntable_shard.connection.add_transaction_record(self) + else + sync_with_transaction_state + set_transaction_state(self.turntable_shard.connection.transaction_state) end + remember_transaction_record_state else super end From 952a43a55a2fbbd6d29186fcda68409ca9f21d61 Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 10 Oct 2016 00:00:56 +0900 Subject: [PATCH 031/125] Follow optimistic locking impl changes --- .../active_record_ext/locking_optimistic.rb | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/lib/active_record/turntable/active_record_ext/locking_optimistic.rb b/lib/active_record/turntable/active_record_ext/locking_optimistic.rb index ea4aa14e..607b9535 100644 --- a/lib/active_record/turntable/active_record_ext/locking_optimistic.rb +++ b/lib/active_record/turntable/active_record_ext/locking_optimistic.rb @@ -20,25 +20,21 @@ def _update_record(attribute_names = self.attribute_names) #:nodoc: relation = self.class.unscoped condition_scope = relation.where( - relation.table[self.class.primary_key].eq(id).and( - relation.table[lock_col].eq(self.class.quote_value(previous_lock_value, column_for_attribute(lock_col))) - ) + self.class.primary_key => id, + lock_col => previous_lock_value, ) if klass.turntable_enabled? and klass.primary_key != klass.turntable_shard_key.to_s condition_scope = condition_scope.where( - relation.table[klass.turntable_shard_key].eq( - self.class.quote_value(self.send(turntable_shard_key), column_for_attribute(klass.turntable_shard_key)) - ) + klass.turntable_shard_key => self.send(klass.turntable_shard_key) ) end - stmt = condition_scope.arel.compile_update( - arel_attributes_with_values_for_update(attribute_names), - self.class.primary_key + affected_rows = condition_scope.update_all( + attributes_for_update(attribute_names).map do |name| + [name, _read_attribute(name)] + end.to_h ) - affected_rows = self.class.connection.update stmt - unless affected_rows == 1 raise ActiveRecord::StaleObjectError.new(self, "update") end From a3ee715a88c6039ebbbb7a195702a2c6f8c92945 Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 10 Oct 2016 00:02:06 +0900 Subject: [PATCH 032/125] Follow persistence module impl changes --- .../active_record_ext/persistence.rb | 60 ++++++++++--------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/lib/active_record/turntable/active_record_ext/persistence.rb b/lib/active_record/turntable/active_record_ext/persistence.rb index 45866e29..a3a74317 100644 --- a/lib/active_record/turntable/active_record_ext/persistence.rb +++ b/lib/active_record/turntable/active_record_ext/persistence.rb @@ -6,8 +6,7 @@ module Persistence ::ActiveRecord::Persistence.class_eval do # @note Override to add sharding scope on reloading def reload(options = nil) - clear_aggregation_cache - clear_association_cache + self.class.connection.clear_query_cache finder_scope = if turntable_enabled? && self.class.primary_key != self.class.turntable_shard_key.to_s self.class.unscoped.where(self.class.turntable_shard_key => self.send(turntable_shard_key)) @@ -17,7 +16,7 @@ def reload(options = nil) fresh_object = if options && options[:lock] - finder_scope.lock.find(id) + finder_scope.lock(options[:lock]).find(id) else finder_scope.find(id) end @@ -28,33 +27,48 @@ def reload(options = nil) end # @note Override to add sharding scope on `touch` - def touch(*names) - raise ActiveRecordError, "cannot touch on a new record object" unless persisted? + def touch(*names, time: nil) + unless persisted? + raise ActiveRecordError, <<-MSG.squish + cannot touch on a new or destroyed record object. Consider using + persisted?, new_record?, or destroyed? before touching + MSG + end + time ||= current_time_from_proper_timezone attributes = timestamp_attributes_for_update_in_model attributes.concat(names) unless attributes.empty? - current_time = current_time_from_proper_timezone changes = {} attributes.each do |column| column = column.to_s - changes[column] = write_attribute(column, current_time) + changes[column] = write_attribute(column, time) end - changes[self.class.locking_column] = increment_lock if locking_enabled? + primary_key = self.class.primary_key + scope = if turntable_enabled? && primary_key != self.class.turntable_shard_key.to_s + self.class.unscoped.where(self.class.turntable_shard_key => _read_attribute(turntable_shard_key)) + else + self.class.unscoped + end + scope = scope.where(primary_key => _read_attribute(primary_key)) + + if locking_enabled? + locking_column = self.class.locking_column + scope = scope.where(locking_column => _read_attribute(locking_column)) + changes[locking_column] = increment_lock + end clear_attribute_changes(changes.keys) - primary_key = self.class.primary_key + result = scope.update_all(changes) == 1 - finder_scope = if turntable_enabled? && primary_key != self.class.turntable_shard_key.to_s - self.class.unscoped.where(self.class.turntable_shard_key => self.send(turntable_shard_key)) - else - self.class.unscoped - end + if !result && locking_enabled? + raise ActiveRecord::StaleObjectError.new(self, "touch") + end - finder_scope.where(primary_key => self[primary_key]).update_all(changes) == 1 + result else true end @@ -88,21 +102,11 @@ def update_columns(attributes) # @note Override to add sharding scope on destroying def relation_for_destroy - pk = self.class.primary_key - column = self.class.columns_hash[pk] - substitute = self.class.connection.substitute_at(column, 0) - klass = self.class - - relation = self.class.unscoped.where( - self.class.arel_table[pk].eq(substitute)) - relation.bind_values = [[column, id]] + klass = self.class + relation = klass.unscoped.where(klass.primary_key => id) if klass.turntable_enabled? && klass.primary_key != klass.turntable_shard_key.to_s - shard_key_column = klass.columns_hash[klass.turntable_shard_key] - shard_key_substitute = klass.connection.substitute_at(shard_key_column) - - relation = relation.where(self.class.arel_table[klass.turntable_shard_key].eq(shard_key_substitute)) - relation.bind_values << [shard_key_column, self[klass.turntable_shard_key]] + relation = relation.where(klass.turntable_shard_key => self[klass.turntable_shard_key]) end relation end From ddf53a2e4be42a5f5ee8a6d59f029798799c77d2 Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 10 Oct 2016 00:02:29 +0900 Subject: [PATCH 033/125] Follow Relation module impl changes --- lib/active_record/turntable/active_record_ext/relation.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/active_record/turntable/active_record_ext/relation.rb b/lib/active_record/turntable/active_record_ext/relation.rb index 30ea868c..74cb1a12 100644 --- a/lib/active_record/turntable/active_record_ext/relation.rb +++ b/lib/active_record/turntable/active_record_ext/relation.rb @@ -13,7 +13,7 @@ def _update_record(values, id, id_was, turntable_scope = nil) # :nodoc: relation = scope.where(@klass.primary_key => (id_was || id)) relation = relation.merge(turntable_scope) if turntable_scope - bvs = binds + relation.bind_values + bvs = binds + relation.bound_attributes um = relation. arel. compile_update(substitutes, @klass.primary_key) From 625b74a73c05fd84b0ed0e2a9fdf78ccb9147880 Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 10 Oct 2016 00:03:10 +0900 Subject: [PATCH 034/125] Follow QueryCache impl changes --- .../turntable/rack/query_cache.rb | 36 +++++++++---------- lib/active_record/turntable/railtie.rb | 8 +++-- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/lib/active_record/turntable/rack/query_cache.rb b/lib/active_record/turntable/rack/query_cache.rb index a1e7fc5d..dc642c3b 100644 --- a/lib/active_record/turntable/rack/query_cache.rb +++ b/lib/active_record/turntable/rack/query_cache.rb @@ -5,35 +5,33 @@ module ActiveRecord module Turntable module Rack class QueryCache < ActiveRecord::QueryCache - def call(env) - enabled = ActiveRecord::Base.connection.query_cache_enabled - connection_id = ActiveRecord::Base.connection_id + def self.run klasses = ActiveRecord::Base.turntable_connections.values - klasses.each do |k| + enables = klasses.map do |k| + enabled = k.connection.query_cache_enabled k.connection.enable_query_cache! - end - response = @app.call(env) - response[2] = ::Rack::BodyProxy.new(response[2]) do - restore_query_cache_settings(connection_id, enabled) + enabled end - response - rescue Exception => e - restore_query_cache_settings(connection_id, enabled) - raise e + enables.all? end - private + def self.complete(enabled) + klasses = ActiveRecord::Base.turntable_connections.values + klasses.each do |k| + k.connection.clear_query_cache + k.connection.disable_query_cache! unless enabled - def restore_query_cache_settings(connection_id, enabled) - klasses = ActiveRecord::Base.turntable_connections.values - klasses.each do |k| - ActiveRecord::Base.connection_id = connection_id - k.connection.clear_query_cache - k.connection.disable_query_cache! unless enabled + unless k.connected? && k.connection.transaction_open? + k.clear_active_connections! end end + end + + def self.install_executor_hooks(executor = ActiveSupport::Executor) + executor.register_hook(self) + end end end end diff --git a/lib/active_record/turntable/railtie.rb b/lib/active_record/turntable/railtie.rb index b4ab3d01..d0bde97f 100644 --- a/lib/active_record/turntable/railtie.rb +++ b/lib/active_record/turntable/railtie.rb @@ -23,9 +23,11 @@ class Railtie < Rails::Railtie end end - # QueryCache Middleware for turntable shards - initializer "turntable.insert_query_cache_middleware" do |app| - app.middleware.insert_after ActiveRecord::QueryCache, ActiveRecord::Turntable::Rack::QueryCache + # set QueryCache executor hooks for turntable clusters + initializer "active_record.set_executor_hooks" do + ActiveSupport.on_load(:active_record) do + ActiveRecord::Turntable::Rack::QueryCache.install_executor_hooks + end end end end From 73c0decdb30af6da654953192a2d448d79165c93 Mon Sep 17 00:00:00 2001 From: gussan Date: Tue, 11 Oct 2016 14:38:02 +0900 Subject: [PATCH 035/125] Use timecop to check changes on updated_at column --- activerecord-turntable.gemspec | 1 + .../turntable/active_record_ext/persistence_spec.rb | 11 +++++++---- spec/spec_helper.rb | 1 + 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/activerecord-turntable.gemspec b/activerecord-turntable.gemspec index 167cc5f3..15a98746 100644 --- a/activerecord-turntable.gemspec +++ b/activerecord-turntable.gemspec @@ -49,6 +49,7 @@ Gem::Specification.new do |spec| spec.add_development_dependency "rubocop" spec.add_development_dependency "onkcop" spec.add_development_dependency "guard-rubocop" + spec.add_development_dependency "timecop" if RUBY_PLATFORM =~ /darwin/ spec.add_development_dependency "growl" diff --git a/spec/active_record/turntable/active_record_ext/persistence_spec.rb b/spec/active_record/turntable/active_record_ext/persistence_spec.rb index 53e2a389..bc305855 100644 --- a/spec/active_record/turntable/active_record_ext/persistence_spec.rb +++ b/spec/active_record/turntable/active_record_ext/persistence_spec.rb @@ -121,11 +121,14 @@ def on_update end it "should change updated_at when updating" do - cards_user.num = 2 + cards_user - expect { - cards_user.save! - }.to change(cards_user, :updated_at) + Timecop.travel(1.day.from_now) do + expect { + cards_user.num = 2 + cards_user.save! + }.to change(cards_user, :updated_at) + end end it "should send shard_key condition when destroying" do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 495b1dd2..e0d1848b 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -6,6 +6,7 @@ require "rspec/collection_matchers" require "webmock/rspec" require "pry" +require "timecop" begin require "pry-byebug" rescue LoadError From 0b110ca983f829b91512b0aaae1d296079de8e2a Mon Sep 17 00:00:00 2001 From: gussan Date: Tue, 11 Oct 2016 16:01:05 +0900 Subject: [PATCH 036/125] Adapt QueryCache extension to executor hooks --- lib/active_record/turntable.rb | 4 ++++ lib/active_record/turntable/rack/query_cache.rb | 13 +++++++++---- lib/active_record/turntable/shard.rb | 3 +++ .../turntable/rack/query_cache_spec.rb | 11 ++++++++++- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/lib/active_record/turntable.rb b/lib/active_record/turntable.rb index 263aef05..08cdadf2 100644 --- a/lib/active_record/turntable.rb +++ b/lib/active_record/turntable.rb @@ -57,6 +57,10 @@ def turntable_config_file=(filename) def turntable_config ActiveRecord::Turntable::Config.instance end + + def turntable_connection_classes + ActiveRecord::Turntable::Shard.connection_classes + end end require "active_record/turntable/railtie" if defined?(Rails) diff --git a/lib/active_record/turntable/rack/query_cache.rb b/lib/active_record/turntable/rack/query_cache.rb index dc642c3b..d76c64a7 100644 --- a/lib/active_record/turntable/rack/query_cache.rb +++ b/lib/active_record/turntable/rack/query_cache.rb @@ -22,15 +22,20 @@ def self.complete(enabled) klasses.each do |k| k.connection.clear_query_cache k.connection.disable_query_cache! unless enabled - - unless k.connected? && k.connection.transaction_open? - k.clear_active_connections! - end end end def self.install_executor_hooks(executor = ActiveSupport::Executor) executor.register_hook(self) + + executor.to_complete do + klasses = ActiveRecord::Base.turntable_connection_classes + klasses.each do |k| + unless k.connected? && k.connection.transaction_open? + k.clear_active_connections! + end + end + end end end end diff --git a/lib/active_record/turntable/shard.rb b/lib/active_record/turntable/shard.rb index f4ef165a..833bdbe8 100644 --- a/lib/active_record/turntable/shard.rb +++ b/lib/active_record/turntable/shard.rb @@ -1,6 +1,9 @@ module ActiveRecord::Turntable class Shard module Connections; end + def self.connection_classes + Connections.constants.map { |name| Connections.const_get(name) } + end DEFAULT_CONFIG = { "connection" => (defined?(Rails) ? Rails.env : "development"), diff --git a/spec/active_record/turntable/rack/query_cache_spec.rb b/spec/active_record/turntable/rack/query_cache_spec.rb index 843b06e6..46339008 100644 --- a/spec/active_record/turntable/rack/query_cache_spec.rb +++ b/spec/active_record/turntable/rack/query_cache_spec.rb @@ -1,4 +1,5 @@ require "spec_helper" +require "active_support/executor" describe ActiveRecord::Turntable::Rack::QueryCache do before(:all) do @@ -10,7 +11,15 @@ truncate_shard end - let(:mw) { ActiveRecord::Turntable::Rack::QueryCache.new lambda { |_env| [200, {}] } } + let(:mw) { + executor = Class.new(ActiveSupport::Executor) + ActiveRecord::Turntable::Rack::QueryCache.install_executor_hooks executor + lambda { |env| + executor.wrap { + [200, {}, nil] + } + } + } subject { mw.call({}) } it "should returns 200 response" do From 192efdccf40ed9da3493e60ebd0199fadb38d063 Mon Sep 17 00:00:00 2001 From: gussan Date: Tue, 11 Oct 2016 16:08:45 +0900 Subject: [PATCH 037/125] Move `QueryCache` under namespace `ActiveRecord::Turntable` --- lib/active_record/turntable.rb | 1 + lib/active_record/turntable/query_cache.rb | 41 ++++++++++++++++++ lib/active_record/turntable/rack.rb | 1 - .../turntable/rack/query_cache.rb | 43 ------------------- lib/active_record/turntable/railtie.rb | 2 +- .../turntable/{rack => }/query_cache_spec.rb | 6 +-- 6 files changed, 46 insertions(+), 48 deletions(-) create mode 100644 lib/active_record/turntable/query_cache.rb delete mode 100644 lib/active_record/turntable/rack/query_cache.rb rename spec/active_record/turntable/{rack => }/query_cache_spec.rb (64%) diff --git a/lib/active_record/turntable.rb b/lib/active_record/turntable.rb index 08cdadf2..1dce17c1 100644 --- a/lib/active_record/turntable.rb +++ b/lib/active_record/turntable.rb @@ -28,6 +28,7 @@ module ActiveRecord::Turntable autoload :Migration autoload :Mixer autoload :PoolProxy + autoload :QueryCache autoload :Shard autoload :ShardingCondition autoload :SeqShard diff --git a/lib/active_record/turntable/query_cache.rb b/lib/active_record/turntable/query_cache.rb new file mode 100644 index 00000000..d4fa4546 --- /dev/null +++ b/lib/active_record/turntable/query_cache.rb @@ -0,0 +1,41 @@ +require "rack/body_proxy" +require "active_record/query_cache" + +module ActiveRecord + module Turntable + class QueryCache < ActiveRecord::QueryCache + def self.run + klasses = ActiveRecord::Base.turntable_connections.values + enables = klasses.map do |k| + enabled = k.connection.query_cache_enabled + k.connection.enable_query_cache! + + enabled + end + + enables.all? + end + + def self.complete(enabled) + klasses = ActiveRecord::Base.turntable_connections.values + klasses.each do |k| + k.connection.clear_query_cache + k.connection.disable_query_cache! unless enabled + end + end + + def self.install_executor_hooks(executor = ActiveSupport::Executor) + executor.register_hook(self) + + executor.to_complete do + klasses = ActiveRecord::Base.turntable_connection_classes + klasses.each do |k| + unless k.connected? && k.connection.transaction_open? + k.clear_active_connections! + end + end + end + end + end + end +end diff --git a/lib/active_record/turntable/rack.rb b/lib/active_record/turntable/rack.rb index c08706b2..d8e11308 100644 --- a/lib/active_record/turntable/rack.rb +++ b/lib/active_record/turntable/rack.rb @@ -3,6 +3,5 @@ module Rack extend ActiveSupport::Autoload autoload :ConnectionManagement - autoload :QueryCache end end diff --git a/lib/active_record/turntable/rack/query_cache.rb b/lib/active_record/turntable/rack/query_cache.rb deleted file mode 100644 index d76c64a7..00000000 --- a/lib/active_record/turntable/rack/query_cache.rb +++ /dev/null @@ -1,43 +0,0 @@ -require "rack/body_proxy" -require "active_record/query_cache" - -module ActiveRecord - module Turntable - module Rack - class QueryCache < ActiveRecord::QueryCache - def self.run - klasses = ActiveRecord::Base.turntable_connections.values - enables = klasses.map do |k| - enabled = k.connection.query_cache_enabled - k.connection.enable_query_cache! - - enabled - end - - enables.all? - end - - def self.complete(enabled) - klasses = ActiveRecord::Base.turntable_connections.values - klasses.each do |k| - k.connection.clear_query_cache - k.connection.disable_query_cache! unless enabled - end - end - - def self.install_executor_hooks(executor = ActiveSupport::Executor) - executor.register_hook(self) - - executor.to_complete do - klasses = ActiveRecord::Base.turntable_connection_classes - klasses.each do |k| - unless k.connected? && k.connection.transaction_open? - k.clear_active_connections! - end - end - end - end - end - end - end -end diff --git a/lib/active_record/turntable/railtie.rb b/lib/active_record/turntable/railtie.rb index d0bde97f..874d7b6e 100644 --- a/lib/active_record/turntable/railtie.rb +++ b/lib/active_record/turntable/railtie.rb @@ -26,7 +26,7 @@ class Railtie < Rails::Railtie # set QueryCache executor hooks for turntable clusters initializer "active_record.set_executor_hooks" do ActiveSupport.on_load(:active_record) do - ActiveRecord::Turntable::Rack::QueryCache.install_executor_hooks + ActiveRecord::Turntable::QueryCache.install_executor_hooks end end end diff --git a/spec/active_record/turntable/rack/query_cache_spec.rb b/spec/active_record/turntable/query_cache_spec.rb similarity index 64% rename from spec/active_record/turntable/rack/query_cache_spec.rb rename to spec/active_record/turntable/query_cache_spec.rb index 46339008..d0404d40 100644 --- a/spec/active_record/turntable/rack/query_cache_spec.rb +++ b/spec/active_record/turntable/query_cache_spec.rb @@ -1,9 +1,9 @@ require "spec_helper" require "active_support/executor" -describe ActiveRecord::Turntable::Rack::QueryCache do +describe ActiveRecord::Turntable::QueryCache do before(:all) do - reload_turntable!(File.join(File.dirname(__FILE__), "../../../config/turntable.yml")) + reload_turntable!(File.join(File.dirname(__FILE__), "../../config/turntable.yml")) end before do @@ -13,7 +13,7 @@ let(:mw) { executor = Class.new(ActiveSupport::Executor) - ActiveRecord::Turntable::Rack::QueryCache.install_executor_hooks executor + ActiveRecord::Turntable::QueryCache.install_executor_hooks executor lambda { |env| executor.wrap { [200, {}, nil] From f6f89ab100b294313544ca3f84df04f9ca96d122 Mon Sep 17 00:00:00 2001 From: gussan Date: Tue, 11 Oct 2016 16:19:03 +0900 Subject: [PATCH 038/125] Update required ruby version to >= 2.2.2 --- activerecord-turntable.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord-turntable.gemspec b/activerecord-turntable.gemspec index 15a98746..6766f0dd 100644 --- a/activerecord-turntable.gemspec +++ b/activerecord-turntable.gemspec @@ -21,7 +21,7 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ["lib"] - spec.required_ruby_version = ">= 2.2" + spec.required_ruby_version = ">= 2.2.2" spec.add_runtime_dependency "activerecord", ">= 5.0", "< 6.0" spec.add_runtime_dependency "activesupport", ">= 5.0", "< 6.0" From 3bc358b379c4636e313aa497ed572854419ea170 Mon Sep 17 00:00:00 2001 From: gussan Date: Tue, 11 Oct 2016 16:28:04 +0900 Subject: [PATCH 039/125] Update travis target ruby versions --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3e678094..a615a1e8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: ruby rvm: - - 2.2 - - 2.3.0 + - 2.2.2 + - 2.3.1 - ruby-head gemfile: - gemfiles/rails5_0.gemfile From 99a534f3ffad1d3350dcd25e39f2c285ea9138ba Mon Sep 17 00:00:00 2001 From: gussan Date: Tue, 11 Oct 2016 16:31:01 +0900 Subject: [PATCH 040/125] Update CHANGELOG --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f32c9450..efb50a56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ ## activerecord-turntable 3.0.0.alpha (unreleased) ## +* Rails5 compatibility + * Minimum ruby requirement version is `2.2.2` + * Rails 4.x support has been dropped. + + ## activerecord-turntable 2.3.3 ## ### Bugfix From 878d67672f446b168543864ad630add7abb8f4b4 Mon Sep 17 00:00:00 2001 From: gussan Date: Tue, 11 Oct 2016 16:32:25 +0900 Subject: [PATCH 041/125] Add rubocop-rspec --- .rubocop.yml | 4 +++- activerecord-turntable.gemspec | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.rubocop.yml b/.rubocop.yml index fa5b2671..ff410e55 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,5 +1,7 @@ inherit_gem: - onkcop: "config/rubocop.yml" + onkcop: + - "config/rubocop.yml" + - "config/rspec.yml" AllCops: TargetRubyVersion: 2.2 diff --git a/activerecord-turntable.gemspec b/activerecord-turntable.gemspec index 6766f0dd..012b4e8c 100644 --- a/activerecord-turntable.gemspec +++ b/activerecord-turntable.gemspec @@ -47,6 +47,7 @@ Gem::Specification.new do |spec| spec.add_development_dependency "guard-rspec" spec.add_development_dependency "coveralls" spec.add_development_dependency "rubocop" + spec.add_development_dependency "rubocop-rspec" spec.add_development_dependency "onkcop" spec.add_development_dependency "guard-rubocop" spec.add_development_dependency "timecop" From 455505718d71b9a7a8479132eed1c5eaddbf9cdb Mon Sep 17 00:00:00 2001 From: gussan Date: Tue, 11 Oct 2016 16:33:42 +0900 Subject: [PATCH 042/125] Revert "Update travis target ruby versions" This reverts commit b0a0bf8a627c72978e627fe8b151b381c68668aa. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index a615a1e8..3e678094 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: ruby rvm: - - 2.2.2 - - 2.3.1 + - 2.2 + - 2.3.0 - ruby-head gemfile: - gemfiles/rails5_0.gemfile From 75da2f396fc4d5beb57a82e61188b48fe94b3dc5 Mon Sep 17 00:00:00 2001 From: gussan Date: Tue, 11 Oct 2016 16:34:08 +0900 Subject: [PATCH 043/125] Re-update travis target ruby versions --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3e678094..be8fd322 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: ruby rvm: - 2.2 - - 2.3.0 + - 2.3.1 - ruby-head gemfile: - gemfiles/rails5_0.gemfile From 1340d8de6e8624e889e8f41b7a95f47423fce946 Mon Sep 17 00:00:00 2001 From: gussan Date: Tue, 11 Oct 2016 16:44:22 +0900 Subject: [PATCH 044/125] Sort gem names --- activerecord-turntable.gemspec | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/activerecord-turntable.gemspec b/activerecord-turntable.gemspec index 012b4e8c..d45dc204 100644 --- a/activerecord-turntable.gemspec +++ b/activerecord-turntable.gemspec @@ -25,32 +25,31 @@ Gem::Specification.new do |spec| spec.add_runtime_dependency "activerecord", ">= 5.0", "< 6.0" spec.add_runtime_dependency "activesupport", ">= 5.0", "< 6.0" - spec.add_runtime_dependency "sql_tree", "= 0.2.0" spec.add_runtime_dependency "bsearch", "~> 1.5" spec.add_runtime_dependency "httpclient", ">= 0" + spec.add_runtime_dependency "sql_tree", "= 0.2.0" # optional dependencies spec.add_development_dependency "activerecord-import" spec.add_development_dependency "barrage" - spec.add_development_dependency "mysql2" - - spec.add_development_dependency "rake" - spec.add_development_dependency "rack" - spec.add_development_dependency "rspec", "~> 3.1.0" - spec.add_development_dependency "rspec-its" - spec.add_development_dependency "rspec-collection_matchers" + spec.add_development_dependency "coveralls" spec.add_development_dependency "fabrication" spec.add_development_dependency "faker" - spec.add_development_dependency "webmock" + spec.add_development_dependency "guard-rspec" + spec.add_development_dependency "guard-rubocop" + spec.add_development_dependency "mysql2" + spec.add_development_dependency "onkcop" spec.add_development_dependency "pry" spec.add_development_dependency "pry-byebug" - spec.add_development_dependency "guard-rspec" - spec.add_development_dependency "coveralls" + spec.add_development_dependency "rack" + spec.add_development_dependency "rake" + spec.add_development_dependency "rspec", "~> 3.1.0" + spec.add_development_dependency "rspec-collection_matchers" + spec.add_development_dependency "rspec-its" spec.add_development_dependency "rubocop" spec.add_development_dependency "rubocop-rspec" - spec.add_development_dependency "onkcop" - spec.add_development_dependency "guard-rubocop" spec.add_development_dependency "timecop" + spec.add_development_dependency "webmock" if RUBY_PLATFORM =~ /darwin/ spec.add_development_dependency "growl" From 653bd7d90a9f02512abed2ab1fd64ad893a9e804 Mon Sep 17 00:00:00 2001 From: gussan Date: Tue, 11 Oct 2016 16:44:44 +0900 Subject: [PATCH 045/125] Remove growl dependency --- activerecord-turntable.gemspec | 4 ---- 1 file changed, 4 deletions(-) diff --git a/activerecord-turntable.gemspec b/activerecord-turntable.gemspec index d45dc204..f6d388e2 100644 --- a/activerecord-turntable.gemspec +++ b/activerecord-turntable.gemspec @@ -50,8 +50,4 @@ Gem::Specification.new do |spec| spec.add_development_dependency "rubocop-rspec" spec.add_development_dependency "timecop" spec.add_development_dependency "webmock" - - if RUBY_PLATFORM =~ /darwin/ - spec.add_development_dependency "growl" - end end From 7f1aca13dcc33761f3ea856925b7554fc1e5684d Mon Sep 17 00:00:00 2001 From: gussan Date: Tue, 11 Oct 2016 16:46:47 +0900 Subject: [PATCH 046/125] Update travis.yml to use ruby 2.2.5 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index be8fd322..3ce47eca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: ruby rvm: - - 2.2 + - 2.2.5 - 2.3.1 - ruby-head gemfile: From 42fe5cabd17e050bdacb7f2e8b0cf192554dab5b Mon Sep 17 00:00:00 2001 From: gussan Date: Tue, 11 Oct 2016 17:09:06 +0900 Subject: [PATCH 047/125] Update `AbstractAdapter` extension * Follow latest AbstractAdapter impl * Use `Module#prepend` instead of overriding methods --- .../turntable/active_record_ext.rb | 2 +- .../active_record_ext/abstract_adapter.rb | 43 +++++++++++-------- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/lib/active_record/turntable/active_record_ext.rb b/lib/active_record/turntable/active_record_ext.rb index f1b4401d..eebf178e 100644 --- a/lib/active_record/turntable/active_record_ext.rb +++ b/lib/active_record/turntable/active_record_ext.rb @@ -21,7 +21,7 @@ module ActiveRecordExt included do include Transactions ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend(Sequencer) - ActiveRecord::ConnectionAdapters::AbstractAdapter.include(AbstractAdapter) + ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend(AbstractAdapter) ActiveRecord::LogSubscriber.prepend(LogSubscriber) ActiveRecord::Persistence.include(Persistence) ActiveRecord::Locking::Optimistic.include(LockingOptimistic) diff --git a/lib/active_record/turntable/active_record_ext/abstract_adapter.rb b/lib/active_record/turntable/active_record_ext/abstract_adapter.rb index 3ad5025c..ec2c16fd 100644 --- a/lib/active_record/turntable/active_record_ext/abstract_adapter.rb +++ b/lib/active_record/turntable/active_record_ext/abstract_adapter.rb @@ -1,29 +1,34 @@ module ActiveRecord::Turntable module ActiveRecordExt module AbstractAdapter - extend ActiveSupport::Concern - - included do - protected - - # @note override for logging current shard name - def log(sql, name = "SQL", binds = []) - @instrumenter.instrument( - "sql.active_record", - sql: sql, - name: name, - connection_id: object_id, - binds: binds, - turntable_shard_name: turntable_shard_name) { yield } - rescue Exception => e + def translate_exception_class(e, sql) + begin message = "#{e.class.name}: #{e.message}: #{sql} : #{turntable_shard_name}" - @logger.error message if @logger - exception = translate_exception(e, message) - exception.set_backtrace e.backtrace - raise exception + rescue Encoding::CompatibilityError + message = "#{e.class.name}: #{e.message.force_encoding sql.encoding}: #{sql} : #{turntable_shard_name}" end + + exception = translate_exception(e, message) + exception.set_backtrace e.backtrace + exception end + # @note override for append current shard name + def log(sql, name = "SQL", binds = [], statement_name = nil) + @instrumenter.instrument( + "sql.active_record", + :sql => sql, + :name => name, + :connection_id => object_id, + :statement_name => statement_name, + :binds => binds, + :turntable_shard_name => turntable_shard_name) { yield } + rescue => e + raise translate_exception_class(e, sql) + end + + protected :translate_exception_class, :log + def turntable_shard_name=(name) @turntable_shard_name = name.to_s end From dab21cd653a0f7f2856dd6d1a7d654b6e1671c1e Mon Sep 17 00:00:00 2001 From: gussan Date: Tue, 11 Oct 2016 17:17:56 +0900 Subject: [PATCH 048/125] Shallow indents --- .../activerecord_import_ext.rb | 45 +++++++++---------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb b/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb index 6ebf7a1b..1d279a24 100644 --- a/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb +++ b/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb @@ -2,35 +2,32 @@ module ActiveRecord::Turntable module ActiveRecordExt # activerecord-import extension module ActiverecordImportExt + # @note override for sequencer injection + # @see https://github.com/zdennis/activerecord-import/blob/ba909fed5a4785fe9c7cce89e48e1242bb6804ea/lib/activerecord-import/import.rb#L558-L581 + private def values_sql_for_columns_and_attributes(columns, array_of_attributes) + connection_memo = connection + array_of_attributes.map do |arr| + my_values = arr.each_with_index.map do |val, j| + column = columns[j] - private - - # @note override for sequencer injection - # @see https://github.com/zdennis/activerecord-import/blob/ba909fed5a4785fe9c7cce89e48e1242bb6804ea/lib/activerecord-import/import.rb#L558-L581 - def values_sql_for_columns_and_attributes(columns, array_of_attributes) - connection_memo = connection - array_of_attributes.map do |arr| - my_values = arr.each_with_index.map do |val, j| - column = columns[j] - - # be sure to query sequence_name *last*, only if cheaper tests fail, because it's costly - if val.nil? && column.name == primary_key && !sequence_name.blank? - if sequencer_enabled? - connection_memo.next_sequence_value(sequence_name) - else - connection_memo.next_value_for_sequence(sequence_name) - end - elsif column - if respond_to?(:type_caster) && type_caster.respond_to?(:type_cast_for_database) # Rails 5.0 and higher - connection_memo.quote(type_caster.type_cast_for_database(column.name, val)) - else # Rails 4.2 and higher - connection_memo.quote(column.type_cast_from_user(val), column) - end + # be sure to query sequence_name *last*, only if cheaper tests fail, because it's costly + if val.nil? && column.name == primary_key && !sequence_name.blank? + if sequencer_enabled? + connection_memo.next_sequence_value(sequence_name) + else + connection_memo.next_value_for_sequence(sequence_name) + end + elsif column + if respond_to?(:type_caster) && type_caster.respond_to?(:type_cast_for_database) # Rails 5.0 and higher + connection_memo.quote(type_caster.type_cast_for_database(column.name, val)) + else # Rails 4.2 and higher + connection_memo.quote(column.type_cast_from_user(val), column) end end - "(#{my_values.join(',')})" end + "(#{my_values.join(',')})" end + end end begin From 9aec7741f8c70da07501fcd01ccf247ef9ad7a87 Mon Sep 17 00:00:00 2001 From: gussan Date: Tue, 11 Oct 2016 17:37:26 +0900 Subject: [PATCH 049/125] Update get_records extension --- .../active_record_ext/association.rb | 40 ++++++++++++------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/lib/active_record/turntable/active_record_ext/association.rb b/lib/active_record/turntable/active_record_ext/association.rb index 111dae38..6f5b7013 100644 --- a/lib/active_record/turntable/active_record_ext/association.rb +++ b/lib/active_record/turntable/active_record_ext/association.rb @@ -7,32 +7,44 @@ module Association include ShardingCondition included do - ActiveRecord::Associations::SingularAssociation.prepend(AssociationExt) - ActiveRecord::Associations::CollectionAssociation.prepend(AssociationExt) + ActiveRecord::Associations::SingularAssociation.prepend(SingularAssociationExt) + ActiveRecord::Associations::CollectionAssociation.prepend(CollectionAssociationExt) ActiveRecord::Associations::Builder::Association::VALID_OPTIONS << :foreign_shard_key end - private + # @note Inject to add sharding condition for singular association + module SingularAssociationExt + private + def get_records + # OPTIMIZE: statement caching + if should_use_shard_key? + return turntable_scope(scope).limit(1).records + end - def turntable_scope(scope, bind = nil) - if should_use_shard_key? - scope = scope.where(klass.turntable_shard_key => owner.send(foreign_shard_key)) + super end - scope - end - - module AssociationExt - private + end - # @note Inject to add sharding condition for association + # @note Inject to add sharding condition for collection association + module CollectionAssociationExt + private def get_records - # OPTIMIZE: Use bind values if cachable scope + # OPTIMIZE: statement caching if should_use_shard_key? - return turntable_scope(scope).limit(1).to_a + return turntable_scope(scope).to_a end super end + end + + private + + def turntable_scope(scope, bind = nil) + if should_use_shard_key? + scope = scope.where(klass.turntable_shard_key => owner.send(foreign_shard_key)) + end + scope end end end From 1d9b0cca78f2102751fc5e795857961229c858d8 Mon Sep 17 00:00:00 2001 From: gussan Date: Tue, 11 Oct 2016 18:28:09 +0900 Subject: [PATCH 050/125] Update Persistence --- .../turntable/active_record_ext/persistence.rb | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/lib/active_record/turntable/active_record_ext/persistence.rb b/lib/active_record/turntable/active_record_ext/persistence.rb index a3a74317..64d0a648 100644 --- a/lib/active_record/turntable/active_record_ext/persistence.rb +++ b/lib/active_record/turntable/active_record_ext/persistence.rb @@ -28,12 +28,7 @@ def reload(options = nil) # @note Override to add sharding scope on `touch` def touch(*names, time: nil) - unless persisted? - raise ActiveRecordError, <<-MSG.squish - cannot touch on a new or destroyed record object. Consider using - persisted?, new_record?, or destroyed? before touching - MSG - end + raise ActiveRecordError, "cannot touch on a new record object" unless persisted? time ||= current_time_from_proper_timezone attributes = timestamp_attributes_for_update_in_model @@ -47,6 +42,7 @@ def touch(*names, time: nil) changes[column] = write_attribute(column, time) end + clear_attribute_changes(changes.keys) primary_key = self.class.primary_key scope = if turntable_enabled? && primary_key != self.class.turntable_shard_key.to_s self.class.unscoped.where(self.class.turntable_shard_key => _read_attribute(turntable_shard_key)) @@ -61,7 +57,6 @@ def touch(*names, time: nil) changes[locking_column] = increment_lock end - clear_attribute_changes(changes.keys) result = scope.update_all(changes) == 1 if !result && locking_enabled? From 76fa214ba0496e021e8b69d02e384e9cfcdd0055 Mon Sep 17 00:00:00 2001 From: gussan Date: Tue, 11 Oct 2016 18:28:32 +0900 Subject: [PATCH 051/125] Update SchemaDumper patch --- .../active_record_ext/schema_dumper.rb | 54 ++++++++++++------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/lib/active_record/turntable/active_record_ext/schema_dumper.rb b/lib/active_record/turntable/active_record_ext/schema_dumper.rb index a1f40b25..a59c9df8 100644 --- a/lib/active_record/turntable/active_record_ext/schema_dumper.rb +++ b/lib/active_record/turntable/active_record_ext/schema_dumper.rb @@ -12,34 +12,50 @@ def table(table, stream) tbl = StringIO.new # first dump primary key column - pk = @connection.primary_key(table) + if @connection.respond_to?(:primary_keys) + pk = @connection.primary_keys(table) + pk = pk.first unless pk.size > 1 + else + pk = @connection.primary_key(table) + end tbl.print = if table =~ /\A(.*)_id_seq\z/ - " create_sequence_for #{remove_prefix_and_suffix($1).inspect}" + " create_sequence_for #{remove_prefix_and_suffix(Regexp.last_match(1)).inspect}" else " create_table #{remove_prefix_and_suffix(table).inspect}" end - pkcol = columns.detect { |c| c.name == pk } - if pkcol - if pk != 'id' - tbl.print %Q(, primary_key: "#{pk}") - elsif pkcol.sql_type == 'bigint' - tbl.print ", id: :bigserial" - elsif pkcol.sql_type == 'uuid' - tbl.print ", id: :uuid" - tbl.print %Q(, default: #{pkcol.default_function.inspect}) + + case pk + when String + tbl.print ", primary_key: #{pk.inspect}" unless pk == 'id' + pkcol = columns.detect { |c| c.name == pk } + pkcolspec = @connection.column_spec_for_primary_key(pkcol) + if pkcolspec.present? + pkcolspec.each do |key, value| + tbl.print ", #{key}: #{value}" + end end + when Array + tbl.print ", primary_key: #{pk.inspect}" else tbl.print ", id: false" end tbl.print ", force: :cascade" + + table_options = @connection.table_options(table) + tbl.print ", options: #{table_options.inspect}" unless table_options.blank? + + if comment = @connection.table_comment(table).presence + tbl.print ", comment: #{comment.inspect}" + end + tbl.puts " do |t|" # then dump all non-primary key columns column_specs = columns.map do |column| raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type) next if column.name == pk - @connection.column_spec(column, @types) + @connection.column_spec(column) end.compact # find all migration keys used in this table @@ -53,28 +69,28 @@ def table(table, stream) } # the string we're going to sprintf our values against, with standardized column widths - format_string = lengths.map { |len| "%-#{len}s" } + format_string = lengths.map{ |len| "%-#{len}s" } # find the max length for the 'type' column, which is special - type_length = column_specs.map { |column| column[:type].length }.max + type_length = column_specs.map{ |column| column[:type].length }.max # add column type definition to our format string format_string.unshift " t.%-#{type_length}s " - format_string *= "" + format_string *= '' column_specs.each do |colspec| - values = keys.zip(lengths).map { |key, len| colspec.key?(key) ? colspec[key] + ", " : " " * len } + values = keys.zip(lengths).map{ |key, len| colspec.key?(key) ? colspec[key] + ", " : " " * len } values.unshift colspec[:type] - tbl.print((format_string % values).gsub(/,\s*$/, "")) + tbl.print((format_string % values).gsub(/,\s*$/, '')) tbl.puts end + indexes_in_create(table, tbl) + tbl.puts " end" tbl.puts - indexes(table, tbl) - tbl.rewind stream.print tbl.read rescue => e From 69cc3cee4c2b159ba379c1e4473d7b5b4bda7f5e Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 12 Oct 2016 15:05:11 +0900 Subject: [PATCH 052/125] Remove unsed rack middleware --- README.md | 11 ----------- lib/active_record/turntable.rb | 1 - lib/active_record/turntable/rack.rb | 7 ------- .../turntable/rack/connection_management.rb | 18 ------------------ 4 files changed, 37 deletions(-) delete mode 100644 lib/active_record/turntable/rack.rb delete mode 100644 lib/active_record/turntable/rack/connection_management.rb diff --git a/README.md b/README.md index f0bd2bff..ee3958aa 100644 --- a/README.md +++ b/README.md @@ -432,17 +432,6 @@ Use with_all method: end ``` -### Connection Management - -Rails's ConnectionManagement middleware keeps ActiveRecord's connection during the process is alive, but Turntable keeps more connections. -This may cause flooding max connections on your database. So, we made a middleware that disconnects on each request. - -if you use turntable's ConnectionManagement middleware, add below line to your initializer. - -```ruby -app.middleware.swap ActiveRecord::ConnectionAdapters::ConnectionManagement, ActiveRecord::Turntable::Rack::ConnectionManagement -``` - ### Performance Exception To notice queries causing performance problem, Turntable has follow options. diff --git a/lib/active_record/turntable.rb b/lib/active_record/turntable.rb index 1dce17c1..3aa5f51f 100644 --- a/lib/active_record/turntable.rb +++ b/lib/active_record/turntable.rb @@ -34,7 +34,6 @@ module ActiveRecord::Turntable autoload :SeqShard autoload :Sequencer end - autoload :Rack autoload :Helpers included do diff --git a/lib/active_record/turntable/rack.rb b/lib/active_record/turntable/rack.rb deleted file mode 100644 index d8e11308..00000000 --- a/lib/active_record/turntable/rack.rb +++ /dev/null @@ -1,7 +0,0 @@ -module ActiveRecord::Turntable - module Rack - extend ActiveSupport::Autoload - - autoload :ConnectionManagement - end -end diff --git a/lib/active_record/turntable/rack/connection_management.rb b/lib/active_record/turntable/rack/connection_management.rb deleted file mode 100644 index f0606c6e..00000000 --- a/lib/active_record/turntable/rack/connection_management.rb +++ /dev/null @@ -1,18 +0,0 @@ -module ActiveRecord::Turntable - module Rack - class ConnectionManagement - def initialize(app) - @app = app - end - - def call(env) - @app.call(env) - ensure - unless env.key?("rack.test") - ActiveRecord::Base.connection_handler.clear_all_connections! - ActiveRecord::Base.clear_all_connections! - end - end - end - end -end From a1dfe2649d5b7d08863a1610fae7b42c3b5755fa Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 12 Oct 2016 20:03:33 +0900 Subject: [PATCH 053/125] Update ConnectionHandler patch --- .../turntable/active_record_ext/connection_handler_extension.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/active_record/turntable/active_record_ext/connection_handler_extension.rb b/lib/active_record/turntable/active_record_ext/connection_handler_extension.rb index fb2db0d7..8746e76e 100644 --- a/lib/active_record/turntable/active_record_ext/connection_handler_extension.rb +++ b/lib/active_record/turntable/active_record_ext/connection_handler_extension.rb @@ -11,7 +11,7 @@ def retrieve_connection_pool(spec_name) # A connection was established in an ancestor process that must have # subsequently forked. We can't reuse the connection, but we can copy # the specification and establish a new connection with it. - establish_connection(ancestor_pool.spec.to_hash).tap do |pool| + establish_connection(ancestor_pool.spec).tap do |pool| pool.schema_cache = ancestor_pool.schema_cache if ancestor_pool.schema_cache end else From bdb8b1d3d4044a11509172fa6acb78c2ea6ed2c6 Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 12 Oct 2016 20:04:30 +0900 Subject: [PATCH 054/125] Update dependency notices --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ee3958aa..5862850f 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,12 @@ ActiveRecord::Turntable is a database sharding extension for ActiveRecord. ## Dependencies -activerecord(>=4.0.0) +activerecord(>=5.0.0, <6.0) -if you are using activerecord 3.x, please use activerecord-turntable version 1.x. +If you are using with older activerecord versions, use following versions. + +* activerecord 3.x - use activerecord-turntable version 1.x. +* activerecord 4.x - use activerecord-turntable version 2.x. ## Supported Database From 325a881c3ee092c81016fa262a63dd1647c8ff28 Mon Sep 17 00:00:00 2001 From: gussan Date: Thu, 13 Oct 2016 13:59:11 +0900 Subject: [PATCH 055/125] Fixes schema dumper error --- .../turntable/active_record_ext/schema_dumper.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/active_record/turntable/active_record_ext/schema_dumper.rb b/lib/active_record/turntable/active_record_ext/schema_dumper.rb index a59c9df8..fef65eff 100644 --- a/lib/active_record/turntable/active_record_ext/schema_dumper.rb +++ b/lib/active_record/turntable/active_record_ext/schema_dumper.rb @@ -19,11 +19,11 @@ def table(table, stream) pk = @connection.primary_key(table) end - tbl.print = if table =~ /\A(.*)_id_seq\z/ - " create_sequence_for #{remove_prefix_and_suffix(Regexp.last_match(1)).inspect}" - else - " create_table #{remove_prefix_and_suffix(table).inspect}" - end + if table =~ /\A(.*)_id_seq\z/ + tbl.print " create_sequence_for #{remove_prefix_and_suffix(Regexp.last_match(1)).inspect}" + else + tbl.print " create_table #{remove_prefix_and_suffix(table).inspect}" + end case pk when String From f4d62060d2547e0cc7c9fb029c0e33e6d6b13b43 Mon Sep 17 00:00:00 2001 From: gussan Date: Thu, 13 Oct 2016 15:01:25 +0900 Subject: [PATCH 056/125] Bump version to 3.0.0.alpha1 --- README.md | 12 ++++++------ lib/active_record/turntable/version.rb | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 5862850f..612a59cc 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Currently supports mysql only. Add to Gemfile: ```ruby -gem 'activerecord-turntable', '~> 2.1.1' +gem 'activerecord-turntable', '~> 3.0.0.alpha1' ``` Run a bundle install: @@ -139,7 +139,7 @@ Edit turntable.yml and database.yml. See below example config. database: sample_app_user3_development ``` -### Example Migration +### Example Migration Generate a model: @@ -285,7 +285,7 @@ First, add configuration to turntable.yml and database.yml seq: user_seq: # <-- sequencer name seq_type: mysql # <-- sequencer type - connection: user_seq_1 # <-- sequencer database connection + connection: user_seq_1 # <-- sequencer database connection ``` Add below to the migration: @@ -372,8 +372,8 @@ end transaction helper to execute transaction to all shards in the cluster: ```ruby -User.user_cluster_transaction do - # Transaction is opened all shards in "user_cluster" +User.user_cluster_transaction do + # Transaction is opened all shards in "user_cluster" end ``` @@ -440,7 +440,7 @@ Use with_all method: To notice queries causing performance problem, Turntable has follow options. * raise\_on\_not\_specified\_shard\_query - raises on queries execute on all shards -* raise\_on\_not\_specified\_shard\_update - raises on updates executed on all shards +* raise\_on\_not\_specified\_shard\_update - raises on updates executed on all shards Add to turntable.yml: diff --git a/lib/active_record/turntable/version.rb b/lib/active_record/turntable/version.rb index a49eb8ed..fa99f75a 100644 --- a/lib/active_record/turntable/version.rb +++ b/lib/active_record/turntable/version.rb @@ -1,5 +1,5 @@ module ActiveRecord module Turntable - VERSION = "3.0.0.alpha".freeze + VERSION = "3.0.0.alpha1".freeze end end From 3a8ddedc385567beb03acd18811bc92699ede648 Mon Sep 17 00:00:00 2001 From: gussan Date: Sun, 1 Jan 2017 20:03:59 +0900 Subject: [PATCH 057/125] Upgrade rspec to 3.5 --- activerecord-turntable.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activerecord-turntable.gemspec b/activerecord-turntable.gemspec index f6d388e2..6e31e085 100644 --- a/activerecord-turntable.gemspec +++ b/activerecord-turntable.gemspec @@ -43,7 +43,7 @@ Gem::Specification.new do |spec| spec.add_development_dependency "pry-byebug" spec.add_development_dependency "rack" spec.add_development_dependency "rake" - spec.add_development_dependency "rspec", "~> 3.1.0" + spec.add_development_dependency "rspec", "~> 3.5.0" spec.add_development_dependency "rspec-collection_matchers" spec.add_development_dependency "rspec-its" spec.add_development_dependency "rubocop" From 8b33922cf95b6866962fb49fa9d19c42387df8ad Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 2 Jan 2017 11:24:24 +0900 Subject: [PATCH 058/125] Update travis target ruby versions --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3ce47eca..01edd7d0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: ruby rvm: - - 2.2.5 - - 2.3.1 + - 2.2.6 + - 2.3.3 - ruby-head gemfile: - gemfiles/rails5_0.gemfile From 0a956fb705bbeab86056c9b7ba508e88344d4160 Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 2 Jan 2017 11:24:53 +0900 Subject: [PATCH 059/125] Update target rails5 version --- gemfiles/rails5_0.gemfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gemfiles/rails5_0.gemfile b/gemfiles/rails5_0.gemfile index fcfe1be0..fb4a7693 100644 --- a/gemfiles/rails5_0.gemfile +++ b/gemfiles/rails5_0.gemfile @@ -1,6 +1,6 @@ source "https://rubygems.org" -gem "activerecord", "5.0.0.1" -gem "activesupport", "5.0.0.1" +gem "activerecord", "5.0.1" +gem "activesupport", "5.0.1" gemspec :path => '../' From a525956fc8bdc54d3f3aa84bbf7717f08e2b518d Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 2 Jan 2017 22:53:55 +0900 Subject: [PATCH 060/125] Update rails version to 5.0.1 --- Gemfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index be420c57..719abbd0 100644 --- a/Gemfile +++ b/Gemfile @@ -2,5 +2,5 @@ source "https://rubygems.org" gemspec -gem "activerecord", "5.0.0.1" -gem "activesupport", "5.0.0.1" +gem "activerecord", "~> 5.0.1" +gem "activesupport", "~> 5.0.1" From f33e7926361fa0e14dd7db395e9c1d3824db77af Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 28 Dec 2016 16:40:10 +0900 Subject: [PATCH 061/125] Fix to propagate shard conditions to `AssociationRelation` too When calling `@user.tasks.find_by(name: 'xxx')` before: SELECT `tasks`.* FROM `tasks` WHERE `tasks`.`name` = "xxx" # raises CannotSpecifyShardError after: SELECT `tasks`.* FROM `tasks` WHERE `tasks`.`user_id` = 1 AND `tasks`.`name` = "xxx" --- .../turntable/active_record_ext.rb | 2 +- .../active_record_ext/association.rb | 45 +++++-------------- .../active_record_ext/association_spec.rb | 15 +++++-- 3 files changed, 23 insertions(+), 39 deletions(-) diff --git a/lib/active_record/turntable/active_record_ext.rb b/lib/active_record/turntable/active_record_ext.rb index eebf178e..2dbf7d1e 100644 --- a/lib/active_record/turntable/active_record_ext.rb +++ b/lib/active_record/turntable/active_record_ext.rb @@ -30,7 +30,7 @@ module ActiveRecordExt ActiveRecord::Migration.include(ActiveRecord::Turntable::Migration) ActiveRecord::ConnectionAdapters::ConnectionHandler.prepend(ConnectionHandlerExtension) ActiveRecord::Associations::Preloader::Association.prepend(AssociationPreloader) - ActiveRecord::Associations::Association.include(Association) + ActiveRecord::Associations::Association.prepend(Association) require "active_record/turntable/active_record_ext/fixtures" require "active_record/turntable/active_record_ext/migration_proxy" require "active_record/turntable/active_record_ext/activerecord_import_ext" diff --git a/lib/active_record/turntable/active_record_ext/association.rb b/lib/active_record/turntable/active_record_ext/association.rb index 6f5b7013..e86f5bef 100644 --- a/lib/active_record/turntable/active_record_ext/association.rb +++ b/lib/active_record/turntable/active_record_ext/association.rb @@ -3,49 +3,24 @@ module ActiveRecord::Turntable module ActiveRecordExt module Association - extend ActiveSupport::Concern include ShardingCondition - included do - ActiveRecord::Associations::SingularAssociation.prepend(SingularAssociationExt) - ActiveRecord::Associations::CollectionAssociation.prepend(CollectionAssociationExt) + def self.prepended(mod) ActiveRecord::Associations::Builder::Association::VALID_OPTIONS << :foreign_shard_key end - # @note Inject to add sharding condition for singular association - module SingularAssociationExt - private - def get_records - # OPTIMIZE: statement caching - if should_use_shard_key? - return turntable_scope(scope).limit(1).records - end + protected - super - end - end - - # @note Inject to add sharding condition for collection association - module CollectionAssociationExt - private - def get_records - # OPTIMIZE: statement caching - if should_use_shard_key? - return turntable_scope(scope).to_a - end + # @note Override to pass shard key conditions + def target_scope + return super unless should_use_shard_key? - super - end + scope = klass.where( + klass.turntable_shard_key => + owner.send(foreign_shard_key) + ) + super.merge!(scope) end - - private - - def turntable_scope(scope, bind = nil) - if should_use_shard_key? - scope = scope.where(klass.turntable_shard_key => owner.send(foreign_shard_key)) - end - scope - end end end end diff --git a/spec/active_record/turntable/active_record_ext/association_spec.rb b/spec/active_record/turntable/active_record_ext/association_spec.rb index 8c8b1e69..a67458ed 100644 --- a/spec/active_record/turntable/active_record_ext/association_spec.rb +++ b/spec/active_record/turntable/active_record_ext/association_spec.rb @@ -47,11 +47,20 @@ ActiveRecord::Base.turntable_config.instance_variable_get(:@config)[:raise_on_not_specified_shard_query] = true end let(:cards_user) { CardsUser.where(user: user).first } + let(:cards_users_history) { cards_users_histories.find { |history| history.user_id == user.id } } context "associated objects has same turntable_key" do - subject { cards_user.cards_users_histories.to_a } - it { expect { subject }.to_not raise_error } - it { is_expected.to include(*cards_users_histories.select { |history| history.cards_user_id == cards_user.id }) } + context "AssociationRelation#to_a" do + subject { cards_user.cards_users_histories.to_a } + it { expect { subject }.to_not raise_error } + it { is_expected.to include(*cards_users_histories.select { |history| history.cards_user_id == cards_user.id }) } + end + + context "AssociationRelation#where" do + subject { cards_user.cards_users_histories.where(id: cards_users_history.id).to_a } + it { expect { subject }.to_not raise_error } + it { is_expected.to include(cards_users_history) } + end end context "associated objects has different turntable_key" do From 536cb67eabe74049dde7fa578edffa485f601f22 Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 2 Jan 2017 23:12:17 +0900 Subject: [PATCH 062/125] Preparing for 3.0.0.alpha2 release --- CHANGELOG.md | 11 +++++++++-- lib/active_record/turntable/version.rb | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index efb50a56..08e93279 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,17 @@ -## activerecord-turntable 3.0.0.alpha (unreleased) ## +## activerecord-turntable 3.0.0.alpha2 ## + +### Improvement + +* Fix to propagate shard conditions to `AssociationRelation` too + +## activerecord-turntable 3.0.0.alpha1 ## + +### Major Changes * Rails5 compatibility * Minimum ruby requirement version is `2.2.2` * Rails 4.x support has been dropped. - ## activerecord-turntable 2.3.3 ## ### Bugfix diff --git a/lib/active_record/turntable/version.rb b/lib/active_record/turntable/version.rb index fa99f75a..71f66d04 100644 --- a/lib/active_record/turntable/version.rb +++ b/lib/active_record/turntable/version.rb @@ -1,5 +1,5 @@ module ActiveRecord module Turntable - VERSION = "3.0.0.alpha1".freeze + VERSION = "3.0.0.alpha2".freeze end end From 78b90abe1389685a49dfc7d2b770392a2b521ac5 Mon Sep 17 00:00:00 2001 From: sue445 Date: Tue, 3 Jan 2017 00:00:21 +0900 Subject: [PATCH 063/125] CI against ruby 2.4.0 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 01edd7d0..f71f93a2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,7 @@ language: ruby rvm: - 2.2.6 - 2.3.3 + - 2.4.0 - ruby-head gemfile: - gemfiles/rails5_0.gemfile From d1703155fdafed148ac84d8f5df0a4080e8fd4b8 Mon Sep 17 00:00:00 2001 From: gussan Date: Tue, 3 Jan 2017 13:07:51 +0900 Subject: [PATCH 064/125] Disable statement cache when adding shard conditions automatically --- .../active_record_ext/association.rb | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/active_record/turntable/active_record_ext/association.rb b/lib/active_record/turntable/active_record_ext/association.rb index e86f5bef..6f32604d 100644 --- a/lib/active_record/turntable/active_record_ext/association.rb +++ b/lib/active_record/turntable/active_record_ext/association.rb @@ -11,16 +11,22 @@ def self.prepended(mod) protected - # @note Override to pass shard key conditions - def target_scope - return super unless should_use_shard_key? + # @note Override to pass shard key conditions + def target_scope + return super unless should_use_shard_key? - scope = klass.where( - klass.turntable_shard_key => - owner.send(foreign_shard_key) - ) - super.merge!(scope) - end + scope = klass.where( + klass.turntable_shard_key => + owner.send(foreign_shard_key) + ) + super.merge!(scope) + end + + private + + def skip_statement_cache? + super || should_use_shard_key? + end end end end From f9d153b33a280ab3f6512e970745843f55c7d1e9 Mon Sep 17 00:00:00 2001 From: gussan Date: Tue, 3 Jan 2017 13:11:13 +0900 Subject: [PATCH 065/125] Preparing for 3.0.0.alpha3 release --- CHANGELOG.md | 6 ++++++ lib/active_record/turntable/version.rb | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08e93279..07f11fe2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## activerecord-turntable 3.0.0.alpha3 ## + +### Bugfix + +* Disable statement cache when adding shard conditions automatically + ## activerecord-turntable 3.0.0.alpha2 ## ### Improvement diff --git a/lib/active_record/turntable/version.rb b/lib/active_record/turntable/version.rb index 71f66d04..e6cab3d1 100644 --- a/lib/active_record/turntable/version.rb +++ b/lib/active_record/turntable/version.rb @@ -1,5 +1,5 @@ module ActiveRecord module Turntable - VERSION = "3.0.0.alpha2".freeze + VERSION = "3.0.0.alpha3".freeze end end From 31f9fb1784e2a8a184be2df996de2b50b05430fe Mon Sep 17 00:00:00 2001 From: gussan Date: Fri, 6 Jan 2017 20:13:21 +0900 Subject: [PATCH 066/125] Update `SchemaDumper` patch Fixes `options` hash is incorrectly nested. --- .../active_record_ext/schema_dumper.rb | 84 ++----------------- .../active_record_ext/schema_dumper_spec.rb | 26 ++++++ spec/support/turntable_helper.rb | 2 +- 3 files changed, 35 insertions(+), 77 deletions(-) create mode 100644 spec/active_record/turntable/active_record_ext/schema_dumper_spec.rb diff --git a/lib/active_record/turntable/active_record_ext/schema_dumper.rb b/lib/active_record/turntable/active_record_ext/schema_dumper.rb index fef65eff..ad95a160 100644 --- a/lib/active_record/turntable/active_record_ext/schema_dumper.rb +++ b/lib/active_record/turntable/active_record_ext/schema_dumper.rb @@ -2,93 +2,25 @@ module ActiveRecord::Turntable module ActiveRecordExt module SchemaDumper + SEQUENCE_TABLE_REGEXP = /\A(.*)_id_seq\z/ private - # @note Override to dump database sequencer method def table(table, stream) - columns = @connection.columns(table) + unless matchdata = table.match(SEQUENCE_TABLE_REGEXP) + return super + end + begin tbl = StringIO.new - # first dump primary key column - if @connection.respond_to?(:primary_keys) - pk = @connection.primary_keys(table) - pk = pk.first unless pk.size > 1 - else - pk = @connection.primary_key(table) - end - - if table =~ /\A(.*)_id_seq\z/ - tbl.print " create_sequence_for #{remove_prefix_and_suffix(Regexp.last_match(1)).inspect}" - else - tbl.print " create_table #{remove_prefix_and_suffix(table).inspect}" - end - - case pk - when String - tbl.print ", primary_key: #{pk.inspect}" unless pk == 'id' - pkcol = columns.detect { |c| c.name == pk } - pkcolspec = @connection.column_spec_for_primary_key(pkcol) - if pkcolspec.present? - pkcolspec.each do |key, value| - tbl.print ", #{key}: #{value}" - end - end - when Array - tbl.print ", primary_key: #{pk.inspect}" - else - tbl.print ", id: false" - end + tbl.print " create_sequence_for #{remove_prefix_and_suffix(matchdata[1]).inspect}" tbl.print ", force: :cascade" table_options = @connection.table_options(table) - tbl.print ", options: #{table_options.inspect}" unless table_options.blank? - - if comment = @connection.table_comment(table).presence - tbl.print ", comment: #{comment.inspect}" + if table_options.present? + tbl.print ", #{format_options(table_options)}" end - - tbl.puts " do |t|" - - # then dump all non-primary key columns - column_specs = columns.map do |column| - raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type) - next if column.name == pk - @connection.column_spec(column) - end.compact - - # find all migration keys used in this table - keys = @connection.migration_keys - - # figure out the lengths for each column based on above keys - lengths = keys.map { |key| - column_specs.map { |spec| - spec[key] ? spec[key].length + 2 : 0 - }.max - } - - # the string we're going to sprintf our values against, with standardized column widths - format_string = lengths.map{ |len| "%-#{len}s" } - - # find the max length for the 'type' column, which is special - type_length = column_specs.map{ |column| column[:type].length }.max - - # add column type definition to our format string - format_string.unshift " t.%-#{type_length}s " - - format_string *= '' - - column_specs.each do |colspec| - values = keys.zip(lengths).map{ |key, len| colspec.key?(key) ? colspec[key] + ", " : " " * len } - values.unshift colspec[:type] - tbl.print((format_string % values).gsub(/,\s*$/, '')) - tbl.puts - end - - indexes_in_create(table, tbl) - - tbl.puts " end" tbl.puts tbl.rewind diff --git a/spec/active_record/turntable/active_record_ext/schema_dumper_spec.rb b/spec/active_record/turntable/active_record_ext/schema_dumper_spec.rb new file mode 100644 index 00000000..06fa8e0c --- /dev/null +++ b/spec/active_record/turntable/active_record_ext/schema_dumper_spec.rb @@ -0,0 +1,26 @@ +require "spec_helper" + +describe ActiveRecord::Turntable::ActiveRecordExt::SchemaDumper do + before(:all) do + reload_turntable!(File.join(File.dirname(__FILE__), "../../../config/turntable.yml")) + ActiveRecord::SchemaDumper.prepend(ActiveRecord::Turntable::ActiveRecordExt::SchemaDumper) + end + + before(:each) do + establish_connection_to(:test) + end + + def dump_schema + stream = StringIO.new + ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream) + stream.string + end + + context "#dump" do + subject { dump_schema } + it { is_expected.to match(/create_table "users", force: :cascade, options: ".*?"\sdo\s\|t\|$/) } + it { is_expected.to match(/create_sequence_for "users", force: :cascade, options: /) } + it { is_expected.not_to match(/create_table "users_id_seq"/) } + it { is_expected.not_to match(/create_sequence_for "users_id_seq".*?do/) } + end +end diff --git a/spec/support/turntable_helper.rb b/spec/support/turntable_helper.rb index d3a19a12..10de2c63 100644 --- a/spec/support/turntable_helper.rb +++ b/spec/support/turntable_helper.rb @@ -19,7 +19,7 @@ def establish_connection_to(env = :test) def truncate_shard ActiveRecord::Base.descendants.each do |klass| - next if klass.abstract_class? + next if klass.abstract_class? || klass == ActiveRecord::SchemaMigration klass.delete_all end end From 6f9abd8cfb19f8acde97a39f508a012662e02a22 Mon Sep 17 00:00:00 2001 From: misoobu Date: Sun, 22 Jan 2017 00:56:56 +0900 Subject: [PATCH 067/125] Follow the activerecord-import This changes include a performance improvement: https://github.com/zdennis/activerecord-import/commit/4b1e84308c5eecafd9c90b3df6c909bfb106e125 --- .../active_record_ext/activerecord_import_ext.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb b/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb index 1d279a24..8d9106b8 100644 --- a/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb +++ b/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb @@ -3,9 +3,11 @@ module ActiveRecordExt # activerecord-import extension module ActiverecordImportExt # @note override for sequencer injection - # @see https://github.com/zdennis/activerecord-import/blob/ba909fed5a4785fe9c7cce89e48e1242bb6804ea/lib/activerecord-import/import.rb#L558-L581 + # @see https://github.com/zdennis/activerecord-import/blob/b325ebb644160a09db6e269e414f33561cb21272/lib/activerecord-import/import.rb#L661-L689 private def values_sql_for_columns_and_attributes(columns, array_of_attributes) connection_memo = connection + type_caster_memo = type_caster if respond_to?(:type_caster) + array_of_attributes.map do |arr| my_values = arr.each_with_index.map do |val, j| column = columns[j] @@ -18,8 +20,8 @@ module ActiverecordImportExt connection_memo.next_value_for_sequence(sequence_name) end elsif column - if respond_to?(:type_caster) && type_caster.respond_to?(:type_cast_for_database) # Rails 5.0 and higher - connection_memo.quote(type_caster.type_cast_for_database(column.name, val)) + if defined?(type_caster_memo) && type_caster_memo.respond_to?(:type_cast_for_database) # Rails 5.0 and higher + connection_memo.quote(type_caster_memo.type_cast_for_database(column.name, val)) else # Rails 4.2 and higher connection_memo.quote(column.type_cast_from_user(val), column) end From dd955917f64cda8c88c7652459817751da5c44f4 Mon Sep 17 00:00:00 2001 From: misoobu Date: Sun, 22 Jan 2017 01:11:36 +0900 Subject: [PATCH 068/125] Re-enable the `AR::LogSubscriber::IGNORE_PAYLOAD_NAMES` The definition was used until version 2.x, but the commit below made that unused. https://github.com/drecom/activerecord-turntable/commit/2ad357dab40aedde25d12838e208f56442f9f555 --- Before: ``` irb(main):001:0> User.create SCHEMA [Shard: master] (0.5ms) SELECT table_name FROM information_schema.tables WHERE table_schema = 'sample_app_development' SCHEMA [Shard: master] (4.9ms) SELECT column_name FROM information_schema.key_column_usage WHERE constraint_name = 'PRIMARY' AND table_schema = 'sample_app_development' AND table_name = 'users' ORDER BY ordinal_position SCHEMA [Shard: master] (0.4ms) SHOW FULL FIELDS FROM `users` [Shard: user_seq] (2.1ms) UPDATE `users_id_seq` SET id=LAST_INSERT_ID(id+1) [Shard: user_seq] (0.2ms) SELECT LAST_INSERT_ID() [Shard: user_shard_1] (0.1ms) BEGIN [ActiveRecord::Turntable] Sending method: insert, sql: #, shards: ["user_shard_1"] SQL [Shard: user_shard_1] (1.4ms) INSERT INTO `users` (`id`, `created_at`, `updated_at`) VALUES (3, '2017-01-21 17:18:18', '2017-01-21 17:18:18') [Shard: user_shard_1] (5.8ms) COMMIT => # ``` After: ``` irb(main):001:0> User.create [Shard: user_seq] (2.6ms) UPDATE `users_id_seq` SET id=LAST_INSERT_ID(id+1) [Shard: user_seq] (0.2ms) SELECT LAST_INSERT_ID() [Shard: user_shard_1] (0.2ms) BEGIN [ActiveRecord::Turntable] Sending method: insert, sql: #, shards: ["user_shard_1"] SQL [Shard: user_shard_1] (15.5ms) INSERT INTO `users` (`id`, `created_at`, `updated_at`) VALUES (4, '2017-01-21 17:28:57', '2017-01-21 17:28:57') [Shard: user_shard_1] (6.1ms) COMMIT => # ``` --- .../active_record_ext/log_subscriber.rb | 6 +++ .../active_record_ext/log_subscriber_spec.rb | 47 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 spec/active_record/turntable/active_record_ext/log_subscriber_spec.rb diff --git a/lib/active_record/turntable/active_record_ext/log_subscriber.rb b/lib/active_record/turntable/active_record_ext/log_subscriber.rb index 5f23f509..f1f2c488 100644 --- a/lib/active_record/turntable/active_record_ext/log_subscriber.rb +++ b/lib/active_record/turntable/active_record_ext/log_subscriber.rb @@ -6,6 +6,12 @@ module LogSubscriber # @note prepend to add shard name logging def sql(event) payload = event.payload + + if self.class::IGNORE_PAYLOAD_NAMES.include?(payload[:name]) + self.class.runtime += event.duration + return + end + if payload[:turntable_shard_name] payload[:name] = "#{payload[:name]} [Shard: #{payload[:turntable_shard_name]}]" end diff --git a/spec/active_record/turntable/active_record_ext/log_subscriber_spec.rb b/spec/active_record/turntable/active_record_ext/log_subscriber_spec.rb new file mode 100644 index 00000000..ed9b10e4 --- /dev/null +++ b/spec/active_record/turntable/active_record_ext/log_subscriber_spec.rb @@ -0,0 +1,47 @@ +require "spec_helper" + +describe ActiveRecord::Turntable::ActiveRecordExt::LogSubscriber do + before(:all) do + reload_turntable!(File.join(File.dirname(__FILE__), "../../../config/turntable.yml")) + end + + before(:each) do + establish_connection_to + end + + class TestLogSubscriber < ActiveRecord::LogSubscriber + attr_reader :debugs + + def initialize + @debugs = [] + super + end + + def debug(message) + @debugs << message + end + end + + TestEvent = Struct.new(:payload) do + def sql + "foo" + end + + def duration + 0 + end + end + + describe "#sql" do + it "ignore SCHEMA log" do + subscriber = TestLogSubscriber.new + expect(subscriber.debugs.length).to eq 0 + + subscriber.sql(TestEvent.new(name: "bar", turntable_shard_name: "shard_1")) + expect(subscriber.debugs.length).to eq 1 + + subscriber.sql(TestEvent.new(name: "SCHEMA", turntable_shard_name: "shard_1")) + expect(subscriber.debugs.length).to eq 1 + end + end +end From 6f6e342b8e7819275c28a480638a4506be51a75a Mon Sep 17 00:00:00 2001 From: gussan Date: Thu, 2 Feb 2017 14:55:59 +0900 Subject: [PATCH 069/125] Add submodule `rails/rails` --- .gitmodules | 3 +++ spec/rails | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 spec/rails diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..29df2cd5 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "spec/rails"] + path = spec/rails + url = https://github.com/rails/rails.git diff --git a/spec/rails b/spec/rails new file mode 160000 index 00000000..65bf1c60 --- /dev/null +++ b/spec/rails @@ -0,0 +1 @@ +Subproject commit 65bf1c60053e727835e06392d27a2fb49665484c From 7149cf58e611550a2dfca1bf6cd1ce2eecf65401 Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 8 Feb 2017 14:28:10 +0900 Subject: [PATCH 070/125] Run activerecord unit tests --- .travis.yml | 16 ++++++++---- Rakefile | 39 +++++++++++++++++++++++++++++ activerecord-turntable.gemspec | 7 ++++++ ci/run-tests.sh | 2 ++ ci/setup-tests.sh | 2 ++ spec/activerecord_helper.rb | 6 +++++ spec/config/activerecord_config.yml | 13 ++++++++++ 7 files changed, 80 insertions(+), 5 deletions(-) create mode 100755 ci/run-tests.sh create mode 100755 ci/setup-tests.sh create mode 100644 spec/activerecord_helper.rb create mode 100644 spec/config/activerecord_config.yml diff --git a/.travis.yml b/.travis.yml index f71f93a2..eb71f305 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,16 +1,22 @@ language: ruby +sudo: false + +cache: + bundler: true + rvm: - 2.2.6 - 2.3.3 - 2.4.0 - ruby-head + gemfile: - gemfiles/rails5_0.gemfile -before_script: - - bundle exec rake turntable:db:reset -script: bundle exec rake spec + +before_install: gem update --system +before_script: ci/setup-tests.sh +script: ci/run-tests.sh + matrix: allow_failures: - rvm: ruby-head -sudo: false -cache: bundler diff --git a/Rakefile b/Rakefile index 74eee64f..4aad9da2 100644 --- a/Rakefile +++ b/Rakefile @@ -123,4 +123,43 @@ namespace :turntable do desc "reset turntable test databases" task :reset => ["turntable:db:drop", "turntable:db:create", "turntable:db:migrate"] end + + namespace :activerecord do + task(:env) do + ENV['ARCONFIG'] ||= File.expand_path('spec/config/activerecord_config.yml', __dir__) + ENV['ARVERSION'] ||= if ActiveRecord.gem_version.prerelease? + "master" + else + "v#{ActiveRecord.gem_version}" + end + end + + namespace :setup do + task :rails => :env do + system(*%w|git submodule update --init|) + Dir.chdir("spec/rails") do + system(*%W|git checkout #{ENV['ARVERSION']}|) + end + FileUtils.cp_r("spec/rails/activerecord/test", ".") + FileUtils.cp_r("spec/rails/activerecord/Rakefile", "activerecord.rake") + File.open("test/cases/helper.rb", "a") do |f| + f << "require '#{File.expand_path("spec/activerecord_helper", __dir__)}'" + end + end + + task :db => :rails do + system(*%w|bundle exec rake -f activerecord.rake db:mysql:rebuild|) + end + end + + desc "setup activerecord test" + task :setup => ["setup:rails", "setup:db"] + + task :test => :env do + desc "run unit tests on activerecord" + unless system(*%w|bundle exec rake -f activerecord.rake test:mysql2|) + exit(1) + end + end + end end diff --git a/activerecord-turntable.gemspec b/activerecord-turntable.gemspec index 6e31e085..6205685f 100644 --- a/activerecord-turntable.gemspec +++ b/activerecord-turntable.gemspec @@ -50,4 +50,11 @@ Gem::Specification.new do |spec| spec.add_development_dependency "rubocop-rspec" spec.add_development_dependency "timecop" spec.add_development_dependency "webmock" + + # activerecord testing dependencies + spec.add_development_dependency "actionview" + spec.add_development_dependency "bcrypt", "~> 3.1.11" + spec.add_development_dependency "minitest", "< 5.3.4" + spec.add_development_dependency "mocha", "~> 0.14" + spec.add_development_dependency "sqlite3", "~> 1.3.6" end diff --git a/ci/run-tests.sh b/ci/run-tests.sh new file mode 100755 index 00000000..c9610667 --- /dev/null +++ b/ci/run-tests.sh @@ -0,0 +1,2 @@ +#!/bin/bash +bundle exec rake spec turntable:activerecord:test diff --git a/ci/setup-tests.sh b/ci/setup-tests.sh new file mode 100755 index 00000000..16926cb6 --- /dev/null +++ b/ci/setup-tests.sh @@ -0,0 +1,2 @@ +#!/bin/bash +bundle exec rake turntable:db:reset turntable:activerecord:setup diff --git a/spec/activerecord_helper.rb b/spec/activerecord_helper.rb new file mode 100644 index 00000000..6ac4e758 --- /dev/null +++ b/spec/activerecord_helper.rb @@ -0,0 +1,6 @@ +$LOAD_PATH.unshift File.expand_path("../lib", __dir__) +require 'active_record' +require 'activerecord-turntable' +ActiveRecord::Base.include(ActiveRecord::Turntable) +require "active_record/turntable/active_record_ext/database_tasks" +warn "[turntable] turntable injected." diff --git a/spec/config/activerecord_config.yml b/spec/config/activerecord_config.yml new file mode 100644 index 00000000..ea8d1377 --- /dev/null +++ b/spec/config/activerecord_config.yml @@ -0,0 +1,13 @@ +default_connection: <%= defined?(JRUBY_VERSION) ? 'jdbcsqlite3' : 'sqlite3' %> + +with_manual_interventions: false + +connections: + mysql2: + arunit: + username: root + encoding: utf8 + collation: utf8_unicode_ci + arunit2: + username: root + encoding: utf8 From 6235ae0557eb83fc4e6d00865a8fbd171ce21049 Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 8 Feb 2017 14:29:12 +0900 Subject: [PATCH 071/125] Update activerecord/fixtures patches --- .../turntable/active_record_ext/fixtures.rb | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/lib/active_record/turntable/active_record_ext/fixtures.rb b/lib/active_record/turntable/active_record_ext/fixtures.rb index dc47a28b..32a2ef47 100644 --- a/lib/active_record/turntable/active_record_ext/fixtures.rb +++ b/lib/active_record/turntable/active_record_ext/fixtures.rb @@ -24,7 +24,7 @@ def self.create_fixtures(fixtures_directory, fixture_set_names, class_names = {} fixture_sets = files_to_read.map do |fs_name| klass = class_names[fs_name] - conn = klass.is_a?(String) ? connection : klass.connection + conn = klass ? klass.connection : connection fixtures_map[fs_name] = new( # ActiveRecord::FixtureSet.new conn, fs_name, @@ -35,12 +35,16 @@ def self.create_fixtures(fixtures_directory, fixture_set_names, class_names = {} update_all_loaded_fixtures fixtures_map ActiveRecord::Base.force_transaction_all_shards!(requires_new: true) do + deleted_tables = Hash.new { |h, k| h[k] = Set.new } fixture_sets.each do |fs| conn = fs.model_class.respond_to?(:connection) ? fs.model_class.connection : connection table_rows = fs.table_rows table_rows.each_key do |table| - conn.delete "DELETE FROM #{conn.quote_table_name(table)}", "Fixture Delete" + unless deleted_tables[conn].include? table + conn.delete "DELETE FROM #{conn.quote_table_name(table)}", "Fixture Delete" + end + deleted_tables[conn] << table end table_rows.each do |fixture_set_name, rows| @@ -48,11 +52,9 @@ def self.create_fixtures(fixtures_directory, fixture_set_names, class_names = {} conn.insert_fixture(row, fixture_set_name) end end - end - # Cap primary key sequences to max(pk). - if connection.respond_to?(:reset_pk_sequence!) - fixture_sets.each do |fs| + # Cap primary key sequences to max(pk). + if connection.respond_to?(:reset_pk_sequence!) connection.reset_pk_sequence!(fs.table_name) end end @@ -66,11 +68,7 @@ def self.create_fixtures(fixtures_directory, fixture_set_names, class_names = {} end module TestFixtures - include ActiveRecord::Turntable::Util - def setup_fixtures(config = ActiveRecord::Base) - return if ActiveRecord::Base.configurations.blank? - if pre_loaded_fixtures && !use_transactional_fixtures raise "pre_loaded_fixtures requires use_transactional_fixtures" end @@ -94,13 +92,13 @@ def setup_fixtures(config = ActiveRecord::Base) end # Load fixtures for every test. else - ActiveRecord::Fixtures.reset_cache + ActiveRecord::FixtureSet.reset_cache @@already_loaded_fixtures[self.class] = nil @loaded_fixtures = load_fixtures(config) end # Instantiate fixtures for every test if requested. - instantiate_fixtures(config) if use_instantiated_fixtures + instantiate_fixtures if use_instantiated_fixtures end def enlist_fixture_connections From 534f19da75681221d45d75aafe8a409b8e6b5aef Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 8 Feb 2017 14:32:06 +0900 Subject: [PATCH 072/125] Fixes const missing --- .../turntable/active_record_ext/persistence.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/active_record/turntable/active_record_ext/persistence.rb b/lib/active_record/turntable/active_record_ext/persistence.rb index 64d0a648..c1b1fb4c 100644 --- a/lib/active_record/turntable/active_record_ext/persistence.rb +++ b/lib/active_record/turntable/active_record_ext/persistence.rb @@ -28,7 +28,7 @@ def reload(options = nil) # @note Override to add sharding scope on `touch` def touch(*names, time: nil) - raise ActiveRecordError, "cannot touch on a new record object" unless persisted? + raise ActiveRecord::ActiveRecordError, "cannot touch on a new record object" unless persisted? time ||= current_time_from_proper_timezone attributes = timestamp_attributes_for_update_in_model @@ -71,8 +71,8 @@ def touch(*names, time: nil) # @note Override to add sharding scope on `update_columns` def update_columns(attributes) - raise ActiveRecordError, "cannot update a new record" if new_record? - raise ActiveRecordError, "cannot update a destroyed record" if destroyed? + raise ActiveRecord::ActiveRecordError, "cannot update a new record" if new_record? + raise ActiveRecord::ActiveRecordError, "cannot update a destroyed record" if destroyed? attributes.each_key do |key| verify_readonly_attribute(key.to_s) From 440dabfe25f6f43a4c4b1c4b17a3eb8077ef72d7 Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 8 Feb 2017 14:35:25 +0900 Subject: [PATCH 073/125] Follow activerecord's interface changes --- .../turntable/active_record_ext/database_tasks.rb | 12 ++++++------ lib/active_record/turntable/migration.rb | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/active_record/turntable/active_record_ext/database_tasks.rb b/lib/active_record/turntable/active_record_ext/database_tasks.rb index 5dcd0ed5..c5b69ef4 100644 --- a/lib/active_record/turntable/active_record_ext/database_tasks.rb +++ b/lib/active_record/turntable/active_record_ext/database_tasks.rb @@ -18,7 +18,7 @@ def drop_all_turntable_cluster end def create_current_turntable_cluster(environment = env) - each_current_turntable_cluster_configuration(true, environment) { |_name, configuration| + each_current_turntable_cluster_configuration(environment) { |_name, configuration| puts "[turntable] *** executing to database: #{configuration['database']}" create configuration } @@ -26,14 +26,14 @@ def create_current_turntable_cluster(environment = env) end def drop_current_turntable_cluster(environment = env) - each_current_turntable_cluster_configuration(true, environment) { |_name, configuration| + each_current_turntable_cluster_configuration(environment) { |_name, configuration| puts "[turntable] *** executing to database: #{configuration['database']}" drop configuration } end - def each_current_turntable_cluster_connected(with_test = false, environment = env) - each_current_turntable_cluster_configuration(with_test, environment) do |name, configuration| + def each_current_turntable_cluster_connected(environment) + each_current_turntable_cluster_configuration(environment) do |name, configuration| ActiveRecord::Base.clear_active_connections! ActiveRecord::Base.establish_connection(configuration) ActiveRecord::Migration.current_shard = name @@ -43,9 +43,9 @@ def each_current_turntable_cluster_connected(with_test = false, environment = en ActiveRecord::Base.establish_connection environment.to_sym end - def each_current_turntable_cluster_configuration(with_test = false, environment = env) + def each_current_turntable_cluster_configuration(environment) environments = [environment] - environments << "test" if with_test && environment == "development" + environments << "test" if environment == "development" current_turntable_cluster_configurations(*environments).each do |name, configuration| yield(name, configuration) unless configuration["database"].blank? diff --git a/lib/active_record/turntable/migration.rb b/lib/active_record/turntable/migration.rb index 0f31afd6..812f1688 100644 --- a/lib/active_record/turntable/migration.rb +++ b/lib/active_record/turntable/migration.rb @@ -108,7 +108,7 @@ module ClassMethods def up(migrations_paths, target_version = nil) super - ActiveRecord::Tasks::DatabaseTasks.each_current_turntable_cluster_connected do |name, configuration| + ActiveRecord::Tasks::DatabaseTasks.each_current_turntable_cluster_connected(current_environment) do |name, configuration| puts "[turntable] *** Migrating database: #{configuration['database']}(Shard: #{name})" super(migrations_paths, target_version) end @@ -117,7 +117,7 @@ def up(migrations_paths, target_version = nil) def down(migrations_paths, target_version = nil, &block) super - ActiveRecord::Tasks::DatabaseTasks.each_current_turntable_cluster_connected do |name, configuration| + ActiveRecord::Tasks::DatabaseTasks.each_current_turntable_cluster_connected(current_environment) do |name, configuration| puts "[turntable] *** Migrating database: #{configuration['database']}(Shard: #{name})" super(migrations_paths, target_version, &block) end @@ -126,7 +126,7 @@ def down(migrations_paths, target_version = nil, &block) def run(*args) super - ActiveRecord::Tasks::DatabaseTasks.each_current_turntable_cluster_connected do |name, configuration| + ActiveRecord::Tasks::DatabaseTasks.each_current_turntable_cluster_connected(current_environment) do |name, configuration| puts "[turntable] *** Migrating database: #{configuration['database']}(Shard: #{name})" super(*args) end From 79964fd5f28904a3958e1dc569687ff8a5493663 Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 8 Feb 2017 14:37:16 +0900 Subject: [PATCH 074/125] Use DEFAULT_ENV instead of `Rails.env` In case of rails is not required --- lib/active_record/turntable/cluster_helper_methods.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/active_record/turntable/cluster_helper_methods.rb b/lib/active_record/turntable/cluster_helper_methods.rb index d1bfcffc..55ab6975 100644 --- a/lib/active_record/turntable/cluster_helper_methods.rb +++ b/lib/active_record/turntable/cluster_helper_methods.rb @@ -30,7 +30,8 @@ def recursive_transaction(pools, options, &block) end def force_connect_all_shards! - conf = configurations[Rails.env] + conf = configurations[::ActiveRecord::ConnectionHandling::DEFAULT_ENV.call.to_sym] + shards = HashWithIndifferentAccess.new shards = shards.merge(conf[:shards]) if conf[:shards] shards = shards.merge(conf[:seq]) if conf[:seq] From e20644f76ed1eb1933e7b4c30183867ab565882f Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 8 Feb 2017 14:42:34 +0900 Subject: [PATCH 075/125] Fixes an error when database environments is not set --- .../turntable/active_record_ext/database_tasks.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/active_record/turntable/active_record_ext/database_tasks.rb b/lib/active_record/turntable/active_record_ext/database_tasks.rb index c5b69ef4..0bfdf769 100644 --- a/lib/active_record/turntable/active_record_ext/database_tasks.rb +++ b/lib/active_record/turntable/active_record_ext/database_tasks.rb @@ -33,6 +33,7 @@ def drop_current_turntable_cluster(environment = env) end def each_current_turntable_cluster_connected(environment) + old_connection_pool = ActiveRecord::Base.connection_pool each_current_turntable_cluster_configuration(environment) do |name, configuration| ActiveRecord::Base.clear_active_connections! ActiveRecord::Base.establish_connection(configuration) @@ -40,7 +41,7 @@ def each_current_turntable_cluster_connected(environment) yield(name, configuration) end ActiveRecord::Base.clear_active_connections! - ActiveRecord::Base.establish_connection environment.to_sym + ActiveRecord::Base.establish_connection old_connection_pool.spec.config end def each_current_turntable_cluster_configuration(environment) From d3e99e5c7a209c93c0bae9538e59e95ff84603e5 Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 8 Feb 2017 14:45:51 +0900 Subject: [PATCH 076/125] Fix errors when turntable configurations are missing --- .../turntable/active_record_ext/database_tasks.rb | 3 ++- lib/active_record/turntable/cluster_helper_methods.rb | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/active_record/turntable/active_record_ext/database_tasks.rb b/lib/active_record/turntable/active_record_ext/database_tasks.rb index 0bfdf769..fc3cd473 100644 --- a/lib/active_record/turntable/active_record_ext/database_tasks.rb +++ b/lib/active_record/turntable/active_record_ext/database_tasks.rb @@ -71,8 +71,9 @@ def current_turntable_cluster_configurations(*environments) configurations = [] environments.each do |environ| config = ActiveRecord::Base.configurations[environ] + next unless config %w(shards seq).each do |name| - configurations += config[name].to_a + configurations += config[name].to_a if config.key?(name) end end configurations diff --git a/lib/active_record/turntable/cluster_helper_methods.rb b/lib/active_record/turntable/cluster_helper_methods.rb index 55ab6975..a41d007a 100644 --- a/lib/active_record/turntable/cluster_helper_methods.rb +++ b/lib/active_record/turntable/cluster_helper_methods.rb @@ -31,6 +31,7 @@ def recursive_transaction(pools, options, &block) def force_connect_all_shards! conf = configurations[::ActiveRecord::ConnectionHandling::DEFAULT_ENV.call.to_sym] + return unless conf shards = HashWithIndifferentAccess.new shards = shards.merge(conf[:shards]) if conf[:shards] From 691e7a7334a7033628d3aebb8eb20c746a35b4c0 Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 8 Feb 2017 14:47:46 +0900 Subject: [PATCH 077/125] Rename method: `table_exists?` to `data_source_exists?` --- lib/active_record/turntable/connection_proxy.rb | 4 ++-- spec/active_record/turntable/connection_proxy_spec.rb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/active_record/turntable/connection_proxy.rb b/lib/active_record/turntable/connection_proxy.rb index 24d50bdd..bcc27ad8 100644 --- a/lib/active_record/turntable/connection_proxy.rb +++ b/lib/active_record/turntable/connection_proxy.rb @@ -198,7 +198,7 @@ def with_master(&block) end delegate :connected?, :automatic_reconnect, :automatic_reconnect=, :checkout_timeout, :dead_connection_timeout, - :spec, :connections, :size, :reaper, :table_exists?, to: :connection_pool + :spec, :connections, :size, :reaper, to: :connection_pool %w(columns columns_hash column_defaults primary_keys).each do |name| define_method(name.to_sym) do @@ -206,7 +206,7 @@ def with_master(&block) end end - %w(table_exists?).each do |name| + %w(data_source_exists?).each do |name| define_method(name.to_sym) do |*args| master.connection_pool.with_connection do |c| c.schema_cache.send(name.to_sym, *args) diff --git a/spec/active_record/turntable/connection_proxy_spec.rb b/spec/active_record/turntable/connection_proxy_spec.rb index fa7d49a8..aeb6ebed 100644 --- a/spec/active_record/turntable/connection_proxy_spec.rb +++ b/spec/active_record/turntable/connection_proxy_spec.rb @@ -232,7 +232,7 @@ it { is_expected.to be_falsey } end - context "#table_exists?" do + context "#data_source_exists?" do before do establish_connection_to(:test) truncate_shard @@ -246,7 +246,7 @@ @user2.save! end - subject { User.connection.table_exists?(:users) } + subject { User.connection.data_source_exists?(:users) } it { is_expected.to be_truthy } end end From 85fdd39131dcbc897cd0037c1581f6f7b4324ba6 Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 8 Feb 2017 14:49:37 +0900 Subject: [PATCH 078/125] Add migration versioning numbers when creating `Migration` instances --- .../turntable/active_record_ext/migration_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/active_record/turntable/active_record_ext/migration_spec.rb b/spec/active_record/turntable/active_record_ext/migration_spec.rb index 19cc09ab..b08820fd 100644 --- a/spec/active_record/turntable/active_record_ext/migration_spec.rb +++ b/spec/active_record/turntable/active_record_ext/migration_spec.rb @@ -15,7 +15,7 @@ context "With clusters definitions" do let(:migration_class) { - klass = Class.new(ActiveRecord::Migration) { + klass = Class.new(ActiveRecord::Migration[5.0]) { clusters :user_cluster } } @@ -27,7 +27,7 @@ context "With shards definitions" do let(:migration_class) { - klass = Class.new(ActiveRecord::Migration) { + klass = Class.new(ActiveRecord::Migration[5.0]) { shards :user_shard_01 } } From d29fbfa481de5e32d8806e25f67c8db8f54748ad Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 8 Feb 2017 14:51:54 +0900 Subject: [PATCH 079/125] Remove schema dumper testing because it is tested on activerecord unit tests --- .../turntable/active_record_ext/schema_dumper_spec.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/active_record/turntable/active_record_ext/schema_dumper_spec.rb b/spec/active_record/turntable/active_record_ext/schema_dumper_spec.rb index 06fa8e0c..05787197 100644 --- a/spec/active_record/turntable/active_record_ext/schema_dumper_spec.rb +++ b/spec/active_record/turntable/active_record_ext/schema_dumper_spec.rb @@ -18,7 +18,6 @@ def dump_schema context "#dump" do subject { dump_schema } - it { is_expected.to match(/create_table "users", force: :cascade, options: ".*?"\sdo\s\|t\|$/) } it { is_expected.to match(/create_sequence_for "users", force: :cascade, options: /) } it { is_expected.not_to match(/create_table "users_id_seq"/) } it { is_expected.not_to match(/create_sequence_for "users_id_seq".*?do/) } From e7b9323732196820b51e404d51462dc7d4329c0a Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 8 Feb 2017 15:01:33 +0900 Subject: [PATCH 080/125] Move `spec/rails` to `tmp/rails` --- .gitmodules | 4 ++-- Rakefile | 6 +++--- spec/rails | 1 - tmp/rails | 1 + 4 files changed, 6 insertions(+), 6 deletions(-) delete mode 160000 spec/rails create mode 160000 tmp/rails diff --git a/.gitmodules b/.gitmodules index 29df2cd5..beb1bea0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "spec/rails"] - path = spec/rails +[submodule "tmp/rails"] + path = tmp/rails url = https://github.com/rails/rails.git diff --git a/Rakefile b/Rakefile index 4aad9da2..c0fbb7aa 100644 --- a/Rakefile +++ b/Rakefile @@ -137,11 +137,11 @@ namespace :turntable do namespace :setup do task :rails => :env do system(*%w|git submodule update --init|) - Dir.chdir("spec/rails") do + Dir.chdir("tmp/rails") do system(*%W|git checkout #{ENV['ARVERSION']}|) end - FileUtils.cp_r("spec/rails/activerecord/test", ".") - FileUtils.cp_r("spec/rails/activerecord/Rakefile", "activerecord.rake") + FileUtils.cp_r("tmp/rails/activerecord/test", ".") + FileUtils.cp_r("tmp/rails/activerecord/Rakefile", "activerecord.rake") File.open("test/cases/helper.rb", "a") do |f| f << "require '#{File.expand_path("spec/activerecord_helper", __dir__)}'" end diff --git a/spec/rails b/spec/rails deleted file mode 160000 index 65bf1c60..00000000 --- a/spec/rails +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 65bf1c60053e727835e06392d27a2fb49665484c diff --git a/tmp/rails b/tmp/rails new file mode 160000 index 00000000..912ae0b3 --- /dev/null +++ b/tmp/rails @@ -0,0 +1 @@ +Subproject commit 912ae0b34bf541f18d051c8a274a54aef91a5e04 From 1a72e020c767714158faca148d7cbea7502a2911 Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 8 Feb 2017 15:10:44 +0900 Subject: [PATCH 081/125] Fixes warning: instance variable not initialized --- .../turntable/active_record_ext/abstract_adapter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/active_record/turntable/active_record_ext/abstract_adapter.rb b/lib/active_record/turntable/active_record_ext/abstract_adapter.rb index ec2c16fd..81049343 100644 --- a/lib/active_record/turntable/active_record_ext/abstract_adapter.rb +++ b/lib/active_record/turntable/active_record_ext/abstract_adapter.rb @@ -34,7 +34,7 @@ def turntable_shard_name=(name) end def turntable_shard_name - @turntable_shard_name + @turntable_shard_name ||= "" end end end From 3a13f1216675386c68deb8d178a01c9edc3f486e Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 8 Feb 2017 15:37:04 +0900 Subject: [PATCH 082/125] Parallelize travis builds --- .travis.yml | 12 ++++++++++-- ci/run-tests.sh | 2 -- ci/setup-tests.sh | 2 -- 3 files changed, 10 insertions(+), 6 deletions(-) delete mode 100755 ci/run-tests.sh delete mode 100755 ci/setup-tests.sh diff --git a/.travis.yml b/.travis.yml index eb71f305..bd94ea0e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,9 +13,17 @@ rvm: gemfile: - gemfiles/rails5_0.gemfile +env: + - SETUP_TASK=turntable:db:reset BUILD_TASK=spec + - SETUP_TASK=turntable:activerecord:setup BUILD_TASK=turntable:activerecord:test + before_install: gem update --system -before_script: ci/setup-tests.sh -script: ci/run-tests.sh + +before_script: + - bundle exec rake $SETUP_TASK + +script: + - bundle exec rake $BUILD_TASK matrix: allow_failures: diff --git a/ci/run-tests.sh b/ci/run-tests.sh deleted file mode 100755 index c9610667..00000000 --- a/ci/run-tests.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -bundle exec rake spec turntable:activerecord:test diff --git a/ci/setup-tests.sh b/ci/setup-tests.sh deleted file mode 100755 index 16926cb6..00000000 --- a/ci/setup-tests.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -bundle exec rake turntable:db:reset turntable:activerecord:setup From 8d8180065a05806b5b9167247c223994ef9efc03 Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 8 Feb 2017 20:06:56 +0900 Subject: [PATCH 083/125] Add edge rails as matrix target --- .travis.yml | 2 ++ gemfiles/rails_edge.gemfile | 8 ++++++++ 2 files changed, 10 insertions(+) create mode 100644 gemfiles/rails_edge.gemfile diff --git a/.travis.yml b/.travis.yml index bd94ea0e..d1dcc4de 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,7 @@ rvm: gemfile: - gemfiles/rails5_0.gemfile + - gemfiles/rails_edge.gemfile env: - SETUP_TASK=turntable:db:reset BUILD_TASK=spec @@ -28,3 +29,4 @@ script: matrix: allow_failures: - rvm: ruby-head + - gemfile: gemfiles/rails_edge.gemfile diff --git a/gemfiles/rails_edge.gemfile b/gemfiles/rails_edge.gemfile new file mode 100644 index 00000000..fcaf72bc --- /dev/null +++ b/gemfiles/rails_edge.gemfile @@ -0,0 +1,8 @@ +source "https://rubygems.org" + +gem "arel", github: "rails/arel" +gem "activerecord", github: "rails/rails" +gem "actionview", github: "rails/rails" +gem "activesupport", github: "rails/rails" + +gemspec :path => '../' From 4948c1f3e02a5adf74f98b32d0764d9038267be0 Mon Sep 17 00:00:00 2001 From: gussan Date: Thu, 9 Feb 2017 16:52:09 +0900 Subject: [PATCH 084/125] Fix desc position --- Rakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rakefile b/Rakefile index c0fbb7aa..264f64cc 100644 --- a/Rakefile +++ b/Rakefile @@ -155,8 +155,8 @@ namespace :turntable do desc "setup activerecord test" task :setup => ["setup:rails", "setup:db"] - task :test => :env do desc "run unit tests on activerecord" + task :test => :env do unless system(*%w|bundle exec rake -f activerecord.rake test:mysql2|) exit(1) end From 2c1ab5a3a7f7bfa00425145c0f29e97a2467e6a6 Mon Sep 17 00:00:00 2001 From: gussan Date: Thu, 9 Feb 2017 16:54:02 +0900 Subject: [PATCH 085/125] Make rails edge testing up to date --- Rakefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Rakefile b/Rakefile index 264f64cc..099f3777 100644 --- a/Rakefile +++ b/Rakefile @@ -128,7 +128,7 @@ namespace :turntable do task(:env) do ENV['ARCONFIG'] ||= File.expand_path('spec/config/activerecord_config.yml', __dir__) ENV['ARVERSION'] ||= if ActiveRecord.gem_version.prerelease? - "master" + "origin/master" else "v#{ActiveRecord.gem_version}" end @@ -137,6 +137,7 @@ namespace :turntable do namespace :setup do task :rails => :env do system(*%w|git submodule update --init|) + system(*%w|git submodule foreach git fetch origin|) Dir.chdir("tmp/rails") do system(*%W|git checkout #{ENV['ARVERSION']}|) end From 6f0be714d24e0cb7a15d0b6fe68b6733abd220e8 Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 9 Jan 2017 18:03:31 +0900 Subject: [PATCH 086/125] Ignore rubocop offences on monkey patches --- .../turntable/active_record_ext/abstract_adapter.rb | 2 ++ lib/active_record/turntable/active_record_ext/fixtures.rb | 2 ++ lib/active_record/turntable/active_record_ext/persistence.rb | 2 ++ 3 files changed, 6 insertions(+) diff --git a/lib/active_record/turntable/active_record_ext/abstract_adapter.rb b/lib/active_record/turntable/active_record_ext/abstract_adapter.rb index 81049343..6f747229 100644 --- a/lib/active_record/turntable/active_record_ext/abstract_adapter.rb +++ b/lib/active_record/turntable/active_record_ext/abstract_adapter.rb @@ -14,6 +14,7 @@ def translate_exception_class(e, sql) end # @note override for append current shard name + # rubocop:disable Style/HashSyntax, Style/MultilineMethodCallBraceLayout def log(sql, name = "SQL", binds = [], statement_name = nil) @instrumenter.instrument( "sql.active_record", @@ -26,6 +27,7 @@ def log(sql, name = "SQL", binds = [], statement_name = nil) rescue => e raise translate_exception_class(e, sql) end + # rubocop:enable Style/HashSyntax, Style/MultilineMethodCallBraceLayout protected :translate_exception_class, :log diff --git a/lib/active_record/turntable/active_record_ext/fixtures.rb b/lib/active_record/turntable/active_record_ext/fixtures.rb index 32a2ef47..d674a09b 100644 --- a/lib/active_record/turntable/active_record_ext/fixtures.rb +++ b/lib/active_record/turntable/active_record_ext/fixtures.rb @@ -7,6 +7,7 @@ module ActiveRecord class FixtureSet extend ActiveRecord::Turntable::Util + # rubocop:disable Style/MultilineMethodCallBraceLayout def self.create_fixtures(fixtures_directory, fixture_set_names, class_names = {}, config = ActiveRecord::Base) fixture_set_names = Array(fixture_set_names).map(&:to_s) class_names = ClassCache.new class_names, config @@ -65,6 +66,7 @@ def self.create_fixtures(fixtures_directory, fixture_set_names, class_names = {} end cached_fixtures(connection, fixture_set_names) end + # rubocop:enable Style/MultilineMethodCallLayout end module TestFixtures diff --git a/lib/active_record/turntable/active_record_ext/persistence.rb b/lib/active_record/turntable/active_record_ext/persistence.rb index c1b1fb4c..7c9816f4 100644 --- a/lib/active_record/turntable/active_record_ext/persistence.rb +++ b/lib/active_record/turntable/active_record_ext/persistence.rb @@ -27,6 +27,7 @@ def reload(options = nil) end # @note Override to add sharding scope on `touch` + # rubocop:disable Style/UnlessElse def touch(*names, time: nil) raise ActiveRecord::ActiveRecordError, "cannot touch on a new record object" unless persisted? @@ -68,6 +69,7 @@ def touch(*names, time: nil) true end end + # rubocop:enable Style/UnlessElse # @note Override to add sharding scope on `update_columns` def update_columns(attributes) From 3e72cfbaa252dc336539a8124a07555c820b46ef Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 9 Jan 2017 18:04:26 +0900 Subject: [PATCH 087/125] Enable byebug always because supported ruby versions are >= 2.2.2 --- spec/spec_helper.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index e0d1848b..c92bd7e2 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -7,10 +7,7 @@ require "webmock/rspec" require "pry" require "timecop" -begin - require "pry-byebug" -rescue LoadError -end +require "pry-byebug" require "activerecord-turntable" From e7ead2b08e54265ad9897e8702f9b45b2497cdd4 Mon Sep 17 00:00:00 2001 From: gussan Date: Thu, 12 Jan 2017 01:14:47 +0900 Subject: [PATCH 088/125] Ignore Metrics/BlockLength on gemspec --- activerecord-turntable.gemspec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/activerecord-turntable.gemspec b/activerecord-turntable.gemspec index 6205685f..53c48ad6 100644 --- a/activerecord-turntable.gemspec +++ b/activerecord-turntable.gemspec @@ -1,6 +1,7 @@ $LOAD_PATH.push File.expand_path("../lib", __FILE__) require "active_record/turntable/version" +# rubocop:disable Metrics/BlockLength Gem::Specification.new do |spec| spec.name = "activerecord-turntable" spec.version = ActiveRecord::Turntable::VERSION @@ -58,3 +59,4 @@ Gem::Specification.new do |spec| spec.add_development_dependency "mocha", "~> 0.14" spec.add_development_dependency "sqlite3", "~> 1.3.6" end +# rubocop:enable Metrics/BlockLength From e3e3452bfc9e382bf0c3e1f28cbdd0c1d28592f1 Mon Sep 17 00:00:00 2001 From: gussan Date: Thu, 12 Jan 2017 01:15:42 +0900 Subject: [PATCH 089/125] Remove unused activerecord_import code --- .../turntable/active_record_ext/activerecord_import_ext.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb b/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb index 8d9106b8..6de15025 100644 --- a/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb +++ b/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb @@ -20,11 +20,7 @@ module ActiverecordImportExt connection_memo.next_value_for_sequence(sequence_name) end elsif column - if defined?(type_caster_memo) && type_caster_memo.respond_to?(:type_cast_for_database) # Rails 5.0 and higher - connection_memo.quote(type_caster_memo.type_cast_for_database(column.name, val)) - else # Rails 4.2 and higher - connection_memo.quote(column.type_cast_from_user(val), column) - end + connection_memo.quote(type_caster_memo.type_cast_for_database(column.name, val)) end end "(#{my_values.join(',')})" From 3039452444eac8587afc3f834ccb408ce6e9605b Mon Sep 17 00:00:00 2001 From: gussan Date: Thu, 12 Jan 2017 01:19:54 +0900 Subject: [PATCH 090/125] Cleanup connection listing on PoolProxy --- lib/active_record/turntable/pool_proxy.rb | 34 +++++++++++++---------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/lib/active_record/turntable/pool_proxy.rb b/lib/active_record/turntable/pool_proxy.rb index 5061cbfe..106ecbd1 100644 --- a/lib/active_record/turntable/pool_proxy.rb +++ b/lib/active_record/turntable/pool_proxy.rb @@ -26,24 +26,30 @@ def with_connection end end - %w(active_connection?).each do |name| - define_method(name.to_sym) do |*_args| - @proxy.master.connection_pool.send(name.to_sym) || - @proxy.seq.connection_pool.try(name.to_sym) if @proxy.respond_to?(:seq) || - @proxy.shards.values.any? do |pool| - pool.connection_pool.send(name.to_sym) - end - end + def active_connection? + connection_pools_list.any? { |cp| cp.active_connection? } end - %w(disconnect! release_connection clear_all_connections! clear_active_connections! clear_reloadable_connections! clear_stale_cached_connections! verify_active_connections!).each do |name| + %w(disconnect! + release_connection + clear_all_connections! + clear_active_connections! + clear_reloadable_connections! + clear_stale_cached_connections! + verify_active_connections!).each do |name| define_method(name.to_sym) do - @proxy.master.connection_pool.send(name.to_sym) - @proxy.seq.connection_pool.try(name.to_sym) if @proxy.respond_to?(:seq) - @proxy.shards.values.each do |pool| - pool.connection_pool.send(name.to_sym) - end + connection_pools_list.each { |cp| cp.public_send(name.to_sym) } end end + + private + + def connection_pools_list + pools = [] + pools << proxy.master.connection_pool + pools << proxy.seq.try(:connection_pool) if proxy.respond_to?(:seq) + pools.concat(proxy.shards.values.map(&:connection_pool)) + pools.compact + end end end From 8b0857d67431de235e6abb3413db34f4e08186c1 Mon Sep 17 00:00:00 2001 From: gussan Date: Thu, 9 Feb 2017 17:36:41 +0900 Subject: [PATCH 091/125] Disable allcops under `test/` and `tmp/` --- .rubocop.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.rubocop.yml b/.rubocop.yml index ff410e55..8eb77f0f 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -5,3 +5,6 @@ inherit_gem: AllCops: TargetRubyVersion: 2.2 + Exclude: + - "test/**/*" + - "tmp/**/*" From dff25b244e4df2e49bb2aaf7b51343e1b3ebd479 Mon Sep 17 00:00:00 2001 From: gussan Date: Thu, 9 Feb 2017 17:38:05 +0900 Subject: [PATCH 092/125] Disable `Style/CaseEquality` cop on SQLTree related files --- lib/active_record/turntable/mixer.rb | 2 ++ lib/active_record/turntable/sql_tree_patch.rb | 2 ++ 2 files changed, 4 insertions(+) diff --git a/lib/active_record/turntable/mixer.rb b/lib/active_record/turntable/mixer.rb index e591ff61..553744d7 100644 --- a/lib/active_record/turntable/mixer.rb +++ b/lib/active_record/turntable/mixer.rb @@ -1,3 +1,4 @@ +# rubocop:disable Style/CaseEquality require "active_support/core_ext/object/try" require "active_record/turntable/sql_tree_patch" @@ -231,3 +232,4 @@ def raise_on_not_specified_shard_update? end end end +# rubocop:enable Style/CaseEquality diff --git a/lib/active_record/turntable/sql_tree_patch.rb b/lib/active_record/turntable/sql_tree_patch.rb index b3e1b1d3..274ffa03 100644 --- a/lib/active_record/turntable/sql_tree_patch.rb +++ b/lib/active_record/turntable/sql_tree_patch.rb @@ -1,3 +1,4 @@ +# rubocop:disable Style/CaseEquality require "sql_tree" require "active_support/core_ext/kernel/reporting" @@ -350,3 +351,4 @@ def self.parse_value_list(tokens) end end end +# rubocop:enable Style/CaseEquality From bf09a248b755ec544d0d7ac455ef0b478c0981ca Mon Sep 17 00:00:00 2001 From: gussan Date: Thu, 9 Feb 2017 19:06:56 +0900 Subject: [PATCH 093/125] Exclude `activerecord.rake` from cop target --- .rubocop.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.rubocop.yml b/.rubocop.yml index 8eb77f0f..82c33144 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -8,3 +8,4 @@ AllCops: Exclude: - "test/**/*" - "tmp/**/*" + - "activerecord.rake" From c3eac867311dd9309c21f6c51bb902cef2187eb3 Mon Sep 17 00:00:00 2001 From: gussan Date: Thu, 9 Feb 2017 20:19:46 +0900 Subject: [PATCH 094/125] Add auto-generated `.rubocop_todo.yml` --- .rubocop_todo.yml | 476 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 476 insertions(+) create mode 100644 .rubocop_todo.yml diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 00000000..07159d60 --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,476 @@ +# This configuration was generated by +# `rubocop --auto-gen-config` +# on 2017-02-10 00:09:09 +0900 using RuboCop version 0.47.1. +# The point is for the user to remove these configuration records +# one by one as the offenses are removed from the code base. +# Note that changes in the inspected code, or installation of new +# versions of RuboCop, may require this file to be generated again. + +# Offense count: 2 +# Configuration parameters: AllowSafeAssignment. +Lint/AssignmentInCondition: + Exclude: + - 'lib/active_record/turntable/active_record_ext/connection_handler_extension.rb' + - 'lib/active_record/turntable/active_record_ext/schema_dumper.rb' + +# Offense count: 1 +Lint/EmptyWhen: + Exclude: + - 'lib/active_record/turntable/sql_tree_patch.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyleAlignWith, SupportedStylesAlignWith, AutoCorrect. +# SupportedStylesAlignWith: keyword, variable, start_of_line +Lint/EndAlignment: + Exclude: + - 'lib/active_record/turntable/algorithm/range_algorithm.rb' + - 'lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb' + +# Offense count: 2 +Lint/HandleExceptions: + Exclude: + - 'lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb' + - 'lib/active_record/turntable/active_record_ext/acts_as_archive_extension.rb' + +# Offense count: 1 +Lint/IneffectiveAccessModifier: + Exclude: + - 'lib/active_record/turntable/sequencer.rb' + +# Offense count: 4 +Lint/RescueException: + Exclude: + - 'lib/active_record/turntable/connection_proxy.rb' + - 'lib/active_record/turntable/mixer.rb' + +# Offense count: 5 +Lint/ShadowingOuterLocalVariable: + Exclude: + - 'lib/active_record/turntable/algorithm/range_algorithm.rb' + - 'lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb' + - 'lib/active_record/turntable/railties/databases.rake' + +# Offense count: 5 +# Cop supports --auto-correct. +Lint/UnneededSplatExpansion: + Exclude: + - 'Rakefile' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: IgnoreEmptyBlocks, AllowUnusedKeywordArguments. +Lint/UnusedBlockArgument: + Exclude: + - 'spec/active_record/turntable/query_cache_spec.rb' + +# Offense count: 1 +# Configuration parameters: ContextCreatingMethods, MethodCreatingMethods. +Lint/UselessAccessModifier: + Exclude: + - 'lib/active_record/turntable/sequencer.rb' + +# Offense count: 8 +Lint/UselessAssignment: + Exclude: + - 'lib/active_record/turntable/algorithm/range_algorithm.rb' + - 'lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb' + - 'lib/active_record/turntable/cluster_helper_methods.rb' + - 'lib/active_record/turntable/migration.rb' + - 'lib/active_record/turntable/mixer.rb' + - 'spec/active_record/turntable/active_record_ext/migration_spec.rb' + +# Offense count: 14 +Metrics/AbcSize: + Max: 106 + +# Offense count: 2 +# Configuration parameters: CountComments, ExcludedMethods. +Metrics/BlockLength: + Max: 88 + +# Offense count: 2 +# Configuration parameters: CountComments. +Metrics/ClassLength: + Max: 202 + +# Offense count: 5 +Metrics/CyclomaticComplexity: + Max: 20 + +# Offense count: 2 +# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. +# URISchemes: http, https +Metrics/LineLength: + Max: 246 + +# Offense count: 10 +# Configuration parameters: CountComments. +Metrics/MethodLength: + Max: 56 + +# Offense count: 1 +# Configuration parameters: CountKeywordArgs. +Metrics/ParameterLists: + Max: 6 + +# Offense count: 9 +Metrics/PerceivedComplexity: + Max: 24 + +# Offense count: 3 +# Cop supports --auto-correct. +Performance/TimesMap: + Exclude: + - 'script/performance/algorithm' + - 'spec/active_record/turntable/active_record_ext/association_preloader_spec.rb' + - 'spec/active_record/turntable/active_record_ext/association_spec.rb' + +# Offense count: 2 +RSpec/DescribeClass: + Exclude: + - 'spec/active_record/turntable/finder_spec.rb' + - 'spec/active_record/turntable/transaction_spec.rb' + +# Offense count: 1 +# Configuration parameters: CustomIncludeMethods. +RSpec/EmptyExampleGroup: + Exclude: + - 'spec/active_record/turntable/mixer/fader_spec.rb' + +# Offense count: 28 +# Configuration parameters: CustomTransform, IgnoredWords. +RSpec/ExampleWording: + Exclude: + - 'spec/active_record/turntable/active_record_ext/clever_load_spec.rb' + - 'spec/active_record/turntable/active_record_ext/persistence_spec.rb' + - 'spec/active_record/turntable/connection_proxy_spec.rb' + - 'spec/active_record/turntable/query_cache_spec.rb' + - 'spec/active_record/turntable_spec.rb' + +# Offense count: 4 +RSpec/ExpectActual: + Exclude: + - 'spec/active_record/turntable/mixer_spec.rb' + +# Offense count: 3 +# Configuration parameters: CustomTransform, IgnoreMethods. +RSpec/FilePath: + Exclude: + - 'spec/active_record/turntable/active_record_ext/fixture_set_spec.rb' + - 'spec/active_record/turntable/active_record_ext/migration_spec.rb' + - 'spec/active_record/turntable/active_record_ext/test_fixtures_spec.rb' + +# Offense count: 11 +# Configuration parameters: EnforcedStyle, SupportedStyles. +# SupportedStyles: implicit, each, example +RSpec/HookArgument: + Exclude: + - 'spec/active_record/turntable/active_record_ext/association_preloader_spec.rb' + - 'spec/active_record/turntable/active_record_ext/association_spec.rb' + - 'spec/active_record/turntable/active_record_ext/clever_load_spec.rb' + - 'spec/active_record/turntable/active_record_ext/locking_optimistic_spec.rb' + - 'spec/active_record/turntable/active_record_ext/log_subscriber_spec.rb' + - 'spec/active_record/turntable/active_record_ext/migration_spec.rb' + - 'spec/active_record/turntable/active_record_ext/persistence_spec.rb' + - 'spec/active_record/turntable/active_record_ext/schema_dumper_spec.rb' + - 'spec/active_record/turntable/active_record_ext/sequencer_spec.rb' + - 'spec/active_record/turntable/transaction_spec.rb' + +# Offense count: 3 +RSpec/LeadingSubject: + Exclude: + - 'spec/active_record/turntable/active_record_ext/persistence_spec.rb' + - 'spec/active_record/turntable/connection_proxy_spec.rb' + - 'spec/active_record/turntable/query_cache_spec.rb' + +# Offense count: 2 +# Configuration parameters: SupportedStyles. +# SupportedStyles: have_received, receive +RSpec/MessageSpies: + EnforcedStyle: receive + +# Offense count: 21 +# Configuration parameters: Max. +RSpec/NestedGroups: + Exclude: + - 'spec/active_record/turntable/active_record_ext/association_preloader_spec.rb' + - 'spec/active_record/turntable/active_record_ext/association_spec.rb' + - 'spec/active_record/turntable/active_record_ext/clever_load_spec.rb' + - 'spec/active_record/turntable/connection_proxy_spec.rb' + - 'spec/active_record/turntable/finder_spec.rb' + - 'spec/active_record/turntable/mixer_spec.rb' + +# Offense count: 21 +# Configuration parameters: EnforcedStyle, SupportedStyles. +# SupportedStyles: not_to, to_not +RSpec/NotToNot: + Exclude: + - 'spec/active_record/turntable/active_record_ext/association_preloader_spec.rb' + - 'spec/active_record/turntable/active_record_ext/association_spec.rb' + - 'spec/active_record/turntable/active_record_ext/persistence_spec.rb' + - 'spec/active_record/turntable/active_record_ext/sequencer_spec.rb' + - 'spec/active_record/turntable/sql_tree_patch_spec.rb' + +# Offense count: 4 +RSpec/ScatteredSetup: + Exclude: + - 'spec/active_record/turntable/active_record_ext/locking_optimistic_spec.rb' + - 'spec/active_record/turntable/active_record_ext/test_fixtures_spec.rb' + +# Offense count: 1 +Style/AccessorMethodName: + Exclude: + - 'lib/active_record/turntable/shard.rb' + +# Offense count: 4 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +# SupportedStyles: always, conditionals +Style/AndOr: + Exclude: + - 'lib/active_record/turntable/active_record_ext/persistence.rb' + - 'lib/active_record/turntable/mixer.rb' + +# Offense count: 15 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles, ProceduralMethods, FunctionalMethods, IgnoredMethods. +# SupportedStyles: line_count_based, semantic, braces_for_chaining +# ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object +# FunctionalMethods: let, let!, subject, watch +# IgnoredMethods: lambda, proc, it +Style/BlockDelimiters: + Exclude: + - 'spec/**/*' + - 'lib/active_record/turntable/active_record_ext/acts_as_archive_extension.rb' + - 'lib/active_record/turntable/active_record_ext/clever_load.rb' + - 'lib/active_record/turntable/active_record_ext/database_tasks.rb' + - 'lib/active_record/turntable/active_record_ext/fixtures.rb' + - 'lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb' + - 'lib/active_record/turntable/cluster_helper_methods.rb' + - 'lib/active_record/turntable/connection_proxy.rb' + - 'script/performance/algorithm' + +# Offense count: 7 +Style/ClassVars: + Exclude: + - 'lib/active_record/turntable.rb' + - 'lib/active_record/turntable/active_record_ext/fixtures.rb' + - 'lib/active_record/turntable/sequencer.rb' + - 'lib/active_record/turntable/sequencer/barrage.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +Style/ClosingParenthesisIndentation: + Exclude: + - 'lib/active_record/turntable/active_record_ext/association.rb' + - 'lib/active_record/turntable/base.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +Style/ElseAlignment: + Exclude: + - 'lib/active_record/turntable/algorithm/range_algorithm.rb' + - 'lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +Style/EmptyLinesAroundAccessModifier: + Exclude: + - 'lib/active_record/turntable/active_record_ext/schema_dumper.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: AllowForAlignment, ForceEqualSignAlignment. +Style/ExtraSpacing: + Exclude: + - 'db/migrate/*.rb' + - 'lib/active_record/turntable/query_cache.rb' + +# Offense count: 1 +# Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms. +# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS +Style/FileName: + Exclude: + - 'lib/activerecord-turntable.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth. +# SupportedStyles: consistent, special_for_inner_method_call, special_for_inner_method_call_in_parentheses +Style/FirstParameterIndentation: + Exclude: + - 'lib/active_record/turntable/active_record_ext/association.rb' + +# Offense count: 2 +# Configuration parameters: MinBodyLength. +Style/GuardClause: + Exclude: + - 'lib/active_record/turntable/sql_tree_patch.rb' + +# Offense count: 1 +Style/IfWithSemicolon: + Exclude: + - 'spec/active_record/turntable_spec.rb' + +# Offense count: 4 +# Cop supports --auto-correct. +# Configuration parameters: Width. +Style/IndentationWidth: + Exclude: + - 'lib/active_record/turntable/active_record_ext/persistence.rb' + - 'lib/active_record/turntable/algorithm/range_algorithm.rb' + - 'lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb' + - 'lib/active_record/turntable/sharding_condition.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +# SupportedStyles: line_count_dependent, lambda, literal +Style/Lambda: + Exclude: + - 'spec/active_record/turntable/query_cache_spec.rb' + +# Offense count: 4 +Style/MethodCalledOnDoEndBlock: + Exclude: + - 'lib/active_record/turntable/migration.rb' + - 'lib/active_record/turntable/mixer.rb' + - 'lib/active_record/turntable/mixer/fader/update_shards_merge_result.rb' + - 'lib/active_record/turntable/sql_tree_patch.rb' + +# Offense count: 1 +Style/MethodMissing: + Exclude: + - 'lib/active_record/turntable/connection_proxy.rb' + +# Offense count: 1 +# Configuration parameters: SupportedStyles. +# SupportedStyles: snake_case, camelCase +Style/MethodName: + EnforcedStyle: snake_case + +# Offense count: 1 +# Configuration parameters: EnforcedStyle, SupportedStyles. +# SupportedStyles: module_function, extend_self +Style/ModuleFunction: + Exclude: + - 'lib/active_record/turntable/util.rb' + +# Offense count: 3 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +# SupportedStyles: symmetrical, new_line, same_line +Style/MultilineMethodCallBraceLayout: + Exclude: + - 'lib/active_record/turntable/mixer.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth. +# SupportedStyles: aligned, indented +Style/MultilineOperationIndentation: + Exclude: + - 'lib/active_record/turntable/mixer.rb' + +# Offense count: 1 +Style/MultilineTernaryOperator: + Exclude: + - 'lib/active_record/turntable.rb' + +# Offense count: 1 +Style/NestedTernaryOperator: + Exclude: + - 'lib/active_record/turntable/mixer.rb' + +# Offense count: 5 +# Cop supports --auto-correct. +# Configuration parameters: PreferredDelimiters. +Style/PercentLiteralDelimiters: + Exclude: + - 'Rakefile' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +# SupportedStyles: short, verbose +Style/PreferredHashMethods: + Exclude: + - 'lib/active_record/turntable/active_record_ext/database_tasks.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +# SupportedStyles: compact, exploded +Style/RaiseArgs: + Exclude: + - 'lib/active_record/turntable/sql_tree_patch.rb' + +# Offense count: 6 +# Cop supports --auto-correct. +# Configuration parameters: AllowMultipleReturnValues. +Style/RedundantReturn: + Exclude: + - 'lib/active_record/turntable/sql_tree_patch.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles, AllowInnerSlashes. +# SupportedStyles: slashes, percent_r, mixed +Style/RegexpLiteral: + Exclude: + - 'Guardfile' + - 'lib/active_record/turntable/mixer.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: AllowForAlignment. +Style/SpaceAroundOperators: + Exclude: + - 'lib/active_record/turntable/query_cache.rb' + +# Offense count: 3 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +# SupportedStyles: space, no_space +Style/SpaceBeforeBlockBraces: + Exclude: + - 'spec/active_record/turntable/active_record_ext/persistence_spec.rb' + +# Offense count: 3 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles, EnforcedStyleForEmptyBraces, SupportedStylesForEmptyBraces, SpaceBeforeBlockParameters. +# SupportedStyles: space, no_space +# SupportedStylesForEmptyBraces: space, no_space +Style/SpaceInsideBlockBraces: + Exclude: + - 'lib/active_record/turntable/active_record_ext/clever_load.rb' + - 'lib/active_record/turntable/cluster_helper_methods.rb' + +# Offense count: 7 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles, ConsistentQuotesInMultiline. +# SupportedStyles: single_quotes, double_quotes +Style/StringLiterals: + Exclude: + - 'Rakefile' + - 'lib/active_record/turntable/active_record_ext/acts_as_archive_extension.rb' + - 'lib/active_record/turntable/sql_tree_patch.rb' + - 'spec/activerecord_helper.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: IgnoredMethods. +# IgnoredMethods: respond_to, define_method +Style/SymbolProc: + Exclude: + - 'lib/active_record/turntable/pool_proxy.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles, AllowSafeAssignment. +# SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex +Style/TernaryParentheses: + Exclude: + - 'lib/active_record/turntable/sequencer.rb' + - 'lib/active_record/turntable/sql_tree_patch.rb' From 076ce8a5e6db2b1b57263243270bd30e40cff6be Mon Sep 17 00:00:00 2001 From: gussan Date: Fri, 10 Feb 2017 18:47:54 +0900 Subject: [PATCH 095/125] Fixes auto-correctable offences Lint/EndAlignment Lint/UnusedBlockArgument Style/AndOr Style/ClosingParenthesisIndentation Style/ElseAlignment Style/EmptyLinesAroundAccessModifier Style/ExtraSpacing Style/FirstParameterIndentation Style/IndentationWidth Style/Lambda Style/MultilineMethodCallBraceLayout Style/MultilineOperationIndentation Style/PreferredHashMethods Style/RaiseArgs Style/RegexpLiteral Style/SpaceAroundOperators Style/SpaceBeforeBlockBraces Style/SpaceInsideBlockBraces Style/StringLiterals Style/SymbolProc --- .rubocop.yml | 3 + .rubocop_todo.yml | 155 ------------------ Rakefile | 4 +- activerecord-turntable.gemspec | 3 - .../acts_as_archive_extension.rb | 2 +- .../active_record_ext/association.rb | 6 +- .../active_record_ext/clever_load.rb | 4 +- .../active_record_ext/database_tasks.rb | 2 +- .../active_record_ext/persistence.rb | 40 ++--- .../active_record_ext/schema_dumper.rb | 1 + .../turntable/algorithm/range_algorithm.rb | 6 +- .../algorithm/range_bsearch_algorithm.rb | 6 +- lib/active_record/turntable/base.rb | 2 +- .../turntable/cluster_helper_methods.rb | 2 +- lib/active_record/turntable/mixer.rb | 15 +- lib/active_record/turntable/pool_proxy.rb | 2 +- lib/active_record/turntable/query_cache.rb | 2 +- .../turntable/sharding_condition.rb | 28 ++-- lib/active_record/turntable/sql_tree_patch.rb | 6 +- .../active_record_ext/persistence_spec.rb | 6 +- .../turntable/query_cache_spec.rb | 2 +- spec/activerecord_helper.rb | 4 +- 22 files changed, 72 insertions(+), 229 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 82c33144..1a2b7e84 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -3,6 +3,9 @@ inherit_gem: - "config/rubocop.yml" - "config/rspec.yml" +inherit_from: + - ".rubocop_todo.yml" + AllCops: TargetRubyVersion: 2.2 Exclude: diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 07159d60..363eabd4 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -18,15 +18,6 @@ Lint/EmptyWhen: Exclude: - 'lib/active_record/turntable/sql_tree_patch.rb' -# Offense count: 2 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyleAlignWith, SupportedStylesAlignWith, AutoCorrect. -# SupportedStylesAlignWith: keyword, variable, start_of_line -Lint/EndAlignment: - Exclude: - - 'lib/active_record/turntable/algorithm/range_algorithm.rb' - - 'lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb' - # Offense count: 2 Lint/HandleExceptions: Exclude: @@ -57,13 +48,6 @@ Lint/UnneededSplatExpansion: Exclude: - 'Rakefile' -# Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: IgnoreEmptyBlocks, AllowUnusedKeywordArguments. -Lint/UnusedBlockArgument: - Exclude: - - 'spec/active_record/turntable/query_cache_spec.rb' - # Offense count: 1 # Configuration parameters: ContextCreatingMethods, MethodCreatingMethods. Lint/UselessAccessModifier: @@ -223,15 +207,6 @@ Style/AccessorMethodName: Exclude: - 'lib/active_record/turntable/shard.rb' -# Offense count: 4 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: always, conditionals -Style/AndOr: - Exclude: - - 'lib/active_record/turntable/active_record_ext/persistence.rb' - - 'lib/active_record/turntable/mixer.rb' - # Offense count: 15 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles, ProceduralMethods, FunctionalMethods, IgnoredMethods. @@ -259,34 +234,6 @@ Style/ClassVars: - 'lib/active_record/turntable/sequencer.rb' - 'lib/active_record/turntable/sequencer/barrage.rb' -# Offense count: 2 -# Cop supports --auto-correct. -Style/ClosingParenthesisIndentation: - Exclude: - - 'lib/active_record/turntable/active_record_ext/association.rb' - - 'lib/active_record/turntable/base.rb' - -# Offense count: 2 -# Cop supports --auto-correct. -Style/ElseAlignment: - Exclude: - - 'lib/active_record/turntable/algorithm/range_algorithm.rb' - - 'lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb' - -# Offense count: 1 -# Cop supports --auto-correct. -Style/EmptyLinesAroundAccessModifier: - Exclude: - - 'lib/active_record/turntable/active_record_ext/schema_dumper.rb' - -# Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: AllowForAlignment, ForceEqualSignAlignment. -Style/ExtraSpacing: - Exclude: - - 'db/migrate/*.rb' - - 'lib/active_record/turntable/query_cache.rb' - # Offense count: 1 # Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms. # AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS @@ -294,14 +241,6 @@ Style/FileName: Exclude: - 'lib/activerecord-turntable.rb' -# Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth. -# SupportedStyles: consistent, special_for_inner_method_call, special_for_inner_method_call_in_parentheses -Style/FirstParameterIndentation: - Exclude: - - 'lib/active_record/turntable/active_record_ext/association.rb' - # Offense count: 2 # Configuration parameters: MinBodyLength. Style/GuardClause: @@ -313,24 +252,6 @@ Style/IfWithSemicolon: Exclude: - 'spec/active_record/turntable_spec.rb' -# Offense count: 4 -# Cop supports --auto-correct. -# Configuration parameters: Width. -Style/IndentationWidth: - Exclude: - - 'lib/active_record/turntable/active_record_ext/persistence.rb' - - 'lib/active_record/turntable/algorithm/range_algorithm.rb' - - 'lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb' - - 'lib/active_record/turntable/sharding_condition.rb' - -# Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: line_count_dependent, lambda, literal -Style/Lambda: - Exclude: - - 'spec/active_record/turntable/query_cache_spec.rb' - # Offense count: 4 Style/MethodCalledOnDoEndBlock: Exclude: @@ -357,22 +278,6 @@ Style/ModuleFunction: Exclude: - 'lib/active_record/turntable/util.rb' -# Offense count: 3 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: symmetrical, new_line, same_line -Style/MultilineMethodCallBraceLayout: - Exclude: - - 'lib/active_record/turntable/mixer.rb' - -# Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth. -# SupportedStyles: aligned, indented -Style/MultilineOperationIndentation: - Exclude: - - 'lib/active_record/turntable/mixer.rb' - # Offense count: 1 Style/MultilineTernaryOperator: Exclude: @@ -390,22 +295,6 @@ Style/PercentLiteralDelimiters: Exclude: - 'Rakefile' -# Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: short, verbose -Style/PreferredHashMethods: - Exclude: - - 'lib/active_record/turntable/active_record_ext/database_tasks.rb' - -# Offense count: 2 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: compact, exploded -Style/RaiseArgs: - Exclude: - - 'lib/active_record/turntable/sql_tree_patch.rb' - # Offense count: 6 # Cop supports --auto-correct. # Configuration parameters: AllowMultipleReturnValues. @@ -422,50 +311,6 @@ Style/RegexpLiteral: - 'Guardfile' - 'lib/active_record/turntable/mixer.rb' -# Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: AllowForAlignment. -Style/SpaceAroundOperators: - Exclude: - - 'lib/active_record/turntable/query_cache.rb' - -# Offense count: 3 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: space, no_space -Style/SpaceBeforeBlockBraces: - Exclude: - - 'spec/active_record/turntable/active_record_ext/persistence_spec.rb' - -# Offense count: 3 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles, EnforcedStyleForEmptyBraces, SupportedStylesForEmptyBraces, SpaceBeforeBlockParameters. -# SupportedStyles: space, no_space -# SupportedStylesForEmptyBraces: space, no_space -Style/SpaceInsideBlockBraces: - Exclude: - - 'lib/active_record/turntable/active_record_ext/clever_load.rb' - - 'lib/active_record/turntable/cluster_helper_methods.rb' - -# Offense count: 7 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles, ConsistentQuotesInMultiline. -# SupportedStyles: single_quotes, double_quotes -Style/StringLiterals: - Exclude: - - 'Rakefile' - - 'lib/active_record/turntable/active_record_ext/acts_as_archive_extension.rb' - - 'lib/active_record/turntable/sql_tree_patch.rb' - - 'spec/activerecord_helper.rb' - -# Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: IgnoredMethods. -# IgnoredMethods: respond_to, define_method -Style/SymbolProc: - Exclude: - - 'lib/active_record/turntable/pool_proxy.rb' - # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles, AllowSafeAssignment. diff --git a/Rakefile b/Rakefile index 099f3777..1db75c65 100644 --- a/Rakefile +++ b/Rakefile @@ -126,8 +126,8 @@ namespace :turntable do namespace :activerecord do task(:env) do - ENV['ARCONFIG'] ||= File.expand_path('spec/config/activerecord_config.yml', __dir__) - ENV['ARVERSION'] ||= if ActiveRecord.gem_version.prerelease? + ENV["ARCONFIG"] ||= File.expand_path("spec/config/activerecord_config.yml", __dir__) + ENV["ARVERSION"] ||= if ActiveRecord.gem_version.prerelease? "origin/master" else "v#{ActiveRecord.gem_version}" diff --git a/activerecord-turntable.gemspec b/activerecord-turntable.gemspec index 53c48ad6..6ad38d77 100644 --- a/activerecord-turntable.gemspec +++ b/activerecord-turntable.gemspec @@ -1,7 +1,5 @@ $LOAD_PATH.push File.expand_path("../lib", __FILE__) require "active_record/turntable/version" - -# rubocop:disable Metrics/BlockLength Gem::Specification.new do |spec| spec.name = "activerecord-turntable" spec.version = ActiveRecord::Turntable::VERSION @@ -59,4 +57,3 @@ Gem::Specification.new do |spec| spec.add_development_dependency "mocha", "~> 0.14" spec.add_development_dependency "sqlite3", "~> 1.3.6" end -# rubocop:enable Metrics/BlockLength diff --git a/lib/active_record/turntable/active_record_ext/acts_as_archive_extension.rb b/lib/active_record/turntable/active_record_ext/acts_as_archive_extension.rb index ad56e16d..368f0b70 100644 --- a/lib/active_record/turntable/active_record_ext/acts_as_archive_extension.rb +++ b/lib/active_record/turntable/active_record_ext/acts_as_archive_extension.rb @@ -23,7 +23,7 @@ def move(config, where, merge_options = {}) end begin - require 'acts_as_archive' + require "acts_as_archive" ActsAsArchive.prepend ActsAsArchiveExt rescue LoadError end diff --git a/lib/active_record/turntable/active_record_ext/association.rb b/lib/active_record/turntable/active_record_ext/association.rb index 6f32604d..73356857 100644 --- a/lib/active_record/turntable/active_record_ext/association.rb +++ b/lib/active_record/turntable/active_record_ext/association.rb @@ -16,9 +16,9 @@ def target_scope return super unless should_use_shard_key? scope = klass.where( - klass.turntable_shard_key => - owner.send(foreign_shard_key) - ) + klass.turntable_shard_key => + owner.send(foreign_shard_key) + ) super.merge!(scope) end diff --git a/lib/active_record/turntable/active_record_ext/clever_load.rb b/lib/active_record/turntable/active_record_ext/clever_load.rb index 21abd63a..4182d603 100644 --- a/lib/active_record/turntable/active_record_ext/clever_load.rb +++ b/lib/active_record/turntable/active_record_ext/clever_load.rb @@ -30,11 +30,11 @@ def clever_load!(association_name) self.each do |obj| matched_object = case reflection.macro when :has_one - foreign_objects.find {|fo| + foreign_objects.find { |fo| obj.send(reflection.association_primary_key) == fo.send(reflection.foreign_key) } when :belongs_to - foreign_objects.find {|fo| + foreign_objects.find { |fo| obj.send(reflection.foreign_key) == fo.send(reflection.association_primary_key) } end diff --git a/lib/active_record/turntable/active_record_ext/database_tasks.rb b/lib/active_record/turntable/active_record_ext/database_tasks.rb index fc3cd473..79b54c55 100644 --- a/lib/active_record/turntable/active_record_ext/database_tasks.rb +++ b/lib/active_record/turntable/active_record_ext/database_tasks.rb @@ -73,7 +73,7 @@ def current_turntable_cluster_configurations(*environments) config = ActiveRecord::Base.configurations[environ] next unless config %w(shards seq).each do |name| - configurations += config[name].to_a if config.key?(name) + configurations += config[name].to_a if config.has_key?(name) end end configurations diff --git a/lib/active_record/turntable/active_record_ext/persistence.rb b/lib/active_record/turntable/active_record_ext/persistence.rb index 7c9816f4..be78445b 100644 --- a/lib/active_record/turntable/active_record_ext/persistence.rb +++ b/lib/active_record/turntable/active_record_ext/persistence.rb @@ -97,30 +97,30 @@ def update_columns(attributes) private - # @note Override to add sharding scope on destroying - def relation_for_destroy - klass = self.class - relation = klass.unscoped.where(klass.primary_key => id) + # @note Override to add sharding scope on destroying + def relation_for_destroy + klass = self.class + relation = klass.unscoped.where(klass.primary_key => id) - if klass.turntable_enabled? && klass.primary_key != klass.turntable_shard_key.to_s - relation = relation.where(klass.turntable_shard_key => self[klass.turntable_shard_key]) + if klass.turntable_enabled? && klass.primary_key != klass.turntable_shard_key.to_s + relation = relation.where(klass.turntable_shard_key => self[klass.turntable_shard_key]) + end + relation end - relation - end - # @note Override to add sharding scope on updating - def _update_record(attribute_names = self.attribute_names) - klass = self.class - attributes_values = arel_attributes_with_values_for_update(attribute_names) - if attributes_values.empty? - 0 - else - scope = if klass.turntable_enabled? and klass.primary_key != klass.turntable_shard_key.to_s - klass.unscoped.where(klass.turntable_shard_key => self.send(turntable_shard_key)) - end - klass.unscoped._update_record attributes_values, id, id_was, scope + # @note Override to add sharding scope on updating + def _update_record(attribute_names = self.attribute_names) + klass = self.class + attributes_values = arel_attributes_with_values_for_update(attribute_names) + if attributes_values.empty? + 0 + else + scope = if klass.turntable_enabled? && (klass.primary_key != klass.turntable_shard_key.to_s) + klass.unscoped.where(klass.turntable_shard_key => self.send(turntable_shard_key)) + end + klass.unscoped._update_record attributes_values, id, id_was, scope + end end - end end end end diff --git a/lib/active_record/turntable/active_record_ext/schema_dumper.rb b/lib/active_record/turntable/active_record_ext/schema_dumper.rb index ad95a160..43fde7c5 100644 --- a/lib/active_record/turntable/active_record_ext/schema_dumper.rb +++ b/lib/active_record/turntable/active_record_ext/schema_dumper.rb @@ -5,6 +5,7 @@ module SchemaDumper SEQUENCE_TABLE_REGEXP = /\A(.*)_id_seq\z/ private + # @note Override to dump database sequencer method def table(table, stream) unless matchdata = table.match(SEQUENCE_TABLE_REGEXP) diff --git a/lib/active_record/turntable/algorithm/range_algorithm.rb b/lib/active_record/turntable/algorithm/range_algorithm.rb index 0d2ae7d7..564b624d 100644 --- a/lib/active_record/turntable/algorithm/range_algorithm.rb +++ b/lib/active_record/turntable/algorithm/range_algorithm.rb @@ -25,9 +25,9 @@ def calculate_used_shards_with_weight(sequence_value) prev_max = 0 shards.each_with_index do |h, idx| weighted_hash[h[:connection]] += if idx < shards.size - 1 - h[:less_than] - prev_max - 1 - else - sequence_value - prev_max + h[:less_than] - prev_max - 1 + else + sequence_value - prev_max end prev_max = h[:less_than] - 1 end diff --git a/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb b/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb index f69139bc..4fb7fcfd 100644 --- a/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb +++ b/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb @@ -29,9 +29,9 @@ def calculate_used_shards_with_weight(sequence_value) prev_max = 0 shards.each_with_index do |h, idx| weighted_hash[h[:connection]] += if idx < shards.size - 1 - h[:less_than] - prev_max - 1 - else - sequence_value - prev_max + h[:less_than] - prev_max - 1 + else + sequence_value - prev_max end prev_max = h[:less_than] - 1 end diff --git a/lib/active_record/turntable/base.rb b/lib/active_record/turntable/base.rb index f12d061b..ac85b0b8 100644 --- a/lib/active_record/turntable/base.rb +++ b/lib/active_record/turntable/base.rb @@ -52,7 +52,7 @@ def turntable(cluster_name, shard_key_name, options = {}) self.turntable_clusters[cluster_name] ||= Cluster.new( turntable_config[:clusters][cluster_name], options - ) + ) prepend ConnectionExtension turntable_replace_connection_pool end diff --git a/lib/active_record/turntable/cluster_helper_methods.rb b/lib/active_record/turntable/cluster_helper_methods.rb index a41d007a..7f5960f8 100644 --- a/lib/active_record/turntable/cluster_helper_methods.rb +++ b/lib/active_record/turntable/cluster_helper_methods.rb @@ -46,7 +46,7 @@ def weighted_random_shard_with(*klasses, &block) shards_weight = self.turntable_cluster.weighted_shards(self.current_sequence) sum = shards_weight.values.inject(&:+) idx = rand(sum) - shard, weight = shards_weight.find {|_k, v| + shard, weight = shards_weight.find { |_k, v| (idx -= v) < 0 } self.connection.with_recursive_shards(shard.name, *klasses, &block) diff --git a/lib/active_record/turntable/mixer.rb b/lib/active_record/turntable/mixer.rb index 553744d7..e711c9c1 100644 --- a/lib/active_record/turntable/mixer.rb +++ b/lib/active_record/turntable/mixer.rb @@ -76,15 +76,15 @@ def find_shard_keys(tree, table_name, shard_key) when "IN", "=", "==" field = tree.lhs.respond_to?(:table) ? tree.lhs : nil if tree.rhs.is_a?(SQLTree::Node::SubQuery) - if field.try(:table) == table_name and field.name == shard_key + if (field.try(:table) == table_name) && (field.name == shard_key) find_shard_keys(tree.rhs.where, table_name, shard_key) else [] end else values = Array(tree.rhs) - if field.try(:table) == table_name and field.name == shard_key and - !tree.rhs.is_a?(SQLTree::Node::SubQuery) + if (field.try(:table) == table_name) && (field.name == shard_key) && + !tree.rhs.is_a?(SQLTree::Node::SubQuery) values.map(&:value).compact else [] @@ -143,8 +143,7 @@ def build_select_fader(tree, method, query, *args, &block) tree.select.first.to_sql == '1 AS "one"' # for `SELECT 1 AS one` (AR::Base.exists?) return Fader::SelectShardsMergeResult.new(@proxy, build_shards_with_same_query(@proxy.shards.values, query), - method, query, *args, &block - ) + method, query, *args, &block) elsif tree.group_by || tree.order_by || tree.limit.try(:value).to_i > 0 raise CannotSpecifyShardError, "cannot specify shard for query: #{tree.to_sql}" elsif shard_keys.present? @@ -156,8 +155,7 @@ def build_select_fader(tree, method, query, *args, &block) else return Fader::SelectShardsMergeResult.new(@proxy, Hash[shard_keys.map { |k| [@proxy.cluster.shard_for(k), query] }], - method, query, *args, &block - ) + method, query, *args, &block) end else # scan all shards if SQLTree::Node::SelectDeclaration === tree.select.first && @@ -178,8 +176,7 @@ def build_select_fader(tree, method, query, *args, &block) end return Fader::SelectShardsMergeResult.new(@proxy, build_shards_with_same_query(@proxy.shards.values, query), - method, query, *args, &block - ) + method, query, *args, &block) else raise CannotSpecifyShardError, "cannot specify shard for query: #{tree.to_sql}" end diff --git a/lib/active_record/turntable/pool_proxy.rb b/lib/active_record/turntable/pool_proxy.rb index 106ecbd1..0fa15dca 100644 --- a/lib/active_record/turntable/pool_proxy.rb +++ b/lib/active_record/turntable/pool_proxy.rb @@ -27,7 +27,7 @@ def with_connection end def active_connection? - connection_pools_list.any? { |cp| cp.active_connection? } + connection_pools_list.any?(&:active_connection?) end %w(disconnect! diff --git a/lib/active_record/turntable/query_cache.rb b/lib/active_record/turntable/query_cache.rb index d4fa4546..42a46f87 100644 --- a/lib/active_record/turntable/query_cache.rb +++ b/lib/active_record/turntable/query_cache.rb @@ -17,7 +17,7 @@ def self.run end def self.complete(enabled) - klasses = ActiveRecord::Base.turntable_connections.values + klasses = ActiveRecord::Base.turntable_connections.values klasses.each do |k| k.connection.clear_query_cache k.connection.disable_query_cache! unless enabled diff --git a/lib/active_record/turntable/sharding_condition.rb b/lib/active_record/turntable/sharding_condition.rb index 31c9cb11..b5e03acb 100644 --- a/lib/active_record/turntable/sharding_condition.rb +++ b/lib/active_record/turntable/sharding_condition.rb @@ -2,22 +2,22 @@ module ActiveRecord::Turntable module ShardingCondition private - def foreign_shard_key - options[:foreign_shard_key] || foreign_target_model.turntable_shard_key - end + def foreign_shard_key + options[:foreign_shard_key] || foreign_target_model.turntable_shard_key + end - def foreign_target_model - respond_to?(:model) ? model : owner - end + def foreign_target_model + respond_to?(:model) ? model : owner + end - def should_use_shard_key? - sharded_by_same_key? || !!options[:foreign_shard_key] - end + def should_use_shard_key? + sharded_by_same_key? || !!options[:foreign_shard_key] + end - def sharded_by_same_key? - foreign_target_model.turntable_enabled? && - klass.turntable_enabled? && - foreign_shard_key == klass.turntable_shard_key - end + def sharded_by_same_key? + foreign_target_model.turntable_enabled? && + klass.turntable_enabled? && + foreign_shard_key == klass.turntable_shard_key + end end end diff --git a/lib/active_record/turntable/sql_tree_patch.rb b/lib/active_record/turntable/sql_tree_patch.rb index 274ffa03..3865b91c 100644 --- a/lib/active_record/turntable/sql_tree_patch.rb +++ b/lib/active_record/turntable/sql_tree_patch.rb @@ -48,7 +48,7 @@ def each_token(&block) # :yields: SQLTree::Token when "," then handle_token(SQLTree::Token::COMMA, &block) when /\d/ then tokenize_number(&block) when "'" then tokenize_quoted_string(&block) - when "E", "x", 'X' then tokenize_possible_escaped_string(&block) + when "E", "x", "X" then tokenize_possible_escaped_string(&block) when /\w/ then tokenize_keyword(&block) when OPERATOR_CHARS then tokenize_operator(&block) when SQLTree.identifier_quote_char then tokenize_quoted_identifier(&block) @@ -185,7 +185,7 @@ def self.parse(tokens) end table_reference else - raise SQLTree::Parser::UnexpectedToken.new(tokens.current) + raise SQLTree::Parser::UnexpectedToken, tokens.current end end end @@ -216,7 +216,7 @@ def self.parse(tokens) tokens.consume(SQLTree::Token::RPAREN) self.new(hint_method, hint_key, index_list) else - raise SQLTree::Parser::UnexpectedToken.new(tokens.current) + raise SQLTree::Parser::UnexpectedToken, tokens.current end end end diff --git a/spec/active_record/turntable/active_record_ext/persistence_spec.rb b/spec/active_record/turntable/active_record_ext/persistence_spec.rb index bc305855..768d297e 100644 --- a/spec/active_record/turntable/active_record_ext/persistence_spec.rb +++ b/spec/active_record/turntable/active_record_ext/persistence_spec.rb @@ -25,16 +25,16 @@ u.save u } - let(:user_status){ + let(:user_status) { stat = user.create_user_status(hp: 10, mp: 10) stat.updated_at = Time.current - 1.day stat.save stat } - let(:card){ + let(:card) { Card.create!(name: "foobar") } - let(:cards_user){ + let(:cards_user) { user.cards_users.create(card: card) } context "When creating record" do diff --git a/spec/active_record/turntable/query_cache_spec.rb b/spec/active_record/turntable/query_cache_spec.rb index d0404d40..2b99c97b 100644 --- a/spec/active_record/turntable/query_cache_spec.rb +++ b/spec/active_record/turntable/query_cache_spec.rb @@ -14,7 +14,7 @@ let(:mw) { executor = Class.new(ActiveSupport::Executor) ActiveRecord::Turntable::QueryCache.install_executor_hooks executor - lambda { |env| + ->(_env) { executor.wrap { [200, {}, nil] } diff --git a/spec/activerecord_helper.rb b/spec/activerecord_helper.rb index 6ac4e758..a6d94765 100644 --- a/spec/activerecord_helper.rb +++ b/spec/activerecord_helper.rb @@ -1,6 +1,6 @@ $LOAD_PATH.unshift File.expand_path("../lib", __dir__) -require 'active_record' -require 'activerecord-turntable' +require "active_record" +require "activerecord-turntable" ActiveRecord::Base.include(ActiveRecord::Turntable) require "active_record/turntable/active_record_ext/database_tasks" warn "[turntable] turntable injected." From 25767546bc9b538b69be81f3f40d7efb5535bd40 Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 13 Feb 2017 09:45:24 +0900 Subject: [PATCH 096/125] Ignore `Lint/EmptyWhen` on sql_tree_patch.rb --- .rubocop_todo.yml | 5 ----- lib/active_record/turntable/sql_tree_patch.rb | 2 ++ 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 363eabd4..48e0205e 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -13,11 +13,6 @@ Lint/AssignmentInCondition: - 'lib/active_record/turntable/active_record_ext/connection_handler_extension.rb' - 'lib/active_record/turntable/active_record_ext/schema_dumper.rb' -# Offense count: 1 -Lint/EmptyWhen: - Exclude: - - 'lib/active_record/turntable/sql_tree_patch.rb' - # Offense count: 2 Lint/HandleExceptions: Exclude: diff --git a/lib/active_record/turntable/sql_tree_patch.rb b/lib/active_record/turntable/sql_tree_patch.rb index 3865b91c..e299a045 100644 --- a/lib/active_record/turntable/sql_tree_patch.rb +++ b/lib/active_record/turntable/sql_tree_patch.rb @@ -38,6 +38,7 @@ def tokenize_quoted_string(&block) # :yields: SQLTree::Token::String end # @note Override to handle x'..' binary string + # rubocop:disable Lint/EmptyWhen: def each_token(&block) # :yields: SQLTree::Token while next_char case current_char @@ -58,6 +59,7 @@ def each_token(&block) # :yields: SQLTree::Token # Make sure to yield any tokens that are still stashed on the queue. empty_keyword_queue!(&block) end + # rubocop:enable Lint/EmptyWhen: alias_method :each, :each_token def tokenize_possible_escaped_string(&block) From 0bb6de48c6c7a23eca1245a1f94f7d8665655e03 Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 13 Feb 2017 09:48:56 +0900 Subject: [PATCH 097/125] Disable `Lint/HandleExceptions` on LoadError --- .rubocop_todo.yml | 6 ------ .../turntable/active_record_ext/activerecord_import_ext.rb | 2 +- .../active_record_ext/acts_as_archive_extension.rb | 2 +- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 48e0205e..1b4971ec 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -13,12 +13,6 @@ Lint/AssignmentInCondition: - 'lib/active_record/turntable/active_record_ext/connection_handler_extension.rb' - 'lib/active_record/turntable/active_record_ext/schema_dumper.rb' -# Offense count: 2 -Lint/HandleExceptions: - Exclude: - - 'lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb' - - 'lib/active_record/turntable/active_record_ext/acts_as_archive_extension.rb' - # Offense count: 1 Lint/IneffectiveAccessModifier: Exclude: diff --git a/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb b/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb index 6de15025..56947e0b 100644 --- a/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb +++ b/lib/active_record/turntable/active_record_ext/activerecord_import_ext.rb @@ -32,7 +32,7 @@ module ActiverecordImportExt require "activerecord-import" require "activerecord-import/base" (class << ActiveRecord::Base; self; end).prepend(ActiverecordImportExt) - rescue LoadError + rescue LoadError # rubocop:disable Lint/HandleExceptions end end end diff --git a/lib/active_record/turntable/active_record_ext/acts_as_archive_extension.rb b/lib/active_record/turntable/active_record_ext/acts_as_archive_extension.rb index 368f0b70..9e1ca68e 100644 --- a/lib/active_record/turntable/active_record_ext/acts_as_archive_extension.rb +++ b/lib/active_record/turntable/active_record_ext/acts_as_archive_extension.rb @@ -25,7 +25,7 @@ def move(config, where, merge_options = {}) begin require "acts_as_archive" ActsAsArchive.prepend ActsAsArchiveExt - rescue LoadError + rescue LoadError # rubocop:disable Lint/HandleExceptions end end end From 5168072237117b3ac372692d03716c9e730deaf6 Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 13 Feb 2017 11:24:28 +0900 Subject: [PATCH 098/125] Fix `Lint/IneffectiveAccessModifier` --- .rubocop_todo.yml | 5 --- lib/active_record/turntable/sequencer.rb | 52 ++++++++++++------------ 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 1b4971ec..70585c03 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -13,11 +13,6 @@ Lint/AssignmentInCondition: - 'lib/active_record/turntable/active_record_ext/connection_handler_extension.rb' - 'lib/active_record/turntable/active_record_ext/schema_dumper.rb' -# Offense count: 1 -Lint/IneffectiveAccessModifier: - Exclude: - - 'lib/active_record/turntable/sequencer.rb' - # Offense count: 4 Lint/RescueException: Exclude: diff --git a/lib/active_record/turntable/sequencer.rb b/lib/active_record/turntable/sequencer.rb index a012a866..c9b83783 100644 --- a/lib/active_record/turntable/sequencer.rb +++ b/lib/active_record/turntable/sequencer.rb @@ -23,23 +23,36 @@ class Sequencer @@tables = {} cattr_reader :sequences, :tables - def self.build(klass, sequence_name = nil, cluster_name = nil) - sequence_name ||= current_cluster_config_for(cluster_name || klass)[:seq].keys.first - seq_config = current_cluster_config_for(cluster_name || klass)[:seq][sequence_name] - seq_type = (seq_config[:seq_type] ? seq_config[:seq_type].to_sym : :mysql) - @@tables[klass.table_name] ||= (@@sequences[sequence_name(klass.table_name, klass.primary_key)] ||= @@sequence_types[seq_type].new(klass, seq_config)) - end + class << self + def build(klass, sequence_name = nil, cluster_name = nil) + sequence_name ||= current_cluster_config_for(cluster_name || klass)[:seq].keys.first + seq_config = current_cluster_config_for(cluster_name || klass)[:seq][sequence_name] + seq_type = (seq_config[:seq_type] ? seq_config[:seq_type].to_sym : :mysql) + @@tables[klass.table_name] ||= (@@sequences[sequence_name(klass.table_name, klass.primary_key)] ||= @@sequence_types[seq_type].new(klass, seq_config)) + end - def self.has_sequencer?(table_name) - !!@@tables[table_name] - end + def has_sequencer?(table_name) + !!@@tables[table_name] + end - def self.sequence_name(table_name, pk) - "#{table_name}_#{pk || 'id'}_seq" - end + def sequence_name(table_name, pk) + "#{table_name}_#{pk || 'id'}_seq" + end - def self.table_name(seq_name) - seq_name.split("_").first + def table_name(seq_name) + seq_name.split("_").first + end + + private + + def current_cluster_config_for(klass_or_name) + cluster_name = if klass_or_name.is_a?(Symbol) + klass_or_name + else + klass_or_name.turntable_cluster_name.to_s + end + ActiveRecord::Base.turntable_config[:clusters][cluster_name] + end end def next_sequence_value @@ -49,16 +62,5 @@ def next_sequence_value def current_sequence_value raise NotImplementedError end - - private - - def self.current_cluster_config_for(klass_or_name) - cluster_name = if klass_or_name.is_a?(Symbol) - klass_or_name - else - klass_or_name.turntable_cluster_name.to_s - end - ActiveRecord::Base.turntable_config[:clusters][cluster_name] - end end end From f44ce669c0f2260f656df163941cd53b60bcba4f Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 13 Feb 2017 12:50:07 +0900 Subject: [PATCH 099/125] Fix `Lint/ShadowingOuterLocalVariable` offences --- .rubocop_todo.yml | 7 ------ .../turntable/algorithm/range_algorithm.rb | 6 ++--- .../algorithm/range_bsearch_algorithm.rb | 6 ++--- .../turntable/railties/databases.rake | 24 +++++++++---------- 4 files changed, 18 insertions(+), 25 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 70585c03..e68a1b03 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -19,13 +19,6 @@ Lint/RescueException: - 'lib/active_record/turntable/connection_proxy.rb' - 'lib/active_record/turntable/mixer.rb' -# Offense count: 5 -Lint/ShadowingOuterLocalVariable: - Exclude: - - 'lib/active_record/turntable/algorithm/range_algorithm.rb' - - 'lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb' - - 'lib/active_record/turntable/railties/databases.rake' - # Offense count: 5 # Cop supports --auto-correct. Lint/UnneededSplatExpansion: diff --git a/lib/active_record/turntable/algorithm/range_algorithm.rb b/lib/active_record/turntable/algorithm/range_algorithm.rb index 564b624d..e952e650 100644 --- a/lib/active_record/turntable/algorithm/range_algorithm.rb +++ b/lib/active_record/turntable/algorithm/range_algorithm.rb @@ -18,9 +18,9 @@ def calculate_idx(key) # { connection_name => weight, ... } def calculate_used_shards_with_weight(sequence_value) - idx = calculate_idx(sequence_value) + current_shard_idx = calculate_idx(sequence_value) last_connection = calculate(sequence_value) - shards = @config[:shards][0..idx] + shards = @config[:shards][0..current_shard_idx] weighted_hash = Hash.new { |h, k| h[k] = 0 } prev_max = 0 shards.each_with_index do |h, idx| @@ -28,7 +28,7 @@ def calculate_used_shards_with_weight(sequence_value) h[:less_than] - prev_max - 1 else sequence_value - prev_max - end + end prev_max = h[:less_than] - 1 end weighted_hash diff --git a/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb b/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb index 4fb7fcfd..e6ec8a52 100644 --- a/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb +++ b/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb @@ -22,9 +22,9 @@ def calculate_idx(key) # { connection_name => weight, ... } def calculate_used_shards_with_weight(sequence_value) - idx = calculate_idx(sequence_value) + current_shard_idx = calculate_idx(sequence_value) last_connection = calculate(sequence_value) - shards = @config[:shards][0..idx] + shards = @config[:shards][0..current_shard_idx] weighted_hash = Hash.new { |h, k| h[k] = 0 } prev_max = 0 shards.each_with_index do |h, idx| @@ -32,7 +32,7 @@ def calculate_used_shards_with_weight(sequence_value) h[:less_than] - prev_max - 1 else sequence_value - prev_max - end + end prev_max = h[:less_than] - 1 end weighted_hash diff --git a/lib/active_record/turntable/railties/databases.rake b/lib/active_record/turntable/railties/databases.rake index 9e896fb6..98ebd4f2 100644 --- a/lib/active_record/turntable/railties/databases.rake +++ b/lib/active_record/turntable/railties/databases.rake @@ -35,9 +35,9 @@ db_namespace = namespace :db do # TODO: implement schema:cache:xxxx task :dump do require "active_record/schema_dumper" - config = ActiveRecord::Base.configurations[Rails.env] - shard_configs = config["shards"] - shard_configs.merge!(config["seq"]) if config["seq"] + current_config = ActiveRecord::Base.configurations[Rails.env] + shard_configs = current_config["shards"] + shard_configs.merge!(current_config["seq"]) if current_config["seq"] if shard_configs shard_configs.each do |name, config| next unless config["database"] @@ -48,15 +48,15 @@ db_namespace = namespace :db do end end end - ActiveRecord::Base.establish_connection(config) + ActiveRecord::Base.establish_connection(current_config) turntable_namespace["schema:dump"].reenable end desc "Load a schema.rb file into the database" task :load do - config = ActiveRecord::Base.configurations[Rails.env] - shard_configs = config["shards"] - shard_configs.merge!(config["seq"]) if config["seq"] + current_config = ActiveRecord::Base.configurations[Rails.env] + shard_configs = current_config["shards"] + shard_configs.merge!(current_config["seq"]) if current_config["seq"] if shard_configs shard_configs.each do |name, config| next unless config["database"] @@ -69,7 +69,7 @@ db_namespace = namespace :db do end end end - ActiveRecord::Base.establish_connection(config) + ActiveRecord::Base.establish_connection(current_config) end end @@ -116,16 +116,16 @@ db_namespace = namespace :db do namespace :test do # desc "Empty the test database" task :purge do - config = ActiveRecord::Base.configurations[Rails.env] - shard_configs = config["shards"] - shard_configs.merge!(config["seq"]) if config["seq"] + current_config = ActiveRecord::Base.configurations[Rails.env] + shard_configs = current_config["shards"] + shard_configs.merge!(current_config["seq"]) if current_config["seq"] if shard_configs shard_configs.each do |_name, config| next unless config["database"] ActiveRecord::Tasks::DatabaseTasks.purge config end end - ActiveRecord::Base.establish_connection(config) + ActiveRecord::Base.establish_connection(current_config) end end end From 2e5d3ac5b7bdabe1762a8f58dfcbba73ad79b7fc Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 13 Feb 2017 13:59:43 +0900 Subject: [PATCH 100/125] Remove already fixed todos --- .rubocop_todo.yml | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index e68a1b03..8e7a145e 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -25,22 +25,6 @@ Lint/UnneededSplatExpansion: Exclude: - 'Rakefile' -# Offense count: 1 -# Configuration parameters: ContextCreatingMethods, MethodCreatingMethods. -Lint/UselessAccessModifier: - Exclude: - - 'lib/active_record/turntable/sequencer.rb' - -# Offense count: 8 -Lint/UselessAssignment: - Exclude: - - 'lib/active_record/turntable/algorithm/range_algorithm.rb' - - 'lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb' - - 'lib/active_record/turntable/cluster_helper_methods.rb' - - 'lib/active_record/turntable/migration.rb' - - 'lib/active_record/turntable/mixer.rb' - - 'spec/active_record/turntable/active_record_ext/migration_spec.rb' - # Offense count: 14 Metrics/AbcSize: Max: 106 From 566134f16a3613c3b3385869e7391cdaf9b4f9a9 Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 13 Feb 2017 14:05:28 +0900 Subject: [PATCH 101/125] Fix `RSpec/DescribeClass` --- .rubocop_todo.yml | 6 ------ spec/active_record/turntable/finder_spec.rb | 2 +- spec/active_record/turntable/transaction_spec.rb | 6 +++--- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 8e7a145e..7b9ac9f1 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -71,12 +71,6 @@ Performance/TimesMap: - 'spec/active_record/turntable/active_record_ext/association_preloader_spec.rb' - 'spec/active_record/turntable/active_record_ext/association_spec.rb' -# Offense count: 2 -RSpec/DescribeClass: - Exclude: - - 'spec/active_record/turntable/finder_spec.rb' - - 'spec/active_record/turntable/transaction_spec.rb' - # Offense count: 1 # Configuration parameters: CustomIncludeMethods. RSpec/EmptyExampleGroup: diff --git a/spec/active_record/turntable/finder_spec.rb b/spec/active_record/turntable/finder_spec.rb index 2072dfb4..f6c62cf6 100644 --- a/spec/active_record/turntable/finder_spec.rb +++ b/spec/active_record/turntable/finder_spec.rb @@ -1,6 +1,6 @@ require "spec_helper" -describe "ActiveRecord::FinderMethods" do +describe ActiveRecord::FinderMethods do before(:all) do reload_turntable!(File.join(File.dirname(__FILE__), "../../config/turntable.yml")) end diff --git a/spec/active_record/turntable/transaction_spec.rb b/spec/active_record/turntable/transaction_spec.rb index 762c5490..180cb6e6 100644 --- a/spec/active_record/turntable/transaction_spec.rb +++ b/spec/active_record/turntable/transaction_spec.rb @@ -1,6 +1,6 @@ require "spec_helper" -describe "transaction" do +describe ActiveRecord::Turntable::ClusterHelperMethods do before(:all) do reload_turntable!(File.join(File.dirname(__FILE__), "../../config/turntable.yml")) end @@ -11,7 +11,7 @@ end let(:clusters) { ActiveRecord::Base.turntable_clusters } - describe "all_cluster_transaction" do + describe ".all_cluster_transaction" do let(:all_clusters) { clusters.values } let(:shards) { all_clusters.flat_map { |c| c.shards.values } } @@ -22,7 +22,7 @@ end end - describe "cluster_transaction" do + describe ".cluster_transaction" do let(:cluster) { clusters[:user_cluster] } let(:shards) { cluster.shards.values } From f28d49413c9d31b51a4496b5ff8d6433aaab510e Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 13 Feb 2017 15:39:56 +0900 Subject: [PATCH 102/125] Resolve rubocop todos: `RSpec/ExampleWording` --- .rubocop_todo.yml | 10 ------- .../active_record_ext/clever_load_spec.rb | 10 +++---- .../active_record_ext/persistence_spec.rb | 28 +++++++++---------- .../turntable/connection_proxy_spec.rb | 14 +++++----- .../turntable/query_cache_spec.rb | 2 +- spec/active_record/turntable_spec.rb | 6 ++-- 6 files changed, 30 insertions(+), 40 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 7b9ac9f1..9650d5e4 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -77,16 +77,6 @@ RSpec/EmptyExampleGroup: Exclude: - 'spec/active_record/turntable/mixer/fader_spec.rb' -# Offense count: 28 -# Configuration parameters: CustomTransform, IgnoredWords. -RSpec/ExampleWording: - Exclude: - - 'spec/active_record/turntable/active_record_ext/clever_load_spec.rb' - - 'spec/active_record/turntable/active_record_ext/persistence_spec.rb' - - 'spec/active_record/turntable/connection_proxy_spec.rb' - - 'spec/active_record/turntable/query_cache_spec.rb' - - 'spec/active_record/turntable_spec.rb' - # Offense count: 4 RSpec/ExpectActual: Exclude: diff --git a/spec/active_record/turntable/active_record_ext/clever_load_spec.rb b/spec/active_record/turntable/active_record_ext/clever_load_spec.rb index 089b38b9..ac4c12f6 100644 --- a/spec/active_record/turntable/active_record_ext/clever_load_spec.rb +++ b/spec/active_record/turntable/active_record_ext/clever_load_spec.rb @@ -27,7 +27,7 @@ context "With their associations" do subject { users.map { |u| u.association(:user_status) } } - it "should be association target loaded" do + it "makes association target loaded" do is_expected.to all(be_loaded) end end @@ -35,7 +35,7 @@ context "With their targets" do subject { users.map { |u| u.association(:user_status).target } } - it "should be loaded target object" do + it "loads target object" do is_expected.to all(be_instance_of(UserStatus)) end end @@ -49,7 +49,7 @@ context "With their associations" do subject { user_statuses.map { |us| us.association(:user) } } - it "should target loaded" do + it "makes target loaded" do is_expected.to all(be_loaded) end end @@ -57,7 +57,7 @@ context "With their targets" do subject { user_statuses.map { |us| us.association(:user).target } } - it "should be loaded target object" do + it "loads target object" do is_expected.to all(be_instance_of(User)) end end @@ -65,7 +65,7 @@ end context "When a model has has_many relation" do - it "should send query only 2 times." do + it "sends query only 2 times." do skip "not implemented yet" end end diff --git a/spec/active_record/turntable/active_record_ext/persistence_spec.rb b/spec/active_record/turntable/active_record_ext/persistence_spec.rb index 768d297e..7d2bb81e 100644 --- a/spec/active_record/turntable/active_record_ext/persistence_spec.rb +++ b/spec/active_record/turntable/active_record_ext/persistence_spec.rb @@ -52,7 +52,7 @@ end context "When the model is sharded by surrogate key" do - it "should not changed from normal operation when updating" do + it "doesn't change the behavior when updating" do user.nickname = "fizzbuzz" strio = StringIO.new ActiveRecord::Base.logger = Logger.new(strio) @@ -62,17 +62,17 @@ expect(strio.string).to match(/WHERE `users`\.`id` = #{user.id}[^\s]*$/) end - it "should be saved to target_shard" do + it "is saved to target_shard" do expect(user).to be_saved_to(user.turntable_shard) end - it "should change updated_at when updating" do + it "changes updated_at when updating" do user.nickname = "fizzbuzz" expect { user.save! }.to change(user, :updated_at) end - it "should not changed from normal operation when destroying" do + it "doesn't change the behavior when destroying" do strio = StringIO.new ActiveRecord::Base.logger = Logger.new(strio) expect { user.destroy }.to_not raise_error @@ -109,7 +109,7 @@ def on_update end context "When the model is sharded by other key" do - it "should send shard_key condition when updating" do + it "appends shard_key condition to queries when updating" do cards_user.num = 10 strio = StringIO.new @@ -120,7 +120,7 @@ def on_update expect(strio.string).to match(/`cards_users`\.`user_id` = #{cards_user.user_id}[^\s]*($|\s)/) end - it "should change updated_at when updating" do + it "changes updated_at when updating" do cards_user Timecop.travel(1.day.from_now) do @@ -131,7 +131,7 @@ def on_update end end - it "should send shard_key condition when destroying" do + it "appends shard_key condition to queries when destroying" do strio = StringIO.new ActiveRecord::Base.logger = Logger.new(strio) expect { @@ -140,11 +140,11 @@ def on_update expect(strio.string).to match(/`cards_users`\.`user_id` = #{cards_user.user_id}[^\s]*($|\s)/) end - it "should warn when creating without shard_key" do + it "warns when creating without shard_key" do skip "doesn't need to implemented soon" end - it "should execute one query when reloading" do + it "executes one query when reloading" do user; cards_user strio = StringIO.new ActiveRecord::Base.logger = Logger.new(strio) @@ -154,7 +154,7 @@ def on_update expect(strio.string.split("\n").select { |stmt| stmt =~ /SELECT/ and stmt !~ /Turntable/ }).to have(1).items end - it "should execute one query when touching" do + it "executes one query when touching" do user; cards_user strio = StringIO.new ActiveRecord::Base.logger = Logger.new(strio) @@ -163,7 +163,7 @@ def on_update expect(strio.string.split("\n").select { |stmt| stmt =~ /UPDATE/ and stmt !~ /Turntable/ }).to have(1).items end - it "should execute one query when locking" do + it "executes one query when locking" do user; cards_user strio = StringIO.new ActiveRecord::Base.logger = Logger.new(strio) @@ -172,7 +172,7 @@ def on_update expect(strio.string.split("\n").select { |stmt| stmt =~ /SELECT/ and stmt !~ /Turntable/ }).to have(1).items end - it "should execute one query when update_columns" do + it "executes one query when update_columns" do user; cards_user strio = StringIO.new ActiveRecord::Base.logger = Logger.new(strio) @@ -183,7 +183,7 @@ def on_update end context "When the model is not sharded" do - it "should not send shard_key condition when updating" do + it "doesn't append shard_key condition to queries when updating" do card.name = "barbaz" strio = StringIO.new ActiveRecord::Base.logger = Logger.new(strio) @@ -193,7 +193,7 @@ def on_update expect(strio.string).to match(/WHERE `cards`\.`id` = #{card.id}[^\s]*$/) end - it "should not send shard_key condition when destroying" do + it "doesn't append shard_key condition to queries when destroying" do strio = StringIO.new ActiveRecord::Base.logger = Logger.new(strio) expect { diff --git a/spec/active_record/turntable/connection_proxy_spec.rb b/spec/active_record/turntable/connection_proxy_spec.rb index aeb6ebed..abe2b250 100644 --- a/spec/active_record/turntable/connection_proxy_spec.rb +++ b/spec/active_record/turntable/connection_proxy_spec.rb @@ -23,7 +23,7 @@ truncate_shard end - it "should be saved to user_shard_1 with id = 1" do + it "is saved to user_shard_1 with id = 1" do user = User.new user.id = 1 expect { @@ -31,7 +31,7 @@ }.not_to raise_error end - it "should be saved to user_shard_2 with id = 30000" do + it "is saved to user_shard_2 with id = 30000" do user = User.new user.id = 30000 expect { @@ -39,7 +39,7 @@ }.not_to raise_error end - it "should be saved to user_shard_2 with id = 30000 with SQL injection attack" do + it "is saved to user_shard_2 with id = 30000 with SQL injection attack" do user = User.new user.id = 30000 user.nickname = "hogehgoge'00" @@ -49,7 +49,7 @@ user.reload end - it "should should be saved the same string when includes escaped string" do + it "is saved the same string when includes escaped string" do user = User.new user.id = 30000 user.nickname = "hoge@\n@\\@@\\nhoge\\\nhoge\\n" @@ -86,14 +86,14 @@ @user2.save! end - it "should be saved to user_shard_1 with id = 1" do + it "is saved to user_shard_1 with id = 1" do @user1.nickname = "foobar" expect { @user1.save! }.not_to raise_error end - it "should be saved to user_shard_2 with id = 30000" do + it "is saved to user_shard_2 with id = 30000" do @user2.nickname = "hogehoge" expect { @user2.save! @@ -104,7 +104,7 @@ expect(User.where(id: [1, 30000]).all.size).to eq(2) end - it "count should be 2" do + it "User.count is 2" do expect(User.count).to eq(2) end diff --git a/spec/active_record/turntable/query_cache_spec.rb b/spec/active_record/turntable/query_cache_spec.rb index 2b99c97b..02935723 100644 --- a/spec/active_record/turntable/query_cache_spec.rb +++ b/spec/active_record/turntable/query_cache_spec.rb @@ -22,7 +22,7 @@ } subject { mw.call({}) } - it "should returns 200 response" do + it "returns 200 response" do expect(subject.first).to eq(200) end end diff --git a/spec/active_record/turntable_spec.rb b/spec/active_record/turntable_spec.rb index ad53c60a..ae2b0b63 100644 --- a/spec/active_record/turntable_spec.rb +++ b/spec/active_record/turntable_spec.rb @@ -6,7 +6,7 @@ end context "#config_file" do - it "should return Rails.root/config/turntable.yml default" do + it "returns Rails.root/config/turntable.yml default" do unless defined?(::Rails); class ::Rails; end; end allow(Rails).to receive(:root) { "/path/to/rails_root" } ActiveRecord::Base.turntable_config_file = nil @@ -14,8 +14,8 @@ end end - context "#config_file=" do - it "should set config_file" do + context "#turntable_config_file=" do + it "set `#turntable_config_file`" do ActiveRecord::Base.include(ActiveRecord::Turntable) filename = "hogefuga" ActiveRecord::Base.turntable_config_file = filename From 4cdeeb804ccfcb59c160d364065d02fbf7e1a532 Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 13 Feb 2017 15:42:09 +0900 Subject: [PATCH 103/125] Resolve rubocop todo: `RSpec/ExpectActual` --- .rubocop_todo.yml | 5 ----- spec/active_record/turntable/mixer_spec.rb | 6 ++---- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 9650d5e4..7ac03fd3 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -77,11 +77,6 @@ RSpec/EmptyExampleGroup: Exclude: - 'spec/active_record/turntable/mixer/fader_spec.rb' -# Offense count: 4 -RSpec/ExpectActual: - Exclude: - - 'spec/active_record/turntable/mixer_spec.rb' - # Offense count: 3 # Configuration parameters: CustomTransform, IgnoreMethods. RSpec/FilePath: diff --git a/spec/active_record/turntable/mixer_spec.rb b/spec/active_record/turntable/mixer_spec.rb index d2d450dd..75e2086c 100644 --- a/spec/active_record/turntable/mixer_spec.rb +++ b/spec/active_record/turntable/mixer_spec.rb @@ -26,7 +26,7 @@ it { is_expected.to be_instance_of(Hash) } it { is_expected.to have_key(1) } - it { expect([1]).to have(1).item } + it { is_expected.to have(1).item } end context "When call divide_insert_values with Bulk INSERT and shard_key 'id'" do @@ -37,9 +37,7 @@ it { is_expected.to be_instance_of(Hash) } it { is_expected.to have_key(3) } - it { expect([1]).to have(1).item } - it { expect([2]).to have(1).item } - it { expect([3]).to have(1).item } + it { expect(subject.values).to all(have(1).item) } end end From b3537b4241e22d52d7aae120d4a9f52aa749b88f Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 13 Feb 2017 15:54:19 +0900 Subject: [PATCH 104/125] Fix oversights about `Lint/UselessAssignment` --- .../turntable/active_record_ext/migration_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/active_record/turntable/active_record_ext/migration_spec.rb b/spec/active_record/turntable/active_record_ext/migration_spec.rb index b08820fd..82511a4c 100644 --- a/spec/active_record/turntable/active_record_ext/migration_spec.rb +++ b/spec/active_record/turntable/active_record_ext/migration_spec.rb @@ -15,7 +15,7 @@ context "With clusters definitions" do let(:migration_class) { - klass = Class.new(ActiveRecord::Migration[5.0]) { + Class.new(ActiveRecord::Migration[5.0]) { clusters :user_cluster } } @@ -27,7 +27,7 @@ context "With shards definitions" do let(:migration_class) { - klass = Class.new(ActiveRecord::Migration[5.0]) { + Class.new(ActiveRecord::Migration[5.0]) { shards :user_shard_01 } } From 0e0a03dd92e4b72d857bb2147e3161cfc5a26e1e Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 13 Feb 2017 16:06:57 +0900 Subject: [PATCH 105/125] tmp Fixes Lint/UselessAssignment --- .../turntable/algorithm/range_algorithm.rb | 1 - .../turntable/algorithm/range_bsearch_algorithm.rb | 1 - .../turntable/cluster_helper_methods.rb | 2 +- lib/active_record/turntable/helpers/test_helper.rb | 4 ++-- lib/active_record/turntable/migration.rb | 2 -- lib/active_record/turntable/mixer.rb | 12 ++++++------ 6 files changed, 9 insertions(+), 13 deletions(-) diff --git a/lib/active_record/turntable/algorithm/range_algorithm.rb b/lib/active_record/turntable/algorithm/range_algorithm.rb index e952e650..b6efb80b 100644 --- a/lib/active_record/turntable/algorithm/range_algorithm.rb +++ b/lib/active_record/turntable/algorithm/range_algorithm.rb @@ -19,7 +19,6 @@ def calculate_idx(key) # { connection_name => weight, ... } def calculate_used_shards_with_weight(sequence_value) current_shard_idx = calculate_idx(sequence_value) - last_connection = calculate(sequence_value) shards = @config[:shards][0..current_shard_idx] weighted_hash = Hash.new { |h, k| h[k] = 0 } prev_max = 0 diff --git a/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb b/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb index e6ec8a52..0d239fba 100644 --- a/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb +++ b/lib/active_record/turntable/algorithm/range_bsearch_algorithm.rb @@ -23,7 +23,6 @@ def calculate_idx(key) # { connection_name => weight, ... } def calculate_used_shards_with_weight(sequence_value) current_shard_idx = calculate_idx(sequence_value) - last_connection = calculate(sequence_value) shards = @config[:shards][0..current_shard_idx] weighted_hash = Hash.new { |h, k| h[k] = 0 } prev_max = 0 diff --git a/lib/active_record/turntable/cluster_helper_methods.rb b/lib/active_record/turntable/cluster_helper_methods.rb index 7f5960f8..15634448 100644 --- a/lib/active_record/turntable/cluster_helper_methods.rb +++ b/lib/active_record/turntable/cluster_helper_methods.rb @@ -46,7 +46,7 @@ def weighted_random_shard_with(*klasses, &block) shards_weight = self.turntable_cluster.weighted_shards(self.current_sequence) sum = shards_weight.values.inject(&:+) idx = rand(sum) - shard, weight = shards_weight.find { |_k, v| + shard = shards_weight.find { |_k, v| (idx -= v) < 0 } self.connection.with_recursive_shards(shard.name, *klasses, &block) diff --git a/lib/active_record/turntable/helpers/test_helper.rb b/lib/active_record/turntable/helpers/test_helper.rb index 2160e96d..9c9db839 100644 --- a/lib/active_record/turntable/helpers/test_helper.rb +++ b/lib/active_record/turntable/helpers/test_helper.rb @@ -1,8 +1,8 @@ module ActiveRecord::Turntable module Helpers module TestHelper - # all shards - def FabricateAll(name, overrides = {}, &block) + # Execute fabricate to all turntable shards + def FabricateAll(name, overrides = {}, &block) # rubocop:disable Style/MethodName obj = Fabrication::Fabricator.generate(name, { save: true, }, overrides, &block) diff --git a/lib/active_record/turntable/migration.rb b/lib/active_record/turntable/migration.rb index 812f1688..bc73e336 100644 --- a/lib/active_record/turntable/migration.rb +++ b/lib/active_record/turntable/migration.rb @@ -52,7 +52,6 @@ def create_sequence_for(table_name, options = {}) options = options.merge(id: false) # TODO: pkname should be pulled from table definitions - pkname = "id" sequence_table_name = ActiveRecord::Turntable::Sequencer.sequence_name(table_name, "id") create_table(sequence_table_name, options) do |t| t.integer :id, limit: 8 @@ -62,7 +61,6 @@ def create_sequence_for(table_name, options = {}) def drop_sequence_for(table_name, options = {}) # TODO: pkname should be pulled from table definitions - pkname = "id" sequence_table_name = ActiveRecord::Turntable::Sequencer.sequence_name(table_name, "id") drop_table(sequence_table_name) end diff --git a/lib/active_record/turntable/mixer.rb b/lib/active_record/turntable/mixer.rb index e711c9c1..48682608 100644 --- a/lib/active_record/turntable/mixer.rb +++ b/lib/active_record/turntable/mixer.rb @@ -116,12 +116,12 @@ def build_shards_with_same_query(shards, query) def bind_sql(sql, binds) # TODO: substitution value should be determined by adapter query = sql.is_a?(String) ? sql : @proxy.to_sql(sql, binds ? binds.dup : []) - query = if query.include?("\0") && binds.is_a?(Array) && binds[0].is_a?(Array) && binds[0][0].is_a?(ActiveRecord::ConnectionAdapters::Column) - binds = binds.dup - query.gsub("\0") { @proxy.master.connection.quote(*binds.shift.reverse) } - else - query - end + if query.include?("\0") && binds.is_a?(Array) && binds[0].is_a?(Array) && binds[0][0].is_a?(ActiveRecord::ConnectionAdapters::Column) + binds = binds.dup + query.gsub("\0") { @proxy.master.connection.quote(*binds.shift.reverse) } + else + query + end end def build_select_fader(tree, method, query, *args, &block) From 25c1c01297cf7c6bc96d1558a1d4d9de2a4aca81 Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 13 Feb 2017 16:25:41 +0900 Subject: [PATCH 106/125] Resolve RSpec/FilePath RSpec/NestedGroups --- .rubocop_todo.yml | 1 - spec/active_record/finder_methods_spec.rb | 38 ++++++++++++++++++ ...spec.rb => cluster_helper_methods_spec.rb} | 0 spec/active_record/turntable/finder_spec.rb | 40 ------------------- .../{active_record_ext => }/migration_spec.rb | 2 +- 5 files changed, 39 insertions(+), 42 deletions(-) create mode 100644 spec/active_record/finder_methods_spec.rb rename spec/active_record/turntable/{transaction_spec.rb => cluster_helper_methods_spec.rb} (100%) delete mode 100644 spec/active_record/turntable/finder_spec.rb rename spec/active_record/turntable/{active_record_ext => }/migration_spec.rb (91%) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 7ac03fd3..3499b3b8 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -82,7 +82,6 @@ RSpec/EmptyExampleGroup: RSpec/FilePath: Exclude: - 'spec/active_record/turntable/active_record_ext/fixture_set_spec.rb' - - 'spec/active_record/turntable/active_record_ext/migration_spec.rb' - 'spec/active_record/turntable/active_record_ext/test_fixtures_spec.rb' # Offense count: 11 diff --git a/spec/active_record/finder_methods_spec.rb b/spec/active_record/finder_methods_spec.rb new file mode 100644 index 00000000..a3034276 --- /dev/null +++ b/spec/active_record/finder_methods_spec.rb @@ -0,0 +1,38 @@ +require "spec_helper" + +describe ActiveRecord::FinderMethods do + before(:all) do + reload_turntable!(File.join(File.dirname(__FILE__), "../config/turntable.yml")) + end + + before do + establish_connection_to(:test) + truncate_shard + user + end + + let(:user) { + u = User.new + u.id = 1 + u.save + u + } + + context "#find" do + context "pass an ID that exists" do + subject { User.find(1) } + + it "returns user" do + is_expected.to eq(user) + end + end + + context "pass an ID that doesn't exist" do + subject { User.find(2) } + + it "raises error" do + expect { subject }.to raise_error + end + end + end +end diff --git a/spec/active_record/turntable/transaction_spec.rb b/spec/active_record/turntable/cluster_helper_methods_spec.rb similarity index 100% rename from spec/active_record/turntable/transaction_spec.rb rename to spec/active_record/turntable/cluster_helper_methods_spec.rb diff --git a/spec/active_record/turntable/finder_spec.rb b/spec/active_record/turntable/finder_spec.rb deleted file mode 100644 index f6c62cf6..00000000 --- a/spec/active_record/turntable/finder_spec.rb +++ /dev/null @@ -1,40 +0,0 @@ -require "spec_helper" - -describe ActiveRecord::FinderMethods do - before(:all) do - reload_turntable!(File.join(File.dirname(__FILE__), "../../config/turntable.yml")) - end - - context "User insert with id" do - before do - establish_connection_to(:test) - truncate_shard - user - end - - let(:user) { - u = User.new - u.id = 1 - u.save - u - } - - describe "User#find" do - context "With existing users.id" do - subject { User.find(1) } - - it "#find should be returns user" do - is_expected.to eq(user) - end - end - - context "With users.id not existing" do - subject { User.find(2) } - - it "#find should raise error" do - expect { subject }.to raise_error - end - end - end - end -end diff --git a/spec/active_record/turntable/active_record_ext/migration_spec.rb b/spec/active_record/turntable/migration_spec.rb similarity index 91% rename from spec/active_record/turntable/active_record_ext/migration_spec.rb rename to spec/active_record/turntable/migration_spec.rb index 82511a4c..3ac0dcf7 100644 --- a/spec/active_record/turntable/active_record_ext/migration_spec.rb +++ b/spec/active_record/turntable/migration_spec.rb @@ -2,7 +2,7 @@ describe ActiveRecord::Turntable::Migration do before(:all) do - reload_turntable!(File.join(File.dirname(__FILE__), "../../../config/turntable.yml")) + reload_turntable!(File.join(File.dirname(__FILE__), "../../config/turntable.yml")) end before(:each) do From d49529d907ec901f082b25dd6c51241a6b294baa Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 13 Feb 2017 16:33:51 +0900 Subject: [PATCH 107/125] Use implicit styles for `RSpec/HookArgument` --- .rubocop_todo.yml | 16 ---------------- .../association_preloader_spec.rb | 2 +- .../active_record_ext/association_spec.rb | 2 +- .../active_record_ext/clever_load_spec.rb | 2 +- .../active_record_ext/locking_optimistic_spec.rb | 2 +- .../active_record_ext/log_subscriber_spec.rb | 2 +- .../active_record_ext/persistence_spec.rb | 4 ++-- .../active_record_ext/schema_dumper_spec.rb | 2 +- .../active_record_ext/sequencer_spec.rb | 2 +- .../turntable/cluster_helper_methods_spec.rb | 2 +- spec/active_record/turntable/migration_spec.rb | 2 +- 11 files changed, 11 insertions(+), 27 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 3499b3b8..13a85c70 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -84,22 +84,6 @@ RSpec/FilePath: - 'spec/active_record/turntable/active_record_ext/fixture_set_spec.rb' - 'spec/active_record/turntable/active_record_ext/test_fixtures_spec.rb' -# Offense count: 11 -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: implicit, each, example -RSpec/HookArgument: - Exclude: - - 'spec/active_record/turntable/active_record_ext/association_preloader_spec.rb' - - 'spec/active_record/turntable/active_record_ext/association_spec.rb' - - 'spec/active_record/turntable/active_record_ext/clever_load_spec.rb' - - 'spec/active_record/turntable/active_record_ext/locking_optimistic_spec.rb' - - 'spec/active_record/turntable/active_record_ext/log_subscriber_spec.rb' - - 'spec/active_record/turntable/active_record_ext/migration_spec.rb' - - 'spec/active_record/turntable/active_record_ext/persistence_spec.rb' - - 'spec/active_record/turntable/active_record_ext/schema_dumper_spec.rb' - - 'spec/active_record/turntable/active_record_ext/sequencer_spec.rb' - - 'spec/active_record/turntable/transaction_spec.rb' - # Offense count: 3 RSpec/LeadingSubject: Exclude: diff --git a/spec/active_record/turntable/active_record_ext/association_preloader_spec.rb b/spec/active_record/turntable/active_record_ext/association_preloader_spec.rb index d51c4a5a..b695592a 100644 --- a/spec/active_record/turntable/active_record_ext/association_preloader_spec.rb +++ b/spec/active_record/turntable/active_record_ext/association_preloader_spec.rb @@ -5,7 +5,7 @@ reload_turntable!(File.join(File.dirname(__FILE__), "../../../config/turntable.yml")) end - before(:each) do + before do establish_connection_to(:test) truncate_shard end diff --git a/spec/active_record/turntable/active_record_ext/association_spec.rb b/spec/active_record/turntable/active_record_ext/association_spec.rb index a67458ed..cb338b6c 100644 --- a/spec/active_record/turntable/active_record_ext/association_spec.rb +++ b/spec/active_record/turntable/active_record_ext/association_spec.rb @@ -5,7 +5,7 @@ reload_turntable!(File.join(File.dirname(__FILE__), "../../../config/turntable.yml")) end - before(:each) do + before do establish_connection_to(:test) truncate_shard end diff --git a/spec/active_record/turntable/active_record_ext/clever_load_spec.rb b/spec/active_record/turntable/active_record_ext/clever_load_spec.rb index ac4c12f6..dd03499a 100644 --- a/spec/active_record/turntable/active_record_ext/clever_load_spec.rb +++ b/spec/active_record/turntable/active_record_ext/clever_load_spec.rb @@ -6,7 +6,7 @@ reload_turntable!(File.join(File.dirname(__FILE__), "../../../config/turntable.yml")) end - before(:each) do + before do establish_connection_to(:test) truncate_shard diff --git a/spec/active_record/turntable/active_record_ext/locking_optimistic_spec.rb b/spec/active_record/turntable/active_record_ext/locking_optimistic_spec.rb index c5ced86d..b37bf52d 100644 --- a/spec/active_record/turntable/active_record_ext/locking_optimistic_spec.rb +++ b/spec/active_record/turntable/active_record_ext/locking_optimistic_spec.rb @@ -5,7 +5,7 @@ reload_turntable!(File.join(File.dirname(__FILE__), "../../../config/turntable.yml")) end - before(:each) do + before do establish_connection_to(:test) truncate_shard end diff --git a/spec/active_record/turntable/active_record_ext/log_subscriber_spec.rb b/spec/active_record/turntable/active_record_ext/log_subscriber_spec.rb index ed9b10e4..8e6b9459 100644 --- a/spec/active_record/turntable/active_record_ext/log_subscriber_spec.rb +++ b/spec/active_record/turntable/active_record_ext/log_subscriber_spec.rb @@ -5,7 +5,7 @@ reload_turntable!(File.join(File.dirname(__FILE__), "../../../config/turntable.yml")) end - before(:each) do + before do establish_connection_to end diff --git a/spec/active_record/turntable/active_record_ext/persistence_spec.rb b/spec/active_record/turntable/active_record_ext/persistence_spec.rb index 7d2bb81e..6c1d2b27 100644 --- a/spec/active_record/turntable/active_record_ext/persistence_spec.rb +++ b/spec/active_record/turntable/active_record_ext/persistence_spec.rb @@ -6,12 +6,12 @@ reload_turntable!(File.join(File.dirname(__FILE__), "../../../config/turntable.yml")) end - before(:each) do + before do establish_connection_to(:test) truncate_shard end - around(:each) do |example| + around do |example| old = ActiveRecord::Base.logger ActiveRecord::Base.logger = Logger.new(STDOUT) example.run diff --git a/spec/active_record/turntable/active_record_ext/schema_dumper_spec.rb b/spec/active_record/turntable/active_record_ext/schema_dumper_spec.rb index 05787197..9dc24701 100644 --- a/spec/active_record/turntable/active_record_ext/schema_dumper_spec.rb +++ b/spec/active_record/turntable/active_record_ext/schema_dumper_spec.rb @@ -6,7 +6,7 @@ ActiveRecord::SchemaDumper.prepend(ActiveRecord::Turntable::ActiveRecordExt::SchemaDumper) end - before(:each) do + before do establish_connection_to(:test) end diff --git a/spec/active_record/turntable/active_record_ext/sequencer_spec.rb b/spec/active_record/turntable/active_record_ext/sequencer_spec.rb index 37e7f3f8..f6a09617 100644 --- a/spec/active_record/turntable/active_record_ext/sequencer_spec.rb +++ b/spec/active_record/turntable/active_record_ext/sequencer_spec.rb @@ -5,7 +5,7 @@ reload_turntable!(File.join(File.dirname(__FILE__), "../../../config/turntable.yml")) end - before(:each) do + before do establish_connection_to(:test) truncate_shard end diff --git a/spec/active_record/turntable/cluster_helper_methods_spec.rb b/spec/active_record/turntable/cluster_helper_methods_spec.rb index 180cb6e6..f638ef0f 100644 --- a/spec/active_record/turntable/cluster_helper_methods_spec.rb +++ b/spec/active_record/turntable/cluster_helper_methods_spec.rb @@ -5,7 +5,7 @@ reload_turntable!(File.join(File.dirname(__FILE__), "../../config/turntable.yml")) end - before(:each) do + before do establish_connection_to(:test) truncate_shard end diff --git a/spec/active_record/turntable/migration_spec.rb b/spec/active_record/turntable/migration_spec.rb index 3ac0dcf7..2564ddd9 100644 --- a/spec/active_record/turntable/migration_spec.rb +++ b/spec/active_record/turntable/migration_spec.rb @@ -5,7 +5,7 @@ reload_turntable!(File.join(File.dirname(__FILE__), "../../config/turntable.yml")) end - before(:each) do + before do establish_connection_to(:test) truncate_shard end From e27bff3470780898414af64f62b4a44a73239f0e Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 13 Feb 2017 16:45:18 +0900 Subject: [PATCH 108/125] `subject` definitions should precede `let` --- .rubocop_todo.yml | 7 ------- .../turntable/active_record_ext/persistence_spec.rb | 2 +- spec/active_record/turntable/connection_proxy_spec.rb | 3 +-- spec/active_record/turntable/query_cache_spec.rb | 2 +- 4 files changed, 3 insertions(+), 11 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 13a85c70..f866068d 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -84,13 +84,6 @@ RSpec/FilePath: - 'spec/active_record/turntable/active_record_ext/fixture_set_spec.rb' - 'spec/active_record/turntable/active_record_ext/test_fixtures_spec.rb' -# Offense count: 3 -RSpec/LeadingSubject: - Exclude: - - 'spec/active_record/turntable/active_record_ext/persistence_spec.rb' - - 'spec/active_record/turntable/connection_proxy_spec.rb' - - 'spec/active_record/turntable/query_cache_spec.rb' - # Offense count: 2 # Configuration parameters: SupportedStyles. # SupportedStyles: have_received, receive diff --git a/spec/active_record/turntable/active_record_ext/persistence_spec.rb b/spec/active_record/turntable/active_record_ext/persistence_spec.rb index 6c1d2b27..1a67e34c 100644 --- a/spec/active_record/turntable/active_record_ext/persistence_spec.rb +++ b/spec/active_record/turntable/active_record_ext/persistence_spec.rb @@ -39,6 +39,7 @@ } context "When creating record" do context "with blob column" do + subject { user } let(:blob_value) { "\123\123\123" } let(:user) { u = User.new(nickname: "x", blob: blob_value) @@ -46,7 +47,6 @@ u.save u } - subject { user } its(:blob) { is_expected.to eq(user.reload.blob) } end end diff --git a/spec/active_record/turntable/connection_proxy_spec.rb b/spec/active_record/turntable/connection_proxy_spec.rb index abe2b250..81166066 100644 --- a/spec/active_record/turntable/connection_proxy_spec.rb +++ b/spec/active_record/turntable/connection_proxy_spec.rb @@ -11,9 +11,8 @@ truncate_shard end - let(:cluster) { ActiveRecord::Turntable::Cluster.new(ActiveRecord::Base.turntable_config[:clusters][:user_cluster]) } subject { ActiveRecord::Turntable::ConnectionProxy.new(User, cluster) } - + let(:cluster) { ActiveRecord::Turntable::Cluster.new(ActiveRecord::Base.turntable_config[:clusters][:user_cluster]) } its(:master_connection) { is_expected.to eql(ActiveRecord::Base.connection) } end diff --git a/spec/active_record/turntable/query_cache_spec.rb b/spec/active_record/turntable/query_cache_spec.rb index 02935723..a55473ac 100644 --- a/spec/active_record/turntable/query_cache_spec.rb +++ b/spec/active_record/turntable/query_cache_spec.rb @@ -11,6 +11,7 @@ truncate_shard end + subject { mw.call({}) } let(:mw) { executor = Class.new(ActiveSupport::Executor) ActiveRecord::Turntable::QueryCache.install_executor_hooks executor @@ -20,7 +21,6 @@ } } } - subject { mw.call({}) } it "returns 200 response" do expect(subject.first).to eq(200) From 801f68f446c5a17f56c78fb72695d6bb291e3cc3 Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 13 Feb 2017 17:04:47 +0900 Subject: [PATCH 109/125] Prefer `have_received` style rather than `received` --- .rubocop_todo.yml | 6 ------ .../turntable/active_record_ext/persistence_spec.rb | 6 ++++-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index f866068d..579e158f 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -84,12 +84,6 @@ RSpec/FilePath: - 'spec/active_record/turntable/active_record_ext/fixture_set_spec.rb' - 'spec/active_record/turntable/active_record_ext/test_fixtures_spec.rb' -# Offense count: 2 -# Configuration parameters: SupportedStyles. -# SupportedStyles: have_received, receive -RSpec/MessageSpies: - EnforcedStyle: receive - # Offense count: 21 # Configuration parameters: Max. RSpec/NestedGroups: diff --git a/spec/active_record/turntable/active_record_ext/persistence_spec.rb b/spec/active_record/turntable/active_record_ext/persistence_spec.rb index 1a67e34c..ba258a0a 100644 --- a/spec/active_record/turntable/active_record_ext/persistence_spec.rb +++ b/spec/active_record/turntable/active_record_ext/persistence_spec.rb @@ -96,14 +96,16 @@ def on_update context "on update once" do it "callback should be called once" do - expect(user).to receive(:on_update).once + allow(user).to receive(:on_update) user.save + expect(user).to have_received(:on_update).once end end context "on destroy once" do it "callback should be called once" do - expect(user).to receive(:on_destroy).once + allow(user).to receive(:on_destroy) user.destroy + expect(user).to have_received(:on_destroy).once end end end From ad5359023e99b0ca58b04610e0173d3d909df51d Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 13 Feb 2017 17:10:13 +0900 Subject: [PATCH 110/125] Prefer `not_to` rather than `to_not` --- .rubocop_todo.yml | 11 ---------- .../association_preloader_spec.rb | 4 ++-- .../active_record_ext/association_spec.rb | 8 ++++---- .../active_record_ext/persistence_spec.rb | 20 +++++++++---------- .../active_record_ext/sequencer_spec.rb | 2 +- .../turntable/sql_tree_patch_spec.rb | 8 ++++---- 6 files changed, 21 insertions(+), 32 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 579e158f..69219cc9 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -95,17 +95,6 @@ RSpec/NestedGroups: - 'spec/active_record/turntable/finder_spec.rb' - 'spec/active_record/turntable/mixer_spec.rb' -# Offense count: 21 -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: not_to, to_not -RSpec/NotToNot: - Exclude: - - 'spec/active_record/turntable/active_record_ext/association_preloader_spec.rb' - - 'spec/active_record/turntable/active_record_ext/association_spec.rb' - - 'spec/active_record/turntable/active_record_ext/persistence_spec.rb' - - 'spec/active_record/turntable/active_record_ext/sequencer_spec.rb' - - 'spec/active_record/turntable/sql_tree_patch_spec.rb' - # Offense count: 4 RSpec/ScatteredSetup: Exclude: diff --git a/spec/active_record/turntable/active_record_ext/association_preloader_spec.rb b/spec/active_record/turntable/active_record_ext/association_preloader_spec.rb index b695592a..8ad79b24 100644 --- a/spec/active_record/turntable/active_record_ext/association_preloader_spec.rb +++ b/spec/active_record/turntable/active_record_ext/association_preloader_spec.rb @@ -42,7 +42,7 @@ context "associated objects has same turntable_key" do subject { CardsUser.where(user: user).preload(:cards_users_histories).first } - it { expect { subject }.to_not raise_error } + it { expect { subject }.not_to raise_error } it "its association should be loaded" do expect(subject.association(:cards_users_histories)).to be_loaded @@ -57,7 +57,7 @@ context "when foreign_shard_key option passed" do subject { CardsUser.where(user: user).preload(:events_users_histories_with_foreign_shard_key).first } - it { expect { subject }.to_not raise_error } + it { expect { subject }.not_to raise_error } it "its association should be loaded" do expect(subject.association(:events_users_histories_with_foreign_shard_key)).to be_loaded diff --git a/spec/active_record/turntable/active_record_ext/association_spec.rb b/spec/active_record/turntable/active_record_ext/association_spec.rb index cb338b6c..5a146ec7 100644 --- a/spec/active_record/turntable/active_record_ext/association_spec.rb +++ b/spec/active_record/turntable/active_record_ext/association_spec.rb @@ -38,7 +38,7 @@ context "When a model with has_one relation" do context "When the has_one associated object doesn't exists" do subject { user.user_status } - it { expect { subject }.to_not raise_error } + it { expect { subject }.not_to raise_error } end end @@ -52,13 +52,13 @@ context "associated objects has same turntable_key" do context "AssociationRelation#to_a" do subject { cards_user.cards_users_histories.to_a } - it { expect { subject }.to_not raise_error } + it { expect { subject }.not_to raise_error } it { is_expected.to include(*cards_users_histories.select { |history| history.cards_user_id == cards_user.id }) } end context "AssociationRelation#where" do subject { cards_user.cards_users_histories.where(id: cards_users_history.id).to_a } - it { expect { subject }.to_not raise_error } + it { expect { subject }.not_to raise_error } it { is_expected.to include(cards_users_history) } end end @@ -67,7 +67,7 @@ context "when foreign_shard_key option passed" do subject { cards_user.events_users_histories_with_foreign_shard_key.to_a } - it { expect { subject }.to_not raise_error } + it { expect { subject }.not_to raise_error } it { is_expected.to include(*events_users_histories.select { |history| history.cards_user_id == cards_user.id }) } end diff --git a/spec/active_record/turntable/active_record_ext/persistence_spec.rb b/spec/active_record/turntable/active_record_ext/persistence_spec.rb index ba258a0a..ad776636 100644 --- a/spec/active_record/turntable/active_record_ext/persistence_spec.rb +++ b/spec/active_record/turntable/active_record_ext/persistence_spec.rb @@ -58,7 +58,7 @@ ActiveRecord::Base.logger = Logger.new(strio) expect { user.save! - }.to_not raise_error + }.not_to raise_error expect(strio.string).to match(/WHERE `users`\.`id` = #{user.id}[^\s]*$/) end @@ -75,7 +75,7 @@ it "doesn't change the behavior when destroying" do strio = StringIO.new ActiveRecord::Base.logger = Logger.new(strio) - expect { user.destroy }.to_not raise_error + expect { user.destroy }.not_to raise_error expect(strio.string).to match(/WHERE `users`\.`id` = #{user.id}[^\s]*$/) end end @@ -118,7 +118,7 @@ def on_update ActiveRecord::Base.logger = Logger.new(strio) expect { cards_user.save! - }.to_not raise_error + }.not_to raise_error expect(strio.string).to match(/`cards_users`\.`user_id` = #{cards_user.user_id}[^\s]*($|\s)/) end @@ -138,7 +138,7 @@ def on_update ActiveRecord::Base.logger = Logger.new(strio) expect { cards_user.destroy - }.to_not raise_error + }.not_to raise_error expect(strio.string).to match(/`cards_users`\.`user_id` = #{cards_user.user_id}[^\s]*($|\s)/) end @@ -151,7 +151,7 @@ def on_update strio = StringIO.new ActiveRecord::Base.logger = Logger.new(strio) - expect { cards_user.reload }.to_not raise_error + expect { cards_user.reload }.not_to raise_error expect(strio.string.split("\n").select { |stmt| stmt =~ /SELECT/ and stmt !~ /Turntable/ }).to have(1).items end @@ -161,7 +161,7 @@ def on_update strio = StringIO.new ActiveRecord::Base.logger = Logger.new(strio) - expect { cards_user.touch }.to_not raise_error + expect { cards_user.touch }.not_to raise_error expect(strio.string.split("\n").select { |stmt| stmt =~ /UPDATE/ and stmt !~ /Turntable/ }).to have(1).items end @@ -170,7 +170,7 @@ def on_update strio = StringIO.new ActiveRecord::Base.logger = Logger.new(strio) - expect { cards_user.lock! }.to_not raise_error + expect { cards_user.lock! }.not_to raise_error expect(strio.string.split("\n").select { |stmt| stmt =~ /SELECT/ and stmt !~ /Turntable/ }).to have(1).items end @@ -179,7 +179,7 @@ def on_update strio = StringIO.new ActiveRecord::Base.logger = Logger.new(strio) - expect { cards_user.update_columns(num: 10) }.to_not raise_error + expect { cards_user.update_columns(num: 10) }.not_to raise_error expect(strio.string.split("\n").select { |stmt| stmt =~ /UPDATE/ and stmt !~ /Turntable/ }).to have(1).items end end @@ -191,7 +191,7 @@ def on_update ActiveRecord::Base.logger = Logger.new(strio) expect { card.save! - }.to_not raise_error + }.not_to raise_error expect(strio.string).to match(/WHERE `cards`\.`id` = #{card.id}[^\s]*$/) end @@ -200,7 +200,7 @@ def on_update ActiveRecord::Base.logger = Logger.new(strio) expect { card.destroy - }.to_not raise_error + }.not_to raise_error expect(strio.string).to match(/WHERE `cards`\.`id` = #{card.id}[^\s]*$/) end end diff --git a/spec/active_record/turntable/active_record_ext/sequencer_spec.rb b/spec/active_record/turntable/active_record_ext/sequencer_spec.rb index f6a09617..0e36f4fd 100644 --- a/spec/active_record/turntable/active_record_ext/sequencer_spec.rb +++ b/spec/active_record/turntable/active_record_ext/sequencer_spec.rb @@ -12,7 +12,7 @@ context "With sequencer enabled model" do subject { User } - its(:sequence_name) { is_expected.to_not be_nil } + its(:sequence_name) { is_expected.not_to be_nil } end context "With sequencer disabled model" do diff --git a/spec/active_record/turntable/sql_tree_patch_spec.rb b/spec/active_record/turntable/sql_tree_patch_spec.rb index 1a197507..be02ff6e 100644 --- a/spec/active_record/turntable/sql_tree_patch_spec.rb +++ b/spec/active_record/turntable/sql_tree_patch_spec.rb @@ -8,7 +8,7 @@ context "Insert query with binary string" do subject { SQLTree["INSERT INTO `hogehoge` (`name`) VALUES (x'deadbeef')"] } - it { expect { subject }.to_not raise_error } + it { expect { subject }.not_to raise_error } its(:to_sql) { is_expected.to include("x'deadbeef") } end @@ -16,7 +16,7 @@ ["FORCE INDEX", "IGNORE INDEX", "USE INDEX"].each do |hint| context hint do subject { SQLTree["SELECT * FROM table #{hint} (`foo`) WHERE field = 'value'"] } - it { expect { subject }.to_not raise_error } + it { expect { subject }.not_to raise_error } its(:to_sql) { is_expected.to include("#{hint} (`foo`)") } end end @@ -24,11 +24,11 @@ context "Select query without index hint" do subject { SQLTree["SELECT * FROM table WHERE field = 'value'"] } - it { expect { subject }.to_not raise_error } + it { expect { subject }.not_to raise_error } end context "Delete query" do subject { SQLTree["DELETE FROM table"] } - it { expect { subject }.to_not raise_error } + it { expect { subject }.not_to raise_error } end end From 261c7c084814ad6ddb63bbb932b674169525df95 Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 13 Feb 2017 17:14:22 +0900 Subject: [PATCH 111/125] Put multiple before hooks into a single hook --- .rubocop_todo.yml | 6 ------ .../turntable/active_record_ext/locking_optimistic_spec.rb | 3 --- .../turntable/active_record_ext/test_fixtures_spec.rb | 5 +---- 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 69219cc9..8c7f9f43 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -95,12 +95,6 @@ RSpec/NestedGroups: - 'spec/active_record/turntable/finder_spec.rb' - 'spec/active_record/turntable/mixer_spec.rb' -# Offense count: 4 -RSpec/ScatteredSetup: - Exclude: - - 'spec/active_record/turntable/active_record_ext/locking_optimistic_spec.rb' - - 'spec/active_record/turntable/active_record_ext/test_fixtures_spec.rb' - # Offense count: 1 Style/AccessorMethodName: Exclude: diff --git a/spec/active_record/turntable/active_record_ext/locking_optimistic_spec.rb b/spec/active_record/turntable/active_record_ext/locking_optimistic_spec.rb index b37bf52d..42509740 100644 --- a/spec/active_record/turntable/active_record_ext/locking_optimistic_spec.rb +++ b/spec/active_record/turntable/active_record_ext/locking_optimistic_spec.rb @@ -8,9 +8,6 @@ before do establish_connection_to(:test) truncate_shard - end - - before do ActiveRecord::Base.turntable_config.instance_variable_get(:@config)[:raise_on_not_specified_shard_update] = true end diff --git a/spec/active_record/turntable/active_record_ext/test_fixtures_spec.rb b/spec/active_record/turntable/active_record_ext/test_fixtures_spec.rb index fcd90bdb..553f2dda 100644 --- a/spec/active_record/turntable/active_record_ext/test_fixtures_spec.rb +++ b/spec/active_record/turntable/active_record_ext/test_fixtures_spec.rb @@ -11,6 +11,7 @@ before do establish_connection_to(:test) truncate_shard + test_fixture_class.fixture_path = fixtures_root end let(:fixtures_root) { File.join(File.dirname(__FILE__), "../../../fixtures") } @@ -19,10 +20,6 @@ let(:test_fixture) { test_fixture_class.new("test") } let(:cards) { YAML.load(ERB.new(IO.read(fixture_file)).result) } - before do - test_fixture_class.fixture_path = fixtures_root - end - describe "#setup_fixtures" do after do test_fixture.teardown_fixtures From 3e420dad279a9468cfce6451345b740836f06dd0 Mon Sep 17 00:00:00 2001 From: gussan Date: Mon, 13 Feb 2017 17:53:08 +0900 Subject: [PATCH 112/125] Fix accessor method name --- .rubocop_todo.yml | 5 ----- lib/active_record/turntable/seq_shard.rb | 2 +- lib/active_record/turntable/shard.rb | 16 ++++++++-------- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 8c7f9f43..ae6eb09f 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -95,11 +95,6 @@ RSpec/NestedGroups: - 'spec/active_record/turntable/finder_spec.rb' - 'spec/active_record/turntable/mixer_spec.rb' -# Offense count: 1 -Style/AccessorMethodName: - Exclude: - - 'lib/active_record/turntable/shard.rb' - # Offense count: 15 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles, ProceduralMethods, FunctionalMethods, IgnoredMethods. diff --git a/lib/active_record/turntable/seq_shard.rb b/lib/active_record/turntable/seq_shard.rb index 2629be17..da0cadc0 100644 --- a/lib/active_record/turntable/seq_shard.rb +++ b/lib/active_record/turntable/seq_shard.rb @@ -3,7 +3,7 @@ class SeqShard < Shard private def create_connection_class - klass = get_or_set_connection_class + klass = connection_class_instance klass.remove_connection klass.establish_connection ActiveRecord::Base.connection_pool.spec.config[:seq][name].with_indifferent_access klass diff --git a/lib/active_record/turntable/shard.rb b/lib/active_record/turntable/shard.rb index 833bdbe8..18eb1199 100644 --- a/lib/active_record/turntable/shard.rb +++ b/lib/active_record/turntable/shard.rb @@ -33,7 +33,14 @@ def connection_klass @connection_klass ||= create_connection_class end - def get_or_set_connection_class + def create_connection_class + klass = connection_class_instance + klass.remove_connection + klass.establish_connection ActiveRecord::Base.connection_pool.spec.config[:shards][name].with_indifferent_access + klass + end + + def connection_class_instance if Connections.const_defined?(name.classify) klass = Connections.const_get(name.classify) else @@ -43,12 +50,5 @@ def get_or_set_connection_class end klass end - - def create_connection_class - klass = get_or_set_connection_class - klass.remove_connection - klass.establish_connection ActiveRecord::Base.connection_pool.spec.config[:shards][name].with_indifferent_access - klass - end end end From c3128676ec6a4a71fb251d5eb7710eee161ef8fd Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 15 Feb 2017 16:16:36 +0900 Subject: [PATCH 113/125] Revert rubocop Style/RedundantException --- lib/active_record/turntable/active_record_ext/fixtures.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/active_record/turntable/active_record_ext/fixtures.rb b/lib/active_record/turntable/active_record_ext/fixtures.rb index d674a09b..189ca286 100644 --- a/lib/active_record/turntable/active_record_ext/fixtures.rb +++ b/lib/active_record/turntable/active_record_ext/fixtures.rb @@ -70,9 +70,10 @@ def self.create_fixtures(fixtures_directory, fixture_set_names, class_names = {} end module TestFixtures + # rubocop:disable Style/RedundantException def setup_fixtures(config = ActiveRecord::Base) if pre_loaded_fixtures && !use_transactional_fixtures - raise "pre_loaded_fixtures requires use_transactional_fixtures" + raise RuntimeError, "pre_loaded_fixtures requires use_transactional_fixtures" end @fixture_cache = {} @@ -102,6 +103,7 @@ def setup_fixtures(config = ActiveRecord::Base) # Instantiate fixtures for every test if requested. instantiate_fixtures if use_instantiated_fixtures end + # rubocop:enable Style/RedundantException def enlist_fixture_connections ActiveRecord::Base.connection_handler.connection_pool_list.map(&:connection) + From ba34007a3e63797f5ea42954ea525b4c6266d88a Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 15 Feb 2017 16:52:12 +0900 Subject: [PATCH 114/125] Fixes Style/ClassVars --- .rubocop_todo.yml | 8 -------- lib/active_record/turntable.rb | 4 ++-- .../turntable/active_record_ext/fixtures.rb | 4 ++-- lib/active_record/turntable/sequencer.rb | 16 +++++++++------- lib/active_record/turntable/sequencer/barrage.rb | 5 +++-- 5 files changed, 16 insertions(+), 21 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index ae6eb09f..f017640d 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -114,14 +114,6 @@ Style/BlockDelimiters: - 'lib/active_record/turntable/connection_proxy.rb' - 'script/performance/algorithm' -# Offense count: 7 -Style/ClassVars: - Exclude: - - 'lib/active_record/turntable.rb' - - 'lib/active_record/turntable/active_record_ext/fixtures.rb' - - 'lib/active_record/turntable/sequencer.rb' - - 'lib/active_record/turntable/sequencer/barrage.rb' - # Offense count: 1 # Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms. # AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS diff --git a/lib/active_record/turntable.rb b/lib/active_record/turntable.rb index 3aa5f51f..a4eebd3f 100644 --- a/lib/active_record/turntable.rb +++ b/lib/active_record/turntable.rb @@ -45,13 +45,13 @@ module ClassMethods DEFAULT_PATH = File.dirname(File.dirname(__FILE__)) def turntable_config_file - @@turntable_config_file ||= + @turntable_config_file ||= File.join(defined?(::Rails) ? ::Rails.root.to_s : DEFAULT_PATH, "config/turntable.yml") end def turntable_config_file=(filename) - @@turntable_config_file = filename + @turntable_config_file = filename end def turntable_config diff --git a/lib/active_record/turntable/active_record_ext/fixtures.rb b/lib/active_record/turntable/active_record_ext/fixtures.rb index 189ca286..b1d0455d 100644 --- a/lib/active_record/turntable/active_record_ext/fixtures.rb +++ b/lib/active_record/turntable/active_record_ext/fixtures.rb @@ -70,7 +70,7 @@ def self.create_fixtures(fixtures_directory, fixture_set_names, class_names = {} end module TestFixtures - # rubocop:disable Style/RedundantException + # rubocop:disable Style/ClassVars, Style/RedundantException def setup_fixtures(config = ActiveRecord::Base) if pre_loaded_fixtures && !use_transactional_fixtures raise RuntimeError, "pre_loaded_fixtures requires use_transactional_fixtures" @@ -103,7 +103,7 @@ def setup_fixtures(config = ActiveRecord::Base) # Instantiate fixtures for every test if requested. instantiate_fixtures if use_instantiated_fixtures end - # rubocop:enable Style/RedundantException + # rubocop:enable Style/ClassVars, Style/RedundantException def enlist_fixture_connections ActiveRecord::Base.connection_handler.connection_pool_list.map(&:connection) + diff --git a/lib/active_record/turntable/sequencer.rb b/lib/active_record/turntable/sequencer.rb index c9b83783..3ec5ef8e 100644 --- a/lib/active_record/turntable/sequencer.rb +++ b/lib/active_record/turntable/sequencer.rb @@ -13,26 +13,28 @@ class Sequencer autoload :Barrage end - @@sequence_types = { + class_attribute :sequence_types + class_attribute :sequences + class_attribute :tables + + self.sequence_types = { api: Api, mysql: Mysql, barrage: Barrage, } - - @@sequences = {} - @@tables = {} - cattr_reader :sequences, :tables + self.sequences = {} + self.tables = {} class << self def build(klass, sequence_name = nil, cluster_name = nil) sequence_name ||= current_cluster_config_for(cluster_name || klass)[:seq].keys.first seq_config = current_cluster_config_for(cluster_name || klass)[:seq][sequence_name] seq_type = (seq_config[:seq_type] ? seq_config[:seq_type].to_sym : :mysql) - @@tables[klass.table_name] ||= (@@sequences[sequence_name(klass.table_name, klass.primary_key)] ||= @@sequence_types[seq_type].new(klass, seq_config)) + tables[klass.table_name] ||= (sequences[sequence_name(klass.table_name, klass.primary_key)] ||= sequence_types[seq_type].new(klass, seq_config)) end def has_sequencer?(table_name) - !!@@tables[table_name] + !!tables[table_name] end def sequence_name(table_name, pk) diff --git a/lib/active_record/turntable/sequencer/barrage.rb b/lib/active_record/turntable/sequencer/barrage.rb index 3e673e41..690daa2f 100644 --- a/lib/active_record/turntable/sequencer/barrage.rb +++ b/lib/active_record/turntable/sequencer/barrage.rb @@ -1,7 +1,8 @@ module ActiveRecord::Turntable class Sequencer class Barrage < Sequencer - @@unique_barrage_instance = {} + class_attribute :unique_barrage_instance + self.unique_barrage_instance = {} def initialize(klass, options = {}) require "barrage" @@ -20,7 +21,7 @@ def current_sequence_value(sequence_name) private def barrage - @@unique_barrage_instance[@options] ||= ::Barrage.new(@options) + self.unique_barrage_instance[@options] ||= ::Barrage.new(@options) end end end From d56b61e9c06b23c90a1712c8f78aaed234d6fb86 Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 15 Feb 2017 16:56:04 +0900 Subject: [PATCH 115/125] Ignore Style/FileName on entrypoint --- .rubocop_todo.yml | 7 ------- lib/activerecord-turntable.rb | 1 + 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index f017640d..6f233b6b 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -114,13 +114,6 @@ Style/BlockDelimiters: - 'lib/active_record/turntable/connection_proxy.rb' - 'script/performance/algorithm' -# Offense count: 1 -# Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms. -# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS -Style/FileName: - Exclude: - - 'lib/activerecord-turntable.rb' - # Offense count: 2 # Configuration parameters: MinBodyLength. Style/GuardClause: diff --git a/lib/activerecord-turntable.rb b/lib/activerecord-turntable.rb index cb6196ac..aa9085f0 100644 --- a/lib/activerecord-turntable.rb +++ b/lib/activerecord-turntable.rb @@ -1,2 +1,3 @@ +# rubocop:disable Style/FileName require "active_record" require "active_record/turntable" From 20b41c25a3b26ec8bd48718ecb6973f1fb8318f2 Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 15 Feb 2017 19:31:41 +0900 Subject: [PATCH 116/125] Fix Style/IfWithSemiColon --- .rubocop_todo.yml | 5 ----- spec/active_record/turntable_spec.rb | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 6f233b6b..d38823f8 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -120,11 +120,6 @@ Style/GuardClause: Exclude: - 'lib/active_record/turntable/sql_tree_patch.rb' -# Offense count: 1 -Style/IfWithSemicolon: - Exclude: - - 'spec/active_record/turntable_spec.rb' - # Offense count: 4 Style/MethodCalledOnDoEndBlock: Exclude: diff --git a/spec/active_record/turntable_spec.rb b/spec/active_record/turntable_spec.rb index ae2b0b63..30976de6 100644 --- a/spec/active_record/turntable_spec.rb +++ b/spec/active_record/turntable_spec.rb @@ -7,7 +7,7 @@ context "#config_file" do it "returns Rails.root/config/turntable.yml default" do - unless defined?(::Rails); class ::Rails; end; end + stub_const("Rails", Class.new) allow(Rails).to receive(:root) { "/path/to/rails_root" } ActiveRecord::Base.turntable_config_file = nil expect(ActiveRecord::Base.turntable_config_file).to eq("/path/to/rails_root/config/turntable.yml") From 67f1761e19b12eaa285e11ecd563e79186b9008a Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 15 Feb 2017 19:55:10 +0900 Subject: [PATCH 117/125] Remove todo Style/MethodName --- .rubocop_todo.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index d38823f8..82e508bc 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -133,12 +133,6 @@ Style/MethodMissing: Exclude: - 'lib/active_record/turntable/connection_proxy.rb' -# Offense count: 1 -# Configuration parameters: SupportedStyles. -# SupportedStyles: snake_case, camelCase -Style/MethodName: - EnforcedStyle: snake_case - # Offense count: 1 # Configuration parameters: EnforcedStyle, SupportedStyles. # SupportedStyles: module_function, extend_self From d815b814493049776f915428c26123e2ec5313d3 Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 15 Feb 2017 20:04:33 +0900 Subject: [PATCH 118/125] Ignore Style/MethodMissing because it is a proxy object --- .rubocop_todo.yml | 5 ----- lib/active_record/turntable/connection_proxy.rb | 2 ++ 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 82e508bc..106357f5 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -128,11 +128,6 @@ Style/MethodCalledOnDoEndBlock: - 'lib/active_record/turntable/mixer/fader/update_shards_merge_result.rb' - 'lib/active_record/turntable/sql_tree_patch.rb' -# Offense count: 1 -Style/MethodMissing: - Exclude: - - 'lib/active_record/turntable/connection_proxy.rb' - # Offense count: 1 # Configuration parameters: EnforcedStyle, SupportedStyles. # SupportedStyles: module_function, extend_self diff --git a/lib/active_record/turntable/connection_proxy.rb b/lib/active_record/turntable/connection_proxy.rb index bcc27ad8..b300fe91 100644 --- a/lib/active_record/turntable/connection_proxy.rb +++ b/lib/active_record/turntable/connection_proxy.rb @@ -53,6 +53,7 @@ def clear_query_cache end end + # rubocop:disable Style/MethodMissing def method_missing(method, *args, &block) clear_query_cache_if_needed(method) if shard_fixed? @@ -69,6 +70,7 @@ def method_missing(method, *args, &block) connection.send(method, *args, &block) end end + # rubocop:enable Style/MethodMissing def respond_to_missing?(method, include_private = false) connection.send(:respond_to?, method, include_private) From 5f0aec594eb7e6ca7876947f01be0aaf7a7d9413 Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 15 Feb 2017 20:08:51 +0900 Subject: [PATCH 119/125] Prefer `module_function` rather than `extend self` --- .rubocop_todo.yml | 7 ------- lib/active_record/turntable/util.rb | 6 ++++-- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 106357f5..59ec68b0 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -128,13 +128,6 @@ Style/MethodCalledOnDoEndBlock: - 'lib/active_record/turntable/mixer/fader/update_shards_merge_result.rb' - 'lib/active_record/turntable/sql_tree_patch.rb' -# Offense count: 1 -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: module_function, extend_self -Style/ModuleFunction: - Exclude: - - 'lib/active_record/turntable/util.rb' - # Offense count: 1 Style/MultilineTernaryOperator: Exclude: diff --git a/lib/active_record/turntable/util.rb b/lib/active_record/turntable/util.rb index a88e786b..e04c152a 100644 --- a/lib/active_record/turntable/util.rb +++ b/lib/active_record/turntable/util.rb @@ -1,7 +1,5 @@ module ActiveRecord::Turntable module Util - extend self - def ar_version_equals_or_later?(version) ar_version >= Gem::Version.new(version) end @@ -13,5 +11,9 @@ def ar_version_earlier_than?(version) def ar_version ActiveRecord.gem_version end + + module_function :ar_version_equals_or_later?, + :ar_version_earlier_than?, + :ar_version end end From d324c1ae020476b177718f6104aaf0c62cb0c1e5 Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 15 Feb 2017 20:18:44 +0900 Subject: [PATCH 120/125] Fix Style/MultilineTernaryOperator --- .rubocop_todo.yml | 5 ----- lib/active_record/turntable.rb | 8 +++++--- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 59ec68b0..c08d5dd7 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -128,11 +128,6 @@ Style/MethodCalledOnDoEndBlock: - 'lib/active_record/turntable/mixer/fader/update_shards_merge_result.rb' - 'lib/active_record/turntable/sql_tree_patch.rb' -# Offense count: 1 -Style/MultilineTernaryOperator: - Exclude: - - 'lib/active_record/turntable.rb' - # Offense count: 1 Style/NestedTernaryOperator: Exclude: diff --git a/lib/active_record/turntable.rb b/lib/active_record/turntable.rb index a4eebd3f..db9a6826 100644 --- a/lib/active_record/turntable.rb +++ b/lib/active_record/turntable.rb @@ -45,15 +45,17 @@ module ClassMethods DEFAULT_PATH = File.dirname(File.dirname(__FILE__)) def turntable_config_file - @turntable_config_file ||= - File.join(defined?(::Rails) ? - ::Rails.root.to_s : DEFAULT_PATH, "config/turntable.yml") + @turntable_config_file ||= File.join(turntable_app_root_path, "config/turntable.yml") end def turntable_config_file=(filename) @turntable_config_file = filename end + def turntable_app_root_path + defined?(::Rails.root) ? ::Rails.root.to_s : DEFAULT_PATH + end + def turntable_config ActiveRecord::Turntable::Config.instance end From 512f7c85a92bec028d341da65f3e71b563eb401c Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 15 Feb 2017 20:29:26 +0900 Subject: [PATCH 121/125] Remove a nested ternary operator --- .rubocop_todo.yml | 5 ----- lib/active_record/turntable/mixer.rb | 3 ++- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index c08d5dd7..29151706 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -128,11 +128,6 @@ Style/MethodCalledOnDoEndBlock: - 'lib/active_record/turntable/mixer/fader/update_shards_merge_result.rb' - 'lib/active_record/turntable/sql_tree_patch.rb' -# Offense count: 1 -Style/NestedTernaryOperator: - Exclude: - - 'lib/active_record/turntable/mixer.rb' - # Offense count: 5 # Cop supports --auto-correct. # Configuration parameters: PreferredDelimiters. diff --git a/lib/active_record/turntable/mixer.rb b/lib/active_record/turntable/mixer.rb index 48682608..b60ed535 100644 --- a/lib/active_record/turntable/mixer.rb +++ b/lib/active_record/turntable/mixer.rb @@ -114,8 +114,9 @@ def build_shards_with_same_query(shards, query) end def bind_sql(sql, binds) + binds = binds ? binds.dup : [] # TODO: substitution value should be determined by adapter - query = sql.is_a?(String) ? sql : @proxy.to_sql(sql, binds ? binds.dup : []) + query = sql.is_a?(String) ? sql : @proxy.to_sql(sql, binds) if query.include?("\0") && binds.is_a?(Array) && binds[0].is_a?(Array) && binds[0][0].is_a?(ActiveRecord::ConnectionAdapters::Column) binds = binds.dup query.gsub("\0") { @proxy.master.connection.quote(*binds.shift.reverse) } From 31c4b0f86185b2474623830b9aaab3dc6579b8b2 Mon Sep 17 00:00:00 2001 From: gussan Date: Wed, 15 Feb 2017 20:44:56 +0900 Subject: [PATCH 122/125] Fix Style/RegexpLiteral --- .rubocop_todo.yml | 9 --------- Guardfile | 2 +- lib/active_record/turntable/mixer.rb | 2 +- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 29151706..35dad93a 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -142,15 +142,6 @@ Style/RedundantReturn: Exclude: - 'lib/active_record/turntable/sql_tree_patch.rb' -# Offense count: 2 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles, AllowInnerSlashes. -# SupportedStyles: slashes, percent_r, mixed -Style/RegexpLiteral: - Exclude: - - 'Guardfile' - - 'lib/active_record/turntable/mixer.rb' - # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, SupportedStyles, AllowSafeAssignment. diff --git a/Guardfile b/Guardfile index 14b3f19b..a5eabb1d 100644 --- a/Guardfile +++ b/Guardfile @@ -11,6 +11,6 @@ guard "rspec", end guard :rubocop do - watch(%r{.+\.rb$}) + watch(/.+\.rb$/) watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) } end diff --git a/lib/active_record/turntable/mixer.rb b/lib/active_record/turntable/mixer.rb index b60ed535..36276c4d 100644 --- a/lib/active_record/turntable/mixer.rb +++ b/lib/active_record/turntable/mixer.rb @@ -12,7 +12,7 @@ class Mixer delegate :logger, to: ActiveRecord::Base - NOT_USED_FOR_SHARDING_OPERATORS_REGEXP = /\A(NOT IN|IS|IS NOT|BETWEEN|LIKE|\!\=|<<|>>|<>|>\=|<=|[\*\+\-\/\%\|\&><])\z/ + NOT_USED_FOR_SHARDING_OPERATORS_REGEXP = /\A(NOT IN|IS|IS NOT|BETWEEN|LIKE|!=|<<|>>|<>|>=|<=|[*+%|&><-])\z/ def initialize(proxy) @proxy = proxy From fb5fd0b56d1b7622e652bc798fd63da201d1cf5d Mon Sep 17 00:00:00 2001 From: gussan Date: Thu, 16 Feb 2017 18:10:24 +0900 Subject: [PATCH 123/125] Fixes rspec warnings on raises_error with no specific error --- spec/active_record/finder_methods_spec.rb | 8 ++------ .../active_record_ext/association_preloader_spec.rb | 4 ++-- .../turntable/active_record_ext/association_spec.rb | 4 ++-- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/spec/active_record/finder_methods_spec.rb b/spec/active_record/finder_methods_spec.rb index a3034276..114bdc10 100644 --- a/spec/active_record/finder_methods_spec.rb +++ b/spec/active_record/finder_methods_spec.rb @@ -22,17 +22,13 @@ context "pass an ID that exists" do subject { User.find(1) } - it "returns user" do - is_expected.to eq(user) - end + it { is_expected.to eq(user) } end context "pass an ID that doesn't exist" do subject { User.find(2) } - it "raises error" do - expect { subject }.to raise_error - end + it { expect { subject }.to raise_error(ActiveRecord::RecordNotFound) } end end end diff --git a/spec/active_record/turntable/active_record_ext/association_preloader_spec.rb b/spec/active_record/turntable/active_record_ext/association_preloader_spec.rb index 8ad79b24..986b0ffc 100644 --- a/spec/active_record/turntable/active_record_ext/association_preloader_spec.rb +++ b/spec/active_record/turntable/active_record_ext/association_preloader_spec.rb @@ -1,6 +1,6 @@ require "spec_helper" -describe ActiveRecord::Turntable::ActiveRecordExt::Association do +describe ActiveRecord::Turntable::ActiveRecordExt::AssociationPreloader do before(:all) do reload_turntable!(File.join(File.dirname(__FILE__), "../../../config/turntable.yml")) end @@ -71,7 +71,7 @@ context "when foreign_shard_key option is not passed" do subject { CardsUser.where(user: user).preload(:events_users_histories).first } - it { expect { subject }.to raise_error } + it { expect { subject }.to raise_error(ActiveRecord::Turntable::CannotSpecifyShardError) } end end end diff --git a/spec/active_record/turntable/active_record_ext/association_spec.rb b/spec/active_record/turntable/active_record_ext/association_spec.rb index 5a146ec7..67bc61b3 100644 --- a/spec/active_record/turntable/active_record_ext/association_spec.rb +++ b/spec/active_record/turntable/active_record_ext/association_spec.rb @@ -72,9 +72,9 @@ end context "when foreign_shard_key option is not passed" do - subject { CardsUser.where(user: user).events_users_histories } + subject { cards_user.events_users_histories.to_a } - it { expect { subject }.to raise_error } + it { expect { subject }.to raise_error(ActiveRecord::Turntable::CannotSpecifyShardError) } end end end From dab68a8c7c39b85aaec5bbde230e8959212ef44f Mon Sep 17 00:00:00 2001 From: gussan Date: Thu, 16 Feb 2017 18:57:31 +0900 Subject: [PATCH 124/125] Fix warning: $INPUT_RECORD_SEPARATOR not initialized --- activerecord-turntable.gemspec | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/activerecord-turntable.gemspec b/activerecord-turntable.gemspec index 6ad38d77..4817f4fc 100644 --- a/activerecord-turntable.gemspec +++ b/activerecord-turntable.gemspec @@ -16,9 +16,10 @@ Gem::Specification.new do |spec| "CHANGELOG.md", ] - spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR) + spec.files = `git ls-files -z`.split("\x0").reject do |f| + f.match(%r{^(test|spec|features)/}) + end spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } - spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ["lib"] spec.required_ruby_version = ">= 2.2.2" From 985a75fc6dc36421277eab0f8b2dc17ec2b29a96 Mon Sep 17 00:00:00 2001 From: gussan Date: Fri, 17 Feb 2017 15:38:52 +0900 Subject: [PATCH 125/125] Update README about older stable branches --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 612a59cc..24b30dd7 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,8 @@ activerecord(>=5.0.0, <6.0) If you are using with older activerecord versions, use following versions. -* activerecord 3.x - use activerecord-turntable version 1.x. -* activerecord 4.x - use activerecord-turntable version 2.x. +* activerecord 4.x - use activerecord-turntable version 2.x.([stable-2-x branch](https://github.com/drecom/activerecord-turntable/tree/stable-2-x)) +* activerecord 3.x - use activerecord-turntable version 1.x.([stable-1-x branch](https://github.com/drecom/activerecord-turntable/tree/stable-1-x)) ## Supported Database