11# frozen_string_literal: true
22
33require 'active_record'
4+ require 'active_record/connection_adapters/mysql2_adapter'
5+
6+ # Monkeypatch the MySQL2 adapter to return hashes with symbol keys by default
7+ module MysqlFramework
8+ module Mysql2AdapterPatch
9+ def configure_connection
10+ super
11+ @raw_connection . query_options [ :as ] = :hash
12+ @raw_connection . query_options [ :symbolize_keys ] = true
13+ @raw_connection . query_options [ :cast_booleans ] = true
14+ end
15+ end
16+ end
17+
18+ ActiveRecord ::ConnectionAdapters ::Mysql2Adapter . prepend ( MysqlFramework ::Mysql2AdapterPatch )
419
520module MysqlFramework
621 class Connector
722 def initialize ( options = { } )
823 @options = default_options . merge ( options )
24+ @connection_map = nil
25+ @map_mutex = Mutex . new
926 end
1027
1128 # This method is called to setup the ActiveRecord connection pool.
1229 def setup
1330 return if @connection_pool
1431
15- # Set default query options for Mysql2::Client before establishing connections
16- Mysql2 ::Client . default_query_options . merge! ( symbolize_keys : true , cast_booleans : true )
17-
1832 ActiveRecord ::Base . establish_connection ( active_record_config )
1933 @connection_pool = ActiveRecord ::Base . connection_pool
34+ @connection_map = { }
2035 end
2136
2237 # This method is called to close all MySQL connections in the pool and dispose of the pool itself.
2338 def dispose
2439 return if @connection_pool . nil?
2540
2641 @connection_pool . disconnect!
42+
43+ @map_mutex . synchronize do
44+ @connection_map . clear
45+ end
46+
2747 @connection_pool = nil
2848 end
2949
@@ -35,16 +55,30 @@ def connections
3555 # This method is called to fetch a client from the connection pool.
3656 def check_out
3757 setup unless @connection_pool
38- @connection_pool . checkout . raw_connection
58+
59+ adapter = @connection_pool . checkout
60+ raw_conn = adapter . raw_connection
61+
62+ @map_mutex . synchronize do
63+ @connection_map [ raw_conn . object_id ] = adapter
64+ end
65+
66+ raw_conn
3967 end
4068
4169 # This method is called to check a client back in to the connection when no longer needed.
4270 def check_in ( client )
4371 return if client . nil? || @connection_pool . nil?
4472
45- # Find the ActiveRecord connection wrapper for this raw connection
46- connection = @connection_pool . connections . find { |conn | conn . raw_connection == client }
47- @connection_pool . checkin ( connection ) if connection
73+ adapter = @map_mutex . synchronize do
74+ @connection_map . delete ( client . object_id )
75+ end
76+
77+ if adapter
78+ @connection_pool . checkin ( adapter )
79+ else
80+ MysqlFramework . logger . warn { "[#{ self . class } ] - Unable to find adapter for raw connection during check_in" }
81+ end
4882 end
4983
5084 # This method is called to use a client from the connection pool.
@@ -77,14 +111,14 @@ def execute(query, provided_client = nil)
77111
78112 # This method is called to execute a query
79113 def query ( query_string , provided_client = nil )
80- with_client ( provided_client ) { |client | client . query ( query_string , ** query_options ) }
114+ with_client ( provided_client ) { |client | client . query ( query_string ) }
81115 end
82116
83117 # This method is called to execute a query which will return multiple result sets in an array
84118 def query_multiple_results ( query_string , provided_client = nil )
85119 results = with_client ( provided_client ) do |client |
86120 result = [ ]
87- result << client . query ( query_string , ** query_options )
121+ result << client . query ( query_string )
88122 result << client . store_result while client . next_result
89123 result . compact
90124 end
@@ -146,9 +180,5 @@ def max_pool_size
146180 def pool_timeout
147181 @pool_timeout ||= Integer ( ENV . fetch ( 'MYSQL_POOL_TIMEOUT' , 5 ) )
148182 end
149-
150- def query_options
151- { as : :hash , symbolize_keys : true , cast_booleans : true }
152- end
153183 end
154184end
0 commit comments