From 3a1e898ead427edb80c7c3d9bc874b910a79e827 Mon Sep 17 00:00:00 2001 From: fumihumi Date: Mon, 21 Apr 2025 00:38:55 +0900 Subject: [PATCH 1/6] chore: format readme.md --- README.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index db760a0..f73075a 100644 --- a/README.md +++ b/README.md @@ -11,12 +11,16 @@ Currently, its implementation is focusing on horizontal database sharding. Howev ## Scope of this gem ### What is included in Octoball + - Octopus-like shard swithcing by `using` class method, e.g.: + ```ruby Octoball.using(:shard1) { User.find_by_name("Alice") } User.using(:shard1).first ``` + - Each model instance knows which shard it came from so shard will be switched automatically: + ```ruby user1 = User.using(:shard1).find_by_name("Bob") user2 = User.using(:shard2).find_by_name("Charlie") @@ -25,15 +29,18 @@ Currently, its implementation is focusing on horizontal database sharding. Howev user1.save! # Save the user1 in the correct shard `:shard1` user2.save! # Save the user2 in the correct shard `:shard2` ``` + - Relations such as `has_many` are also resolved from the model instance's shard: + ```ruby user = User.using(:shard1).find_by_name("Alice") user.blogs.where(title: "blog") # user's blogs are fetched from `:shard1` ``` ### What is NOT included in Octoball + - Connection handling and configuration -- managed by the native `ActiveRecord::Base.connects_to` methods introduced in ActiveRecord 6.1. - - You need to migrate from Octopus' `config/shards.yml` to [Rails native multiple DB configuration using `config/database.yml`](https://edgeguides.rubyonrails.org/active_record_multiple_databases.html). Please refer the [Setup](#Setup) section for more details. + - You need to migrate from Octopus' `config/shards.yml` to [Rails native multiple DB configuration using `config/database.yml`](https://edgeguides.rubyonrails.org/active_record_multiple_databases.html). Please refer the [Setup](#setup) section for more details. - Migration -- done by ActiveRecord 6.1+ natively. - Instead of `using` method in Octopus, you can specify the `migrations_paths` parameter in the `config/database.yml` file. - Replication handling -- done by ActiveRecord's `role` @@ -46,6 +53,7 @@ gem "octoball" ``` Define the database connections in `config/database.yml`, e.g.: + ``` default: &default adapter: mysql2 @@ -63,7 +71,9 @@ development: <<: *default database: db_shard1 ``` + And define shards and corresponding connections in abstract ActiveRecord model class, e.g.: + ```ruby class ApplicationRecord < ActiveRecord::Base self.abstract_class = true @@ -80,21 +90,24 @@ end ``` Optionally, to use the `:master` shard as a default connection like Octopus, add the following script to `config/initializers/default_shard.rb`: + ``` ActiveRecord::Base.default_shard = :master ``` - ## Development of Octoball + Octoball has rspec tests delived from subsets of Octopus' rspec. To run the rspec tests, follow these steps: + ``` RAILS_ENV=test bundle exec rake db:prepare RAILS_ENV=test bundle exec rake spec ``` ## License + Octoball is released under the MIT license. Original Octopus' copyright: Copyright (c) Thiago Pradi From 919af4bd91a7f57bd2af9539de96db4a14579d2e Mon Sep 17 00:00:00 2001 From: fumihumi Date: Mon, 21 Apr 2025 00:43:52 +0900 Subject: [PATCH 2/6] Database configuration: replace localhost with 127.0.0.1 and add port configuration - Replace all database host settings from 'localhost' to '127.0.0.1' for better compatibility - Add explicit port configuration using ENV['MYSQL_PORT'] with default 3306 --- README.md | 2 +- Rakefile | 3 ++- spec/spec_helper.rb | 3 ++- spec/support/database_connection.rb | 3 ++- spec/support/database_models.rb | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f73075a..8407262 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ default: &default adapter: mysql2 pool: 5 username: root - host: localhost + host: 127.0.0.1 timeout: 5000 connnect_timeout: 5000 diff --git a/Rakefile b/Rakefile index 4778582..9779b49 100644 --- a/Rakefile +++ b/Rakefile @@ -10,8 +10,9 @@ RuboCop::RakeTask.new namespace :db do mysql_spec = { adapter: 'mysql2', - host: (ENV['MYSQL_HOST'] || 'localhost'), + host: (ENV['MYSQL_HOST'] || '127.0.0.1'), username: (ENV['MYSQL_USER'] || 'root'), + port: (ENV['MYSQL_PORT'] || 3306), encoding: 'utf8mb4', } diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index d51f786..3794c0e 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -11,8 +11,9 @@ RSpec.configure do |config| mysql_spec = { adapter: 'mysql2', - host: (ENV['MYSQL_HOST'] || 'localhost'), + host: (ENV['MYSQL_HOST'] || '127.0.0.1'), username: (ENV['MYSQL_USER'] || 'root'), + port: (ENV['MYSQL_PORT'] || 3306), encoding: 'utf8mb4', } ActiveRecord::Base.configurations = { diff --git a/spec/support/database_connection.rb b/spec/support/database_connection.rb index 6f48102..393721b 100644 --- a/spec/support/database_connection.rb +++ b/spec/support/database_connection.rb @@ -4,8 +4,9 @@ mysql_spec = { adapter: 'mysql2', - host: (ENV['MYSQL_HOST'] || 'localhost'), + host: (ENV['MYSQL_HOST'] || '127.0.0.1'), username: (ENV['MYSQL_USER'] || 'root'), + port: (ENV['MYSQL_PORT'] || 3306), encoding: 'utf8mb4', } diff --git a/spec/support/database_models.rb b/spec/support/database_models.rb index 82da656..122dbea 100644 --- a/spec/support/database_models.rb +++ b/spec/support/database_models.rb @@ -20,7 +20,7 @@ class Client < ApplicationRecord # This class sets its own connection class CustomConnectionBase < ActiveRecord::Base self.abstract_class = true - establish_connection(:adapter => 'mysql2', :host => (ENV['MYSQL_HOST'] || 'localhost'), :database => 'octoball_shard_2', :username => "#{ENV['MYSQL_USER'] || 'root'}", :password => '') + establish_connection(:adapter => 'mysql2', :host => (ENV['MYSQL_HOST'] || '127.0.0.1'), :database => 'octoball_shard_2', :username => "#{ENV['MYSQL_USER'] || 'root'}", :password => '', :port => (ENV['MYSQL_PORT'] || 3306)) connects_to shards: { custom_shard: { writing: :shard3 } } From 4222a21d7c3f31cbf8dbf58f9276c3e1ad2323ea Mon Sep 17 00:00:00 2001 From: fumihumi Date: Mon, 21 Apr 2025 00:44:13 +0900 Subject: [PATCH 3/6] chore: Add missing Active Record require in Rakefile --- Rakefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Rakefile b/Rakefile index 9779b49..0fb1ffd 100644 --- a/Rakefile +++ b/Rakefile @@ -32,6 +32,8 @@ namespace :db do desc 'Create tables on tests databases' task :create_tables do + require 'active_record' + ActiveRecord::Base.configurations = { "test" => { shard1: mysql_spec.merge(database: 'octoball_shard_1'), From 3cea423e94a7806c7d6676f3160a2e92a9ed8718 Mon Sep 17 00:00:00 2001 From: fumihumi Date: Mon, 21 Apr 2025 00:57:28 +0900 Subject: [PATCH 4/6] feat: Change database adapter from mysql2 to trilogy - Update all configuration files and code to use trilogy adapter instead of mysql2 --- README.md | 2 +- Rakefile | 2 +- octoball.gemspec | 2 +- spec/spec_helper.rb | 2 +- spec/support/database_connection.rb | 2 +- spec/support/database_models.rb | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 8407262..c1d8d3f 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ Define the database connections in `config/database.yml`, e.g.: ``` default: &default - adapter: mysql2 + adapter: trilogy pool: 5 username: root host: 127.0.0.1 diff --git a/Rakefile b/Rakefile index 0fb1ffd..6bfa273 100644 --- a/Rakefile +++ b/Rakefile @@ -9,7 +9,7 @@ RuboCop::RakeTask.new namespace :db do mysql_spec = { - adapter: 'mysql2', + adapter: 'trilogy', host: (ENV['MYSQL_HOST'] || '127.0.0.1'), username: (ENV['MYSQL_USER'] || 'root'), port: (ENV['MYSQL_PORT'] || 3306), diff --git a/octoball.gemspec b/octoball.gemspec index 6f17172..0a5c30e 100644 --- a/octoball.gemspec +++ b/octoball.gemspec @@ -20,7 +20,7 @@ Gem::Specification.new do |s| s.add_dependency 'activerecord', '>= 7.0' s.add_dependency 'activesupport', '>= 7.0' - s.add_development_dependency 'mysql2' + s.add_development_dependency 'trilogy' s.add_development_dependency 'rake' s.add_development_dependency 'rspec', '>= 3' s.add_development_dependency 'rubocop' diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 3794c0e..e1077f8 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -10,7 +10,7 @@ RSpec.configure do |config| mysql_spec = { - adapter: 'mysql2', + adapter: 'trilogy', host: (ENV['MYSQL_HOST'] || '127.0.0.1'), username: (ENV['MYSQL_USER'] || 'root'), port: (ENV['MYSQL_PORT'] || 3306), diff --git a/spec/support/database_connection.rb b/spec/support/database_connection.rb index 393721b..a6c0292 100644 --- a/spec/support/database_connection.rb +++ b/spec/support/database_connection.rb @@ -3,7 +3,7 @@ ActiveRecord::Base.logger = Logger.new(File.open('database.log', 'a')) mysql_spec = { - adapter: 'mysql2', + adapter: 'trilogy', host: (ENV['MYSQL_HOST'] || '127.0.0.1'), username: (ENV['MYSQL_USER'] || 'root'), port: (ENV['MYSQL_PORT'] || 3306), diff --git a/spec/support/database_models.rb b/spec/support/database_models.rb index 122dbea..0632a63 100644 --- a/spec/support/database_models.rb +++ b/spec/support/database_models.rb @@ -20,7 +20,7 @@ class Client < ApplicationRecord # This class sets its own connection class CustomConnectionBase < ActiveRecord::Base self.abstract_class = true - establish_connection(:adapter => 'mysql2', :host => (ENV['MYSQL_HOST'] || '127.0.0.1'), :database => 'octoball_shard_2', :username => "#{ENV['MYSQL_USER'] || 'root'}", :password => '', :port => (ENV['MYSQL_PORT'] || 3306)) + establish_connection(:adapter => 'trilogy', :host => (ENV['MYSQL_HOST'] || '127.0.0.1'), :database => 'octoball_shard_2', :username => "#{ENV['MYSQL_USER'] || 'root'}", :password => '', :port => (ENV['MYSQL_PORT'] || 3306)) connects_to shards: { custom_shard: { writing: :shard3 } } From b89d6ce1f5e5b50375c3198635c809464ca29fa9 Mon Sep 17 00:00:00 2001 From: fumihumi Date: Mon, 21 Apr 2025 01:10:18 +0900 Subject: [PATCH 5/6] ci: add matrix testing for Ruby and Rails versions - Configure CI to test with Ruby 3.1-3.4 and Rails 7.1/8.0 - Add version-specific Gemfiles in .github/gemfiles/ --- .github/gemfiles/rails_7.1.gemfile | 6 ++++++ .github/gemfiles/rails_7.2.gemfile | 6 ++++++ .github/gemfiles/rails_8.0.gemfile | 6 ++++++ .github/workflows/rspec.yml | 5 +++-- 4 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 .github/gemfiles/rails_7.1.gemfile create mode 100644 .github/gemfiles/rails_7.2.gemfile create mode 100644 .github/gemfiles/rails_8.0.gemfile diff --git a/.github/gemfiles/rails_7.1.gemfile b/.github/gemfiles/rails_7.1.gemfile new file mode 100644 index 0000000..a17a9e9 --- /dev/null +++ b/.github/gemfiles/rails_7.1.gemfile @@ -0,0 +1,6 @@ +source 'https://rubygems.org' + +gemspec :path => '../../' + +gem 'activerecord', '~> 7.1.0' +gem 'activesupport', '~> 7.1.0' diff --git a/.github/gemfiles/rails_7.2.gemfile b/.github/gemfiles/rails_7.2.gemfile new file mode 100644 index 0000000..792a46e --- /dev/null +++ b/.github/gemfiles/rails_7.2.gemfile @@ -0,0 +1,6 @@ +source 'https://rubygems.org' + +gemspec :path => '../../' + +gem 'activerecord', '~> 7.2.0' +gem 'activesupport', '~> 7.2.0' diff --git a/.github/gemfiles/rails_8.0.gemfile b/.github/gemfiles/rails_8.0.gemfile new file mode 100644 index 0000000..f57bc80 --- /dev/null +++ b/.github/gemfiles/rails_8.0.gemfile @@ -0,0 +1,6 @@ +source 'https://rubygems.org' + +gemspec :path => '../../' + +gem 'activerecord', '~> 8.0.0' +gem 'activesupport', '~> 8.0.0' diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index 6cfcbc8..c7094c9 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -17,9 +17,10 @@ jobs: strategy: fail-fast: true matrix: - ruby: ["3.1","3.2","3.3"] + ruby: ["3.1","3.2","3.3", "3.4"] + rails: ["7.1", "7.2", "8.0"] env: - BUNDLE_GEMFILE: .github/Gemfile + BUNDLE_GEMFILE: .github/gemfiles/rails_${{ matrix.rails }}.gemfile MYSQL_HOST: 127.0.0.1 RAILS_ENV: test steps: From 4db1e882d0bb3e518858a57f54b89a12be5daea6 Mon Sep 17 00:00:00 2001 From: fumihumi Date: Mon, 21 Apr 2025 09:51:52 +0900 Subject: [PATCH 6/6] drop ruby 3.1 --- .github/workflows/rspec.yml | 2 +- octoball.gemspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index c7094c9..9a4a60e 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -17,7 +17,7 @@ jobs: strategy: fail-fast: true matrix: - ruby: ["3.1","3.2","3.3", "3.4"] + ruby: ["3.2","3.3", "3.4"] rails: ["7.1", "7.2", "8.0"] env: BUNDLE_GEMFILE: .github/gemfiles/rails_${{ matrix.rails }}.gemfile diff --git a/octoball.gemspec b/octoball.gemspec index 0a5c30e..422dce7 100644 --- a/octoball.gemspec +++ b/octoball.gemspec @@ -15,7 +15,7 @@ Gem::Specification.new do |s| s.homepage = 'https://github.com/aktsk/octoball' s.require_paths = ['lib'] - s.required_ruby_version = '>= 3.1.0' + s.required_ruby_version = '>= 3.2.0' s.add_dependency 'activerecord', '>= 7.0' s.add_dependency 'activesupport', '>= 7.0'