Skip to content

Commit

Permalink
Merge pull request #117 from zendesk/nony--trilogy
Browse files Browse the repository at this point in the history
Add support for Trilogy mysql adapter
  • Loading branch information
HeyNonster committed Jul 18, 2023
2 parents 37226c2 + 4e115dc commit bd6584b
Show file tree
Hide file tree
Showing 20 changed files with 233 additions and 79 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Expand Up @@ -38,7 +38,8 @@ jobs:
- "3.2"
gemfile:
- rails6.1
- rails7.0
- rails7.0_mysql2
- rails7.0_trilogy
legacy_connection_handling:
- "false"
- "true"
Expand Down
2 changes: 2 additions & 0 deletions Changelog.md
Expand Up @@ -6,6 +6,8 @@ and as of v1.0.0 this project adheres to [Semantic Versioning](https://semver.or

## [Unreleased]

- Remove `mysql2` as a direct dependency, test Rails 7.0 with `mysql2` and `activerecord-trilogy-adapter`

## [1.2.5] - 2023-07-14
### Added
- Start testing with Ruby 3.2.
Expand Down
2 changes: 1 addition & 1 deletion Readme.md
Expand Up @@ -43,7 +43,7 @@ test_pool_2 => 127.0.0.1/3306//root/false

## Support

For now, the only backend known to work is MySQL, with the mysql2 gem.
For now, the only backend known to work is MySQL, with the mysql2 or activerecord-trilogy-adapter gem.
Postgres, from an informal reading of the docs, will never support the concept of one server connection sharing multiple dbs.

## Installation
Expand Down
1 change: 0 additions & 1 deletion active_record_host_pool.gemspec
Expand Up @@ -29,5 +29,4 @@ Gem::Specification.new do |s|
s.required_ruby_version = ">= 2.7.0"

s.add_runtime_dependency("activerecord", ">= 5.1.0", "< 7.1")
s.add_runtime_dependency("mysql2")
end
1 change: 0 additions & 1 deletion gemfiles/rails5.1.gemfile.lock
Expand Up @@ -3,7 +3,6 @@ PATH
specs:
active_record_host_pool (1.2.5)
activerecord (>= 5.1.0, < 7.1)
mysql2

GEM
remote: https://rubygems.org/
Expand Down
1 change: 0 additions & 1 deletion gemfiles/rails5.2.gemfile.lock
Expand Up @@ -3,7 +3,6 @@ PATH
specs:
active_record_host_pool (1.2.5)
activerecord (>= 5.1.0, < 7.1)
mysql2

GEM
remote: https://rubygems.org/
Expand Down
1 change: 0 additions & 1 deletion gemfiles/rails6.0.gemfile.lock
Expand Up @@ -3,7 +3,6 @@ PATH
specs:
active_record_host_pool (1.2.5)
activerecord (>= 5.1.0, < 7.1)
mysql2

GEM
remote: https://rubygems.org/
Expand Down
1 change: 0 additions & 1 deletion gemfiles/rails6.1.gemfile.lock
Expand Up @@ -3,7 +3,6 @@ PATH
specs:
active_record_host_pool (1.2.5)
activerecord (>= 5.1.0, < 7.1)
mysql2

GEM
remote: https://rubygems.org/
Expand Down
File renamed without changes.
Expand Up @@ -3,40 +3,40 @@ PATH
specs:
active_record_host_pool (1.2.5)
activerecord (>= 5.1.0, < 7.1)
mysql2

GEM
remote: https://rubygems.org/
specs:
activemodel (7.0.4.3)
activesupport (= 7.0.4.3)
activerecord (7.0.4.3)
activemodel (= 7.0.4.3)
activesupport (= 7.0.4.3)
activesupport (7.0.4.3)
activemodel (7.0.5)
activesupport (= 7.0.5)
activerecord (7.0.5)
activemodel (= 7.0.5)
activesupport (= 7.0.5)
activesupport (7.0.5)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
ast (2.4.2)
byebug (11.1.3)
coderay (1.1.3)
concurrent-ruby (1.1.10)
i18n (1.12.0)
concurrent-ruby (1.2.2)
i18n (1.14.1)
concurrent-ruby (~> 1.0)
jaro_winkler (1.5.4)
jaro_winkler (1.5.6)
method_source (1.0.0)
minitest (5.16.3)
minitest (5.18.1)
minitest-fail-fast (0.1.0)
minitest (~> 5)
minitest-line (0.6.5)
minitest (~> 5.0)
minitest-mock_expectations (1.1.3)
mysql2 (0.5.5)
parallel (1.22.1)
parser (3.1.2.1)
parallel (1.23.0)
parser (3.2.2.3)
ast (~> 2.4.1)
phenix (1.0.1)
racc
phenix (1.1.0)
activerecord (>= 4.2, < 7.1)
bundler
pry (0.14.2)
Expand All @@ -45,6 +45,7 @@ GEM
pry-byebug (3.10.1)
byebug (~> 11.0)
pry (>= 0.13, < 0.15)
racc (1.7.1)
rainbow (3.1.1)
rake (13.0.6)
rexml (3.2.5)
Expand All @@ -56,8 +57,8 @@ GEM
rexml
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 1.7)
ruby-progressbar (1.11.0)
tzinfo (2.0.5)
ruby-progressbar (1.13.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (1.6.1)

Expand Down
10 changes: 10 additions & 0 deletions gemfiles/rails7.0_trilogy.gemfile
@@ -0,0 +1,10 @@
# frozen_string_literal: true

source 'https://rubygems.org'

gemspec path: '../'

gem 'activerecord', '~> 7.0.0'
gem 'activerecord-trilogy-adapter', '>= 3.0'

eval_gemfile 'common.rb'
86 changes: 86 additions & 0 deletions gemfiles/rails7.0_trilogy.gemfile.lock
@@ -0,0 +1,86 @@
PATH
remote: ..
specs:
active_record_host_pool (1.2.5)
activerecord (>= 5.1.0, < 7.1)

GEM
remote: https://rubygems.org/
specs:
activemodel (7.0.5)
activesupport (= 7.0.5)
activerecord (7.0.5)
activemodel (= 7.0.5)
activesupport (= 7.0.5)
activerecord-trilogy-adapter (3.0.0)
activerecord (>= 7.0, < 7.1a)
trilogy (>= 2.4.0)
activesupport (7.0.5)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
ast (2.4.2)
byebug (11.1.3)
coderay (1.1.3)
concurrent-ruby (1.2.2)
i18n (1.14.1)
concurrent-ruby (~> 1.0)
jaro_winkler (1.5.6)
method_source (1.0.0)
minitest (5.18.1)
minitest-fail-fast (0.1.0)
minitest (~> 5)
minitest-line (0.6.5)
minitest (~> 5.0)
minitest-mock_expectations (1.1.3)
parallel (1.23.0)
parser (3.2.2.3)
ast (~> 2.4.1)
racc
phenix (1.1.0)
activerecord (>= 4.2, < 7.1)
bundler
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.1)
rainbow (3.1.1)
rake (13.0.6)
rexml (3.2.5)
rubocop (0.80.1)
jaro_winkler (~> 1.5.1)
parallel (~> 1.10)
parser (>= 2.7.0.1)
rainbow (>= 2.2.2, < 4.0)
rexml
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 1.7)
ruby-progressbar (1.13.0)
trilogy (2.4.1)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (1.6.1)

PLATFORMS
ruby

DEPENDENCIES
active_record_host_pool!
activerecord (~> 7.0.0)
activerecord-trilogy-adapter (>= 3.0)
byebug
minitest (>= 5.10.0)
minitest-fail-fast
minitest-line
minitest-mock_expectations (~> 1.1.3)
phenix (>= 1.0.1)
pry-byebug (~> 3.9)
rake (>= 12.0.0)
rubocop (~> 0.80.0)

BUNDLED WITH
2.4.13
17 changes: 14 additions & 3 deletions lib/active_record_host_pool.rb
@@ -1,5 +1,19 @@
# frozen_string_literal: true

module ActiveRecordHostPool
class << self
attr_accessor :loaded_db_adapter
end
end

begin
require 'mysql2'
ActiveRecordHostPool.loaded_db_adapter = :mysql2
rescue LoadError
require 'activerecord-trilogy-adapter'
ActiveRecordHostPool.loaded_db_adapter = :trilogy
end

require 'active_record'
require 'active_record/base'
require 'active_record/connection_adapters/abstract_adapter'
Expand All @@ -9,6 +23,3 @@
require 'active_record_host_pool/pool_proxy'
require 'active_record_host_pool/connection_adapter_mixin'
require 'active_record_host_pool/version'

module ActiveRecordHostPool
end
40 changes: 36 additions & 4 deletions lib/active_record_host_pool/connection_adapter_mixin.rb
@@ -1,9 +1,23 @@
# frozen_string_literal: true

require "active_record/connection_adapters/mysql2_adapter"
case ActiveRecordHostPool.loaded_db_adapter
when :mysql2
require "active_record/connection_adapters/mysql2_adapter"
when :trilogy
require 'trilogy_adapter/connection'
require "trilogy_adapter/errors"
ActiveRecord::Base.extend TrilogyAdapter::Connection
end

module ActiveRecordHostPool
module DatabaseSwitch
case ActiveRecordHostPool.loaded_db_adapter
when :mysql2
DB_SWITCHING_METHOD = "select_db"
when :trilogy
DB_SWITCHING_METHOD = "change_db"
end

def self.included(base)
base.class_eval do
attr_reader(:_host_pool_current_database)
Expand Down Expand Up @@ -73,15 +87,28 @@ def _switch_connection
(_host_pool_current_database != @_cached_current_database) ||
@connection.object_id != @_cached_connection_object_id
)
log("select_db #{_host_pool_current_database}", "SQL") do
log("#{DB_SWITCHING_METHOD} #{_host_pool_current_database}", "SQL") do
clear_cache!
raw_connection.select_db(_host_pool_current_database)
_arhp_select_db(_host_pool_current_database)
end
@_cached_current_database = _host_pool_current_database
@_cached_connection_object_id = @connection.object_id
end
end

case ActiveRecordHostPool.loaded_db_adapter
when :mysql2
def _arhp_select_db(database)
raw_connection.select_db(database)
end
when :trilogy
# rubocop:disable Lint/DuplicateMethods
def _arhp_select_db(database)
raw_connection.change_db(database)
end
# rubocop:enable Lint/DuplicateMethods
end

# prevent different databases from sharing the same query cache
def cache_sql(sql, *args)
super(_host_pool_current_database.to_s + "/" + sql, *args)
Expand Down Expand Up @@ -122,7 +149,12 @@ def establish_connection(spec)
end
end

ActiveRecord::ConnectionAdapters::Mysql2Adapter.include(ActiveRecordHostPool::DatabaseSwitch)
case ActiveRecordHostPool.loaded_db_adapter
when :mysql2
ActiveRecord::ConnectionAdapters::Mysql2Adapter.include(ActiveRecordHostPool::DatabaseSwitch)
when :trilogy
ActiveRecord::ConnectionAdapters::TrilogyAdapter.include(ActiveRecordHostPool::DatabaseSwitch)
end

# In Rails 6.1 Connection Pools are no longer instantiated in #establish_connection but in a
# new pool method.
Expand Down
9 changes: 8 additions & 1 deletion lib/active_record_host_pool/pool_proxy_6_1.rb
Expand Up @@ -18,6 +18,13 @@ module ActiveRecordHostPool
class PoolProxy < Delegator
include Mutex_m

case ActiveRecordHostPool.loaded_db_adapter
when :mysql2
RESCUABLE_DB_ERROR = Mysql2::Error
when :trilogy
RESCUABLE_DB_ERROR = Trilogy::ProtocolError
end

def initialize(pool_config)
super(pool_config)
@pool_config = pool_config
Expand All @@ -39,7 +46,7 @@ def __setobj__(pool_config)
def connection(*args)
real_connection = _unproxied_connection(*args)
_connection_proxy_for(real_connection, @config[:database])
rescue Mysql2::Error, ActiveRecord::NoDatabaseError
rescue RESCUABLE_DB_ERROR, ActiveRecord::NoDatabaseError, ActiveRecord::StatementInvalid
_connection_pools.delete(_pool_key)
Kernel.raise
end
Expand Down

0 comments on commit bd6584b

Please sign in to comment.