From ed94fce1b8957b3ea6b09ea54e2eb676a888d2b9 Mon Sep 17 00:00:00 2001 From: Daniel Cunha Date: Mon, 12 Jun 2023 09:16:07 -0300 Subject: [PATCH 1/5] Rails 6 dummy support --- lib/octopus/collection_association.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/octopus/collection_association.rb b/lib/octopus/collection_association.rb index 6713271a..e688f0c4 100644 --- a/lib/octopus/collection_association.rb +++ b/lib/octopus/collection_association.rb @@ -1,7 +1,7 @@ module Octopus module CollectionAssociation def self.included(base) - if Octopus.rails51? || Octopus.rails52? + if Octopus.atleast_rails51? base.sharded_methods :reader, :writer, :ids_reader, :ids_writer, :create, :create!, :build, :include?, :load_target, :reload, :size, :select From 27b3d98cd2c21eccb910ec23e55d010b4602ee5c Mon Sep 17 00:00:00 2001 From: Daniel Cunha Date: Tue, 13 Jun 2023 17:25:52 -0300 Subject: [PATCH 2/5] Upgrade ruby sintaxe on gem --- .gitignore | 3 +- .tool-versions | 1 + Gemfile.lock | 102 ++++++++++++++++++++++++++++++++ Rakefile | 2 +- ar-octopus.gemspec | 16 +++-- lib/octopus.rb | 7 ++- lib/octopus/persistence.rb | 4 +- lib/octopus/proxy.rb | 42 ++++++++++--- lib/octopus/relation_proxy.rb | 8 ++- lib/octopus/scope_proxy.rb | 2 +- lib/octopus/version.rb | 2 +- sample_app/config/database.yml | 6 +- spec/octopus/migration_spec.rb | 4 +- spec/octopus/model_spec.rb | 4 +- spec/octopus/proxy_spec.rb | 4 +- spec/support/database_models.rb | 4 +- spec/support/octopus_helper.rb | 14 ++--- 17 files changed, 183 insertions(+), 42 deletions(-) create mode 100644 .tool-versions create mode 100644 Gemfile.lock diff --git a/.gitignore b/.gitignore index e64ea9d9..bd5e6d81 100644 --- a/.gitignore +++ b/.gitignore @@ -3,10 +3,11 @@ .bundle .rvmrc .ruby-version -Gemfile.lock gemfiles/*.lock pkg/* *.rbc tmp/* .*.sw[a-z] database.log +.byebug_history +.env \ No newline at end of file diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 00000000..d6608a7e --- /dev/null +++ b/.tool-versions @@ -0,0 +1 @@ +ruby 3.0.6 diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 00000000..11608f8a --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,102 @@ +PATH + remote: . + specs: + ar-octopus-ruby-3 (0.11.2) + activerecord (~> 6.0.6.1) + activesupport (~> 6.0.6.1) + +GEM + remote: https://rubygems.org/ + specs: + activemodel (6.0.6.1) + activesupport (= 6.0.6.1) + activerecord (6.0.6.1) + activemodel (= 6.0.6.1) + activesupport (= 6.0.6.1) + activesupport (6.0.6.1) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + zeitwerk (~> 2.2, >= 2.2.2) + appraisal (2.4.1) + bundler + rake + thor (>= 0.14.0) + ast (2.4.2) + byebug (11.1.3) + coderay (1.1.3) + concurrent-ruby (1.2.2) + diff-lcs (1.5.0) + i18n (1.14.1) + concurrent-ruby (~> 1.0) + json (2.6.3) + method_source (1.0.0) + minitest (5.18.0) + mysql2 (0.5.5) + parallel (1.23.0) + parser (3.2.2.3) + ast (~> 2.4.1) + racc + pg (0.21.0) + pry (0.14.2) + coderay (~> 1.1) + method_source (~> 1.0) + pry-byebug (3.10.1) + byebug (~> 11.0) + pry (>= 0.13, < 0.15) + racc (1.7.0) + rainbow (3.1.1) + rake (13.0.6) + regexp_parser (2.8.1) + rexml (3.2.5) + rspec (3.12.0) + rspec-core (~> 3.12.0) + rspec-expectations (~> 3.12.0) + rspec-mocks (~> 3.12.0) + rspec-core (3.12.2) + rspec-support (~> 3.12.0) + rspec-expectations (3.12.3) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.12.0) + rspec-mocks (3.12.5) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.12.0) + rspec-support (3.12.0) + rubocop (1.52.1) + json (~> 2.3) + parallel (~> 1.10) + parser (>= 3.2.2.3) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) + rexml (>= 3.2.5, < 4.0) + rubocop-ast (>= 1.28.0, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 2.4.0, < 3.0) + rubocop-ast (1.29.0) + parser (>= 3.2.1.0) + ruby-progressbar (1.13.0) + sqlite3 (1.6.3-x86_64-linux) + thor (1.2.2) + thread_safe (0.3.6) + tzinfo (1.2.11) + thread_safe (~> 0.1) + unicode-display_width (2.4.2) + zeitwerk (2.6.8) + +PLATFORMS + x86_64-linux + +DEPENDENCIES + appraisal (>= 0.3.8) + ar-octopus-ruby-3! + mysql2 (~> 0.5) + pg (~> 0.18) + pry-byebug + rake + rspec (>= 3) + rubocop + sqlite3 (~> 1.4) + +BUNDLED WITH + 2.4.13 diff --git a/Rakefile b/Rakefile index e3d5f728..f7efb3f6 100644 --- a/Rakefile +++ b/Rakefile @@ -65,7 +65,7 @@ namespace :db do class BlankModel < ActiveRecord::Base; end BlankModel.using(shard_symbol).connection.initialize_schema_migrations_table - BlankModel.using(shard_symbol).connection.initialize_metadata_table if Octopus.atleast_rails50? + BlankModel.using(shard_symbol).connection.initialize_metadata_table if Octopus.atleast_rails50? BlankModel.using(shard_symbol).connection.create_table(:users) do |u| u.string :name diff --git a/ar-octopus.gemspec b/ar-octopus.gemspec index 6e8c1017..8e3d0266 100644 --- a/ar-octopus.gemspec +++ b/ar-octopus.gemspec @@ -3,7 +3,7 @@ $LOAD_PATH.push File.expand_path('../lib', __FILE__) require 'octopus/version' Gem::Specification.new do |s| - s.name = 'ar-octopus' + s.name = 'ar-octopus-ruby-3' s.version = Octopus::VERSION s.authors = ['Thiago Pradi', 'Mike Perham', 'Gabriel Sobrinho'] s.email = ['tchandy@gmail.com', 'mperham@gmail.com', 'gabriel.sobrinho@gmail.com'] @@ -17,22 +17,26 @@ Gem::Specification.new do |s| s.require_paths = ['lib'] s.post_install_message = "Important: If you are upgrading from < Octopus 0.5.0 you need to run:\n" \ - "$ rake octopus:copy_schema_versions\n\n" \ + "$ rake octopus:copy_scha_versions\n\n" \ 'Octopus now stores schema version information in each shard and migrations will not ' \ 'work properly unless this task is invoked.' s.required_ruby_version = '>= 2.2.0' - s.add_dependency 'activerecord', '>= 4.2.0' - s.add_dependency 'activesupport', '>= 4.2.0' + s.add_dependency 'activerecord', "~> 6.0.6.1" + s.add_dependency 'activesupport', "~> 6.0.6.1" s.add_development_dependency 'appraisal', '>= 0.3.8' - s.add_development_dependency 'mysql2', '>= 0.3.18', "< 0.5" + # To install the mysql2 gem its necessary execute the following command before run bundle + # $ sudo apt-get install libmysqlclient-dev + s.add_development_dependency 'mysql2', '~> 0.5' s.add_development_dependency 'pg', '~> 0.18' s.add_development_dependency 'rake' s.add_development_dependency 'rspec', '>= 3' s.add_development_dependency 'rubocop' - s.add_development_dependency 'sqlite3', '~> 1.3.6' + # To install the sqlite3 gem its necessary execute the following command before run bundle + # $ sudo apt-get install -y sqlite3 libsqlite3-dev + s.add_development_dependency 'sqlite3', '~> 1.4' s.add_development_dependency 'pry-byebug' s.license = 'MIT' diff --git a/lib/octopus.rb b/lib/octopus.rb index ffea3f78..cd4454ae 100644 --- a/lib/octopus.rb +++ b/lib/octopus.rb @@ -1,6 +1,7 @@ require 'active_record' require 'active_support/version' require 'active_support/core_ext/class' +require 'byebug' require 'yaml' require 'erb' @@ -101,7 +102,7 @@ def self.rails42? def self.rails50? ActiveRecord::VERSION::MAJOR == 5 && ActiveRecord::VERSION::MINOR == 0 end - + def self.atleast_rails50? ActiveRecord::VERSION::MAJOR >= 5 end @@ -114,6 +115,10 @@ def self.rails52? ActiveRecord::VERSION::MAJOR == 5 && ActiveRecord::VERSION::MINOR == 2 end + def self.rails60? + ActiveRecord::VERSION::MAJOR > 6 || ActiveRecord::VERSION::MAJOR == 6 + end + def self.atleast_rails51? ActiveRecord::VERSION::MAJOR > 5 || (ActiveRecord::VERSION::MAJOR == 5 && ActiveRecord::VERSION::MINOR >= 1) end diff --git a/lib/octopus/persistence.rb b/lib/octopus/persistence.rb index 9e07da17..888a6184 100644 --- a/lib/octopus/persistence.rb +++ b/lib/octopus/persistence.rb @@ -32,8 +32,8 @@ def update_column(*args) run_on_shard { super } end - def increment!(*args) - run_on_shard { super } + def increment!(...) + run_on_shard { super(...) } end def decrement!(*args) diff --git a/lib/octopus/proxy.rb b/lib/octopus/proxy.rb index b18f5ab1..a2a0313c 100644 --- a/lib/octopus/proxy.rb +++ b/lib/octopus/proxy.rb @@ -120,10 +120,10 @@ def check_schema_migrations(shard) def transaction(options = {}, &block) if !sharded && current_model_replicated? run_queries_on_shard(Octopus.master_shard) do - select_connection.transaction(options, &block) + select_connection.transaction(**options, &block) end else - select_connection.transaction(options, &block) + select_connection.transaction(**options, &block) end end @@ -192,15 +192,15 @@ def send_queries_to_slave_group(method, *args, &block) def current_model_replicated? replicated && (current_model.try(:replicated) || fully_replicated?) end - + def initialize_schema_migrations_table if Octopus.atleast_rails52? select_connection.transaction { ActiveRecord::SchemaMigration.create_table } - else + else select_connection.initialize_schema_migrations_table end end - + def initialize_metadata_table select_connection.transaction { ActiveRecord::InternalMetadata.create_table } end @@ -212,9 +212,12 @@ def initialize_metadata_table # We are planning to migrate to a much stable logic for the Proxy that doesn't require method missing. def legacy_method_missing_logic(method, *args, &block) if should_clean_connection_proxy?(method) - conn = select_connection clean_connection_proxy - conn.send(method, *args, &block) + args, preparable = handle_args(args) + + val = preparable.nil? ? + select_connection.send(method, *args, &block) : + select_connection.send(method, *args, **preparable, &block) elsif should_send_queries_to_shard_slave_group?(method) send_queries_to_shard_slave_group(method, *args, &block) elsif should_send_queries_to_slave_group?(method) @@ -222,7 +225,11 @@ def legacy_method_missing_logic(method, *args, &block) elsif should_send_queries_to_replicated_databases?(method) send_queries_to_selected_slave(method, *args, &block) else - val = select_connection.send(method, *args, &block) + args, preparable = handle_args(args) + + val = preparable.nil? ? + select_connection.send(method, *args, &block) : + select_connection.send(method, *args, **preparable, &block) if val.instance_of? ActiveRecord::Result val.current_shard = shard_name @@ -309,7 +316,12 @@ def send_queries_to_balancer(balancer, method, *args, &block) # while preserving `current_shard` def send_queries_to_slave(slave, method, *args, &block) using_shard(slave) do - val = select_connection.send(method, *args, &block) + args, preparable = handle_args(args) + + val = preparable.nil? ? + select_connection.send(method, *args, &block) : + select_connection.send(method, *args, **preparable, &block) + if val.instance_of? ActiveRecord::Result val.current_shard = slave end @@ -361,5 +373,17 @@ def using_group(group, &_block) self.current_group = older_group end end + + private + + def handle_args(args) + return [[], nil] if args.empty? + + preparable_args = args.select{ |arg| arg.is_a?(Hash) && arg.key?(:preparable)} + return [args, nil] if preparable_args.empty? + + args -= preparable_args + return [args, preparable_args.first] + end end end diff --git a/lib/octopus/relation_proxy.rb b/lib/octopus/relation_proxy.rb index aaf36d69..d3d4deba 100644 --- a/lib/octopus/relation_proxy.rb +++ b/lib/octopus/relation_proxy.rb @@ -33,7 +33,9 @@ def method_missing(method, *args, &block) if !block && BATCH_METHODS.include?(method) ::Enumerator.new do |yielder| run_on_shard do - @ar_relation.public_send(method, *args) do |batch_item| + parsed_args = args.empty? ? {} : args.first + + @ar_relation.public_send(method, **parsed_args) do |batch_item| yielder << batch_item end end @@ -43,7 +45,9 @@ def method_missing(method, *args, &block) elsif WHERE_CHAIN_METHODS.include?(method) ::Octopus::ScopeProxy.new(@current_shard, run_on_shard { @ar_relation.public_send(method, *args) } ) elsif block - @ar_relation.public_send(method, *args, &block) + parsed_args = args.empty? ? {} : args.first + + @ar_relation.public_send(method, **parsed_args, &block) else run_on_shard do if method == :load_records diff --git a/lib/octopus/scope_proxy.rb b/lib/octopus/scope_proxy.rb index 0cf3dd5b..12723a77 100644 --- a/lib/octopus/scope_proxy.rb +++ b/lib/octopus/scope_proxy.rb @@ -28,7 +28,7 @@ def using(shard) # Transaction Method send all queries to a specified shard. def transaction(options = {}, &block) - run_on_shard { klass.transaction(options, &block) } + run_on_shard { klass.transaction(**options, &block) } end def connection diff --git a/lib/octopus/version.rb b/lib/octopus/version.rb index 47839e61..1f30bbf4 100644 --- a/lib/octopus/version.rb +++ b/lib/octopus/version.rb @@ -1,3 +1,3 @@ module Octopus - VERSION = '0.10.2' + VERSION = '0.11.2' end diff --git a/sample_app/config/database.yml b/sample_app/config/database.yml index d26cc790..433337f2 100644 --- a/sample_app/config/database.yml +++ b/sample_app/config/database.yml @@ -2,7 +2,7 @@ # gem install sqlite3-ruby (not necessary on OS X Leopard) development: adapter: postgresql - username: postgres + username: postgres password: database: octopus_sample_app_development encoding: unicode @@ -13,7 +13,7 @@ development: # Do not set this db to the same as development or production. test: &test adapter: postgresql - username: postgres + username: postgres password: database: octopus_sample_app_test encoding: unicode @@ -21,7 +21,7 @@ test: &test production: adapter: postgresql - username: postgres + username: postgres password: database: octopus_sample_app_production encoding: unicode diff --git a/spec/octopus/migration_spec.rb b/spec/octopus/migration_spec.rb index 999db255..93c55699 100644 --- a/spec/octopus/migration_spec.rb +++ b/spec/octopus/migration_spec.rb @@ -2,8 +2,10 @@ def get_all_versions if Octopus.atleast_rails52? + schema = ActiveRecord::SchemaMigration migrations_root = File.expand_path(File.join(File.dirname(__FILE__), '..', 'migrations')) - ActiveRecord::MigrationContext.new(migrations_root).get_all_versions + + ActiveRecord::MigrationContext.new(migrations_root, schema).get_all_versions else ActiveRecord::Migrator.get_all_versions end diff --git a/spec/octopus/model_spec.rb b/spec/octopus/model_spec.rb index 5f827e52..c8cf535e 100644 --- a/spec/octopus/model_spec.rb +++ b/spec/octopus/model_spec.rb @@ -309,7 +309,7 @@ if Octopus.atleast_rails52? expect(User.using(:postgresql_shard).connection.adapter_name).to eq('PostgreSQL') expect(User.using(:alone_shard).connection.adapter_name).to eq('Mysql2') - else + else expect(User.using(:postgresql_shard).arel_engine.connection.adapter_name).to eq('PostgreSQL') expect(User.using(:alone_shard).arel_engine.connection.adapter_name).to eq('Mysql2') end @@ -497,7 +497,7 @@ end user = User.using(:brazil).where(:name => 'User1').first - expect(user.as_json(:except => [:created_at, :updated_at, :id])).to eq('admin' => nil, 'name' => 'User1', 'number' => nil) + expect(user.as_json(:except => [:created_at, :updated_at, :id, :current_shard])).to eq('admin' => nil, 'name' => 'User1', 'number' => nil) end describe 'transaction' do diff --git a/spec/octopus/proxy_spec.rb b/spec/octopus/proxy_spec.rb index 6dc15277..dc68d5cf 100644 --- a/spec/octopus/proxy_spec.rb +++ b/spec/octopus/proxy_spec.rb @@ -30,10 +30,10 @@ config = proxy.config expect(config[:adapter]).to eq('mysql2') expect(config[:database]).to eq('octopus_shard_1') - expect(config[:username]).to eq("#{ENV['MYSQL_USER'] || 'root'}") + expect(config[:username]).to eq("#{ENV['MYSQL_USER'] || 'daniel'}") end - unless Octopus.rails50? || Octopus.rails51?|| Octopus.rails52? + unless Octopus.rails50? || Octopus.rails51?|| Octopus.rails52? || Octopus.rails60? it 'should respond correctly to respond_to?(:pk_and_sequence_for)' do expect(proxy.respond_to?(:pk_and_sequence_for)).to be true end diff --git a/spec/support/database_models.rb b/spec/support/database_models.rb index 787ecebc..a7acd40f 100644 --- a/spec/support/database_models.rb +++ b/spec/support/database_models.rb @@ -28,7 +28,7 @@ class Cat < ActiveRecord::Base # This class sets its own connection class CustomConnection < ActiveRecord::Base self.table_name = 'custom' - octopus_establish_connection(:adapter => 'mysql2', :database => 'octopus_shard_2', :username => "#{ENV['MYSQL_USER'] || 'root'}", :password => '') + octopus_establish_connection(:adapter => 'mysql2', :database => 'octopus_shard_2', :username => "#{ENV['MYSQL_USER'] || ''}", :password => '1234') end # This items belongs to a client @@ -93,7 +93,7 @@ class Ham < ActiveRecord::Base # This class sets its own connection class Advert < ActiveRecord::Base - establish_connection(:adapter => 'postgresql', :database => 'octopus_shard_1', :username => ENV['POSTGRES_USER'] || 'postgres', :password => '') + establish_connection(:adapter => 'postgresql', :database => 'octopus_shard_1', :username => ENV['POSTGRES_USER'] || 'daniel', :password => '1234', :host => '') end class MmorpgPlayer < ActiveRecord::Base diff --git a/spec/support/octopus_helper.rb b/spec/support/octopus_helper.rb index 01db6431..730451dd 100644 --- a/spec/support/octopus_helper.rb +++ b/spec/support/octopus_helper.rb @@ -29,7 +29,7 @@ def self.clean_connection_proxy def self.migrating_to_version(version, &_block) migrations_root = File.expand_path(File.join(File.dirname(__FILE__), '..', 'migrations')) - + begin migrate_to_version(:up, migrations_root, version) yield @@ -37,14 +37,12 @@ def self.migrating_to_version(version, &_block) migrate_to_version(:down, migrations_root, version) end end - + def self.migrate_to_version(direction, root, version) - if Octopus.atleast_rails52? - migrations = ActiveRecord::MigrationContext.new(root).migrations.select {|mig| version == mig.version } - ActiveRecord::Migrator.new(direction, migrations, version).run - else - ActiveRecord::Migrator.run(direction, root, version) - end + schema = ActiveRecord::SchemaMigration + migrations = ActiveRecord::MigrationContext.new(root, schema).migrations.select {|mig| version == mig.version } + + ActiveRecord::Migrator.new(direction, migrations, schema, version).run end def self.using_environment(environment, &_block) From 9c295a7149a89928df3ffc15a67a40d8ce262530 Mon Sep 17 00:00:00 2001 From: sosolidkk Date: Thu, 15 Jun 2023 14:12:07 -0300 Subject: [PATCH 3/5] Undo some unneeded changes and improvements --- .rubocop.yml | 12 ++---- .rubocop_todo.yml | 2 +- lib/octopus.rb | 15 +++---- lib/octopus/abstract_adapter.rb | 2 +- lib/octopus/association.rb | 2 +- lib/octopus/association_shard_tracking.rb | 12 +++--- lib/octopus/collection_association.rb | 2 +- lib/octopus/collection_proxy.rb | 2 +- lib/octopus/load_balancing/round_robin.rb | 1 + lib/octopus/log_subscriber.rb | 2 +- lib/octopus/migration.rb | 52 +++++++++++------------ lib/octopus/model.rb | 9 ++-- lib/octopus/persistence.rb | 2 +- lib/octopus/proxy.rb | 41 ++++++++---------- lib/octopus/proxy_config.rb | 18 ++++---- lib/octopus/query_cache_for_shards.rb | 2 +- lib/octopus/relation_proxy.rb | 2 +- lib/octopus/scope_proxy.rb | 9 ++-- lib/octopus/shard_tracking/attribute.rb | 4 +- lib/octopus/singular_association.rb | 2 +- lib/octopus/version.rb | 2 + spec/spec_helper.rb | 1 + spec/support/database_models.rb | 4 +- 23 files changed, 93 insertions(+), 107 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 0b40abf0..c99c4bba 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,10 +1,7 @@ inherit_from: .rubocop_todo.yml -ActionFilter: - EnforcedStyle: filter - CaseIndentation: - IndentWhenRelativeTo: end + EnforcedStyle: end CollectionMethods: PreferredMethods: @@ -17,14 +14,11 @@ Encoding: Enabled: false EndAlignment: - AlignWith: variable + EnforcedStyleAlignWith: variable HashSyntax: EnforcedStyle: hash_rockets -Style/IndentHash: - EnforcedStyle: consistent - Loop: Enabled: false @@ -37,7 +31,7 @@ RegexpLiteral: Semicolon: AllowAsExpressionSeparator: true -Style/TrailingComma: +Style/TrailingCommaInArguments: EnforcedStyleForMultiline: comma Style/TrivialAccessors: diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 6113fb54..d9cd5562 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -10,7 +10,7 @@ Lint/AmbiguousRegexpLiteral: Enabled: false # Offense count: 1 -Lint/HandleExceptions: +Lint/SuppressedException: Enabled: false # Offense count: 1 diff --git a/lib/octopus.rb b/lib/octopus.rb index cd4454ae..60c2df04 100644 --- a/lib/octopus.rb +++ b/lib/octopus.rb @@ -1,7 +1,6 @@ require 'active_record' require 'active_support/version' require 'active_support/core_ext/class' -require 'byebug' require 'yaml' require 'erb' @@ -19,10 +18,10 @@ def self.config @config ||= begin file_name = File.join(Octopus.directory, 'config/shards.yml').to_s - if File.exist?(file_name) || File.symlink?(file_name) - config ||= HashWithIndifferentAccess.new(YAML.load(ERB.new(File.read(file_name)).result))[Octopus.env] + config = if File.exist?(file_name) || File.symlink?(file_name) + HashWithIndifferentAccess.new(YAML.safe_load(ERB.new(File.read(file_name)).result))[Octopus.env] else - config ||= HashWithIndifferentAccess.new + HashWithIndifferentAccess.new end config @@ -100,7 +99,7 @@ def self.rails42? end def self.rails50? - ActiveRecord::VERSION::MAJOR == 5 && ActiveRecord::VERSION::MINOR == 0 + ActiveRecord::VERSION::MAJOR == 5 && ActiveRecord::VERSION::MINOR.zero? end def self.atleast_rails50? @@ -130,10 +129,10 @@ def self.atleast_rails52? attr_writer :logger def self.logger - if defined?(Rails.logger) - @logger ||= Rails.logger + @logger = if defined?(Rails.logger) + Rails.logger else - @logger ||= Logger.new($stderr) + Logger.new($stderr) end end diff --git a/lib/octopus/abstract_adapter.rb b/lib/octopus/abstract_adapter.rb index f6ce7956..9b3467b2 100644 --- a/lib/octopus/abstract_adapter.rb +++ b/lib/octopus/abstract_adapter.rb @@ -30,4 +30,4 @@ def initialize(*args) end end -ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:prepend, Octopus::AbstractAdapter::OctopusShard) +ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend(Octopus::AbstractAdapter::OctopusShard) diff --git a/lib/octopus/association.rb b/lib/octopus/association.rb index 1d01f269..df9b9392 100644 --- a/lib/octopus/association.rb +++ b/lib/octopus/association.rb @@ -11,4 +11,4 @@ def current_shard end end -ActiveRecord::Associations::Association.send(:include, Octopus::Association) +ActiveRecord::Associations::Association.include(Octopus::Association) diff --git a/lib/octopus/association_shard_tracking.rb b/lib/octopus/association_shard_tracking.rb index 36d4622f..3ab5d348 100644 --- a/lib/octopus/association_shard_tracking.rb +++ b/lib/octopus/association_shard_tracking.rb @@ -10,11 +10,11 @@ def initialize(record, current_shard) def message [ - "Association Error: Records are from different shards", + 'Association Error: Records are from different shards', "Record: #{record.inspect}", "Current Shard: #{current_shard.inspect}", - "Current Record Shard: #{record.current_shard.inspect}", - ].join(" ") + "Current Record Shard: #{record.current_shard.inspect}" + ].join(' ') end end @@ -25,7 +25,7 @@ def self.extended(base) module InstanceMethods def connection_on_association=(record) return unless ::Octopus.enabled? - return if !self.class.connection.respond_to?(:current_shard) || !self.respond_to?(:current_shard) + return if !self.class.connection.respond_to?(:current_shard) || !respond_to?(:current_shard) if !record.current_shard.nil? && !current_shard.nil? && record.current_shard.to_s != current_shard.to_s raise MismatchedShards.new(record, current_shard) @@ -50,8 +50,8 @@ def has_and_belongs_to_many(association_id, scope = nil, options = {}, &extensio end def default_octopus_opts(options) - options[:before_add] = [ :connection_on_association=, options[:before_add] ].compact.flatten - options[:before_remove] = [ :connection_on_association=, options[:before_remove] ].compact.flatten + options[:before_add] = [:connection_on_association=, options[:before_add]].compact.flatten + options[:before_remove] = [:connection_on_association=, options[:before_remove]].compact.flatten end def assign_octopus_opts(scope, options) diff --git a/lib/octopus/collection_association.rb b/lib/octopus/collection_association.rb index e688f0c4..3f42d847 100644 --- a/lib/octopus/collection_association.rb +++ b/lib/octopus/collection_association.rb @@ -14,4 +14,4 @@ def self.included(base) end end -ActiveRecord::Associations::CollectionAssociation.send(:include, Octopus::CollectionAssociation) +ActiveRecord::Associations::CollectionAssociation.include(Octopus::CollectionAssociation) diff --git a/lib/octopus/collection_proxy.rb b/lib/octopus/collection_proxy.rb index f9c10262..c66cd251 100644 --- a/lib/octopus/collection_proxy.rb +++ b/lib/octopus/collection_proxy.rb @@ -13,4 +13,4 @@ def current_shard end end -ActiveRecord::Associations::CollectionProxy.send(:include, Octopus::CollectionProxy) +ActiveRecord::Associations::CollectionProxy.include(Octopus::CollectionProxy) diff --git a/lib/octopus/load_balancing/round_robin.rb b/lib/octopus/load_balancing/round_robin.rb index e045430a..b2c4d8f1 100644 --- a/lib/octopus/load_balancing/round_robin.rb +++ b/lib/octopus/load_balancing/round_robin.rb @@ -7,6 +7,7 @@ module LoadBalancing class RoundRobin def initialize(slaves_list) raise Octopus::Exception.new("No slaves available") if slaves_list.empty? + @slaves_list = slaves_list @slave_index = 0 end diff --git a/lib/octopus/log_subscriber.rb b/lib/octopus/log_subscriber.rb index 32139485..a3c1ab58 100644 --- a/lib/octopus/log_subscriber.rb +++ b/lib/octopus/log_subscriber.rb @@ -23,4 +23,4 @@ def debug_with_octopus_shard(msg) end end -ActiveRecord::LogSubscriber.send(:include, Octopus::LogSubscriber) +ActiveRecord::LogSubscriber.include(Octopus::LogSubscriber) diff --git a/lib/octopus/migration.rb b/lib/octopus/migration.rb index d016c8ce..8543b06e 100644 --- a/lib/octopus/migration.rb +++ b/lib/octopus/migration.rb @@ -67,20 +67,20 @@ def self.included(base) base.class_eval do class << self - alias_method :migrate_without_octopus, :migrate - alias_method :migrate, :migrate_with_octopus - - alias_method :up_without_octopus, :up - alias_method :up, :up_with_octopus + alias_method :migrate_without_octopus, :migrate + alias_method :migrate, :migrate_with_octopus - alias_method :down_without_octopus, :down - alias_method :down, :down_with_octopus + alias_method :up_without_octopus, :up + alias_method :up, :up_with_octopus - alias_method :run_without_octopus, :run - alias_method :run, :run_with_octopus + alias_method :down_without_octopus, :down + alias_method :down, :down_with_octopus - alias_method :rollback_without_octopus, :rollback - alias_method :rollback, :rollback_with_octopus + alias_method :run_without_octopus, :run + alias_method :run, :run_with_octopus + + alias_method :rollback_without_octopus, :rollback + alias_method :rollback, :rollback_with_octopus end end end @@ -96,25 +96,26 @@ class << self end if Octopus.atleast_rails52? ### Post RAILS 5.2 Migration methods - def run_with_octopus(&block) return run_without_octopus(&block) unless connection.is_a?(Octopus::Proxy) + shards = migrations.map(&:shards).flatten.map(&:to_s) connection.send_queries_to_multiple_shards(shards) do run_without_octopus(&block) end - rescue ActiveRecord::UnknownMigrationVersionError => e - raise unless migrations(true).detect { |m| m.version == e.version } + rescue ActiveRecord::UnknownMigrationVersionError => e + raise unless migrations(true).detect { |m| m.version == e.version } end def migrate_with_octopus(&block) return migrate_without_octopus(&block) unless connection.is_a?(Octopus::Proxy) + shards = migrations.map(&:shards).flatten.map(&:to_s) connection.send_queries_to_multiple_shards(shards) do migrate_without_octopus(&block) end - rescue ActiveRecord::UnknownMigrationVersionError => e - raise unless migrations(true).detect { |m| m.version == e.version } + rescue ActiveRecord::UnknownMigrationVersionError => e + raise unless migrations(true).detect { |m| m.version == e.version } end def migrations_with_octopus(shard_agnostic = true) @@ -123,16 +124,15 @@ def migrations_with_octopus(shard_agnostic = true) migrations.select { |m| m.shards.include?(connection.current_shard.to_sym) } end - - private - + + private + def connection ActiveRecord::Base.connection end - - else + + else ### Pre RAILS 5.2 Migration methods - def run_with_octopus(&block) run_without_octopus(&block) rescue ActiveRecord::UnknownMigrationVersionError => e @@ -230,7 +230,7 @@ def initialize_with_octopus(version) end end -ActiveRecord::Migration.send(:include, Octopus::Migration) -ActiveRecord::Migrator.send(:include, Octopus::Migrator) -ActiveRecord::MigrationProxy.send(:include, Octopus::MigrationProxy) -ActiveRecord::UnknownMigrationVersionError.send(:include, Octopus::UnknownMigrationVersionError) +ActiveRecord::Migration.include(Octopus::Migration) +ActiveRecord::Migrator.include(Octopus::Migrator) +ActiveRecord::MigrationProxy.include(Octopus::MigrationProxy) +ActiveRecord::UnknownMigrationVersionError.include(Octopus::UnknownMigrationVersionError) diff --git a/lib/octopus/model.rb b/lib/octopus/model.rb index ba9649e4..b4a559f3 100644 --- a/lib/octopus/model.rb +++ b/lib/octopus/model.rb @@ -12,9 +12,9 @@ module SharedMethods def using(shard) if block_given? raise Octopus::Exception, <<-EOF -#{name}.using is not allowed to receive a block, it works just like a regular scope. + #{name}.using is not allowed to receive a block, it works just like a regular scope. -If you are trying to scope everything to a specific shard, use Octopus.using instead. + If you are trying to scope everything to a specific shard, use Octopus.using instead. EOF end @@ -39,6 +39,7 @@ def self.included(base) def set_current_shard return unless Octopus.enabled? + shard = self.class.connection_proxy.current_shard self.current_shard = shard if self.class.allowed_shard?(shard) end @@ -59,7 +60,7 @@ def init_with(coder) end def should_set_current_shard? - self.respond_to?(:current_shard) && !current_shard.nil? + respond_to?(:current_shard) && !current_shard.nil? end def equality_with_octopus(comparison_object) @@ -103,7 +104,7 @@ def allow_shard(*shards) def hijack_methods after_initialize :set_current_shard - around_save :run_on_shard, :unless => lambda { self.class.custom_octopus_connection } + around_save :run_on_shard, :unless => -> { self.class.custom_octopus_connection } class_attribute :custom_octopus_connection diff --git a/lib/octopus/persistence.rb b/lib/octopus/persistence.rb index 888a6184..ed8b2745 100644 --- a/lib/octopus/persistence.rb +++ b/lib/octopus/persistence.rb @@ -42,4 +42,4 @@ def decrement!(*args) end end -ActiveRecord::Base.send(:include, Octopus::Persistence) +ActiveRecord::Base.include(Octopus::Persistence) diff --git a/lib/octopus/proxy.rb b/lib/octopus/proxy.rb index a2a0313c..2dc75a1b 100644 --- a/lib/octopus/proxy.rb +++ b/lib/octopus/proxy.rb @@ -23,15 +23,15 @@ def initialize(config = Octopus.config) # Rails Connection Methods - Those methods are overriden to add custom behavior that helps # Octopus introduce Sharding / Replication. delegate :adapter_name, :add_transaction_record, :case_sensitive_modifier, - :type_cast, :to_sql, :quote, :quote_column_name, :quote_table_name, - :quote_table_name_for_assignment, :supports_migrations?, :table_alias_for, - :table_exists?, :in_clause_length, :supports_ddl_transactions?, - :sanitize_limit, :prefetch_primary_key?, :current_database, - :combine_bind_parameters, :empty_insert_statement_value, :assume_migrated_upto_version, - :schema_cache, :substitute_at, :internal_string_options_for_primary_key, :lookup_cast_type_from_column, - :supports_advisory_locks?, :get_advisory_lock, :initialize_internal_metadata_table, - :release_advisory_lock, :prepare_binds_for_database, :cacheable_query, :column_name_for_operation, - :prepared_statements, :transaction_state, :create_table, to: :select_connection + :type_cast, :to_sql, :quote, :quote_column_name, :quote_table_name, + :quote_table_name_for_assignment, :supports_migrations?, :table_alias_for, + :table_exists?, :in_clause_length, :supports_ddl_transactions?, + :sanitize_limit, :prefetch_primary_key?, :current_database, + :combine_bind_parameters, :empty_insert_statement_value, :assume_migrated_upto_version, + :schema_cache, :substitute_at, :internal_string_options_for_primary_key, :lookup_cast_type_from_column, + :supports_advisory_locks?, :get_advisory_lock, :initialize_internal_metadata_table, + :release_advisory_lock, :prepare_binds_for_database, :cacheable_query, :column_name_for_operation, + :prepared_statements, :transaction_state, :create_table, to: :select_connection def execute(sql, name = nil) conn = select_connection @@ -280,10 +280,10 @@ def should_send_queries_to_replicated_databases?(method) end def send_queries_to_selected_slave(method, *args, &block) - if current_model.replicated || fully_replicated? - selected_slave = slaves_load_balancer.next current_load_balance_options + selected_slave = if current_model.replicated || fully_replicated? + slaves_load_balancer.next current_load_balance_options else - selected_slave = Octopus.master_shard + Octopus.master_shard end send_queries_to_slave(selected_slave, method, *args, &block) @@ -318,13 +318,9 @@ def send_queries_to_slave(slave, method, *args, &block) using_shard(slave) do args, preparable = handle_args(args) - val = preparable.nil? ? - select_connection.send(method, *args, &block) : - select_connection.send(method, *args, **preparable, &block) + val = preparable.nil? ? select_connection.send(method, *args, &block) : select_connection.send(method, *args, **preparable, &block) + val.current_shard = slave if val.instance_of? ActiveRecord::Result - if val.instance_of? ActiveRecord::Result - val.current_shard = slave - end val end end @@ -351,9 +347,8 @@ def using_shard(shard, &_block) older_load_balance_options = current_load_balance_options begin - unless current_model && !current_model.allowed_shard?(shard) - self.current_shard = shard - end + self.current_shard = shard unless current_model && !current_model.allowed_shard?(shard) + yield ensure self.current_shard = older_shard @@ -379,11 +374,11 @@ def using_group(group, &_block) def handle_args(args) return [[], nil] if args.empty? - preparable_args = args.select{ |arg| arg.is_a?(Hash) && arg.key?(:preparable)} + preparable_args = args.select { |arg| arg.is_a?(Hash) && arg.key?(:preparable) } return [args, nil] if preparable_args.empty? args -= preparable_args - return [args, preparable_args.first] + [args, preparable_args.first] end end end diff --git a/lib/octopus/proxy_config.rb b/lib/octopus/proxy_config.rb index 93a2e5bc..b6205a06 100644 --- a/lib/octopus/proxy_config.rb +++ b/lib/octopus/proxy_config.rb @@ -199,10 +199,10 @@ def initialize_shards(config) def initialize_replication(config) @replicated = true - if config.key?('fully_replicated') - @fully_replicated = config['fully_replicated'] + @fully_replicated = if config.key?('fully_replicated') + config['fully_replicated'] else - @fully_replicated = true + true end @slaves_list = shards.keys.map(&:to_s).sort @@ -218,9 +218,9 @@ def reinitialize_shards def connection_pool_for(config, adapter) if Octopus.rails4? - spec = ActiveRecord::ConnectionAdapters::ConnectionSpecification.new(config.dup, adapter ) + spec = ActiveRecord::ConnectionAdapters::ConnectionSpecification.new(config.dup, adapter) else - name = adapter["octopus_shard"] + name = adapter['octopus_shard'] spec = ActiveRecord::ConnectionAdapters::ConnectionSpecification.new(name, config.dup, adapter) end @@ -241,11 +241,9 @@ def structurally_slave_group?(config) end def initialize_adapter(adapter) - begin - require "active_record/connection_adapters/#{adapter}_adapter" - rescue LoadError - raise "Please install the #{adapter} adapter: `gem install activerecord-#{adapter}-adapter` (#{$ERROR_INFO})" - end + require "active_record/connection_adapters/#{adapter}_adapter" + rescue LoadError + raise "Please install the #{adapter} adapter: `gem install activerecord-#{adapter}-adapter` (#{$ERROR_INFO})" end end end diff --git a/lib/octopus/query_cache_for_shards.rb b/lib/octopus/query_cache_for_shards.rb index d29f9145..c2f5b6ad 100644 --- a/lib/octopus/query_cache_for_shards.rb +++ b/lib/octopus/query_cache_for_shards.rb @@ -21,4 +21,4 @@ module QueryCacheForShards end end -ActiveRecord::ConnectionAdapters::ConnectionPool.send(:prepend, Octopus::ConnectionPool::QueryCacheForShards) +ActiveRecord::ConnectionAdapters::ConnectionPool.prepend(Octopus::ConnectionPool::QueryCacheForShards) diff --git a/lib/octopus/relation_proxy.rb b/lib/octopus/relation_proxy.rb index d3d4deba..00eb72d7 100644 --- a/lib/octopus/relation_proxy.rb +++ b/lib/octopus/relation_proxy.rb @@ -43,7 +43,7 @@ def method_missing(method, *args, &block) elsif ENUM_METHODS.include?(method) || block && ENUM_WITH_BLOCK_METHODS.include?(method) run_on_shard { @ar_relation.to_a }.public_send(method, *args, &block) elsif WHERE_CHAIN_METHODS.include?(method) - ::Octopus::ScopeProxy.new(@current_shard, run_on_shard { @ar_relation.public_send(method, *args) } ) + ::Octopus::ScopeProxy.new(@current_shard, run_on_shard { @ar_relation.public_send(method, *args) }) elsif block parsed_args = args.empty? ? {} : args.first diff --git a/lib/octopus/scope_proxy.rb b/lib/octopus/scope_proxy.rb index 12723a77..41428677 100644 --- a/lib/octopus/scope_proxy.rb +++ b/lib/octopus/scope_proxy.rb @@ -22,6 +22,7 @@ def initialize(shard, klass) def using(shard) fail "Nonexistent Shard Name: #{shard}" if @klass.connection.shards[shard].nil? + @current_shard = shard self end @@ -45,13 +46,9 @@ def connection def method_missing(method, *args, &block) result = run_on_shard { @klass.__send__(method, *args, &block) } - if result.respond_to?(:all) - return ::Octopus::ScopeProxy.new(current_shard, result) - end + return ::Octopus::ScopeProxy.new(current_shard, result) if result.respond_to?(:all) - if result.respond_to?(:current_shard) - result.current_shard = current_shard - end + result.current_shard = current_shard if result.respond_to?(:current_shard) result end diff --git a/lib/octopus/shard_tracking/attribute.rb b/lib/octopus/shard_tracking/attribute.rb index 8b808f0f..71b5b7a6 100644 --- a/lib/octopus/shard_tracking/attribute.rb +++ b/lib/octopus/shard_tracking/attribute.rb @@ -13,9 +13,7 @@ def self.included(base) def set_current_shard return unless Octopus.enabled? - if ActiveRecord::Base.connection_proxy.block - self.current_shard = ActiveRecord::Base.connection_proxy.current_shard - end + self.current_shard = ActiveRecord::Base.connection_proxy.current_shard if ActiveRecord::Base.connection_proxy.block end end end diff --git a/lib/octopus/singular_association.rb b/lib/octopus/singular_association.rb index 52a78901..6abbad42 100644 --- a/lib/octopus/singular_association.rb +++ b/lib/octopus/singular_association.rb @@ -6,4 +6,4 @@ def self.included(base) end end -ActiveRecord::Associations::SingularAssociation.send(:include, Octopus::SingularAssociation) +ActiveRecord::Associations::SingularAssociation.include(Octopus::SingularAssociation) diff --git a/lib/octopus/version.rb b/lib/octopus/version.rb index 1f30bbf4..054fb884 100644 --- a/lib/octopus/version.rb +++ b/lib/octopus/version.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Octopus VERSION = '0.11.2' end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index af2b75ae..51685bdf 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,5 +1,6 @@ require 'rubygems' require 'pry' +require 'byebug' require 'bundler/setup' require 'octopus' diff --git a/spec/support/database_models.rb b/spec/support/database_models.rb index a7acd40f..c8a3462a 100644 --- a/spec/support/database_models.rb +++ b/spec/support/database_models.rb @@ -28,7 +28,7 @@ class Cat < ActiveRecord::Base # This class sets its own connection class CustomConnection < ActiveRecord::Base self.table_name = 'custom' - octopus_establish_connection(:adapter => 'mysql2', :database => 'octopus_shard_2', :username => "#{ENV['MYSQL_USER'] || ''}", :password => '1234') + octopus_establish_connection(:adapter => 'mysql2', :database => 'octopus_shard_2', :username => "#{ENV['MYSQL_USER'] || 'root'}", :password => '') end # This items belongs to a client @@ -93,7 +93,7 @@ class Ham < ActiveRecord::Base # This class sets its own connection class Advert < ActiveRecord::Base - establish_connection(:adapter => 'postgresql', :database => 'octopus_shard_1', :username => ENV['POSTGRES_USER'] || 'daniel', :password => '1234', :host => '') + establish_connection(:adapter => 'postgresql', :database => 'octopus_shard_1', :username => ENV['POSTGRES_USER'] || 'root', :password => '') end class MmorpgPlayer < ActiveRecord::Base From d0c9eff666d0d256db78c6421fdafd74af572ae4 Mon Sep 17 00:00:00 2001 From: sosolidkk Date: Thu, 15 Jun 2023 14:27:46 -0300 Subject: [PATCH 4/5] Add empty line at end of .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index bd5e6d81..485c2794 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,4 @@ tmp/* .*.sw[a-z] database.log .byebug_history -.env \ No newline at end of file +.env From 108268795a69f15e83ed29a2388d79d3b8a6f62b Mon Sep 17 00:00:00 2001 From: sosolidkk Date: Fri, 16 Jun 2023 09:27:24 -0300 Subject: [PATCH 5/5] Change wrong credential user value --- spec/octopus/proxy_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/octopus/proxy_spec.rb b/spec/octopus/proxy_spec.rb index dc68d5cf..b46bed2f 100644 --- a/spec/octopus/proxy_spec.rb +++ b/spec/octopus/proxy_spec.rb @@ -30,7 +30,7 @@ config = proxy.config expect(config[:adapter]).to eq('mysql2') expect(config[:database]).to eq('octopus_shard_1') - expect(config[:username]).to eq("#{ENV['MYSQL_USER'] || 'daniel'}") + expect(config[:username]).to eq("#{ENV['MYSQL_USER'] || 'root'}") end unless Octopus.rails50? || Octopus.rails51?|| Octopus.rails52? || Octopus.rails60?