class MysqlFramework::Connector
Public Class Methods
# File lib/mysql_framework/connector.rb, line 5 def initialize(options = {}) @options = default_options.merge(options) @mutex = Mutex.new Mysql2::Client.default_query_options.merge!(symbolize_keys: true, cast_booleans: true) end
Public Instance Methods
This method is called to check a client back in to the connection when no longer needed.
# File lib/mysql_framework/connector.rb, line 66 def check_in(client) @mutex.synchronize do return client&.close unless connection_pool_enabled? client = new_client if client&.closed? @connection_pool.push(client) end end
This method is called to fetch a client from the connection pool.
# File lib/mysql_framework/connector.rb, line 41 def check_out @mutex.synchronize do begin return new_client unless connection_pool_enabled? client = @connection_pool.pop(true) client.ping if @options[:reconnect] client rescue ThreadError if @created_connections < max_pool_size client = new_client @created_connections += 1 return client end MysqlFramework.logger.error { "[#{self.class}] - Database connection pool depleted." } raise 'Database connection pool depleted.' end end end
This method is called to get the idle connection queue for this connector.
# File lib/mysql_framework/connector.rb, line 36 def connections @connection_pool end
This method is called to close all MySQL connections in the pool and dispose of the pool itself.
# File lib/mysql_framework/connector.rb, line 24 def dispose return if @connection_pool.nil? until @connection_pool.empty? conn = @connection_pool.pop(true) conn&.close end @connection_pool = nil end
This method is called to execute a prepared statement
@note Ensure we free any result and close each statement, otherwise we can run into a 'Commands out of sync' error if multiple threads are running different queries at the same time.
# File lib/mysql_framework/connector.rb, line 88 def execute(query, provided_client = nil) with_client(provided_client) do |client| begin statement = client.prepare(query.sql) result = statement.execute(*query.params) result&.to_a ensure result&.free statement&.close end end end
This method is called to execute a query
# File lib/mysql_framework/connector.rb, line 102 def query(query_string, provided_client = nil) with_client(provided_client) { |client| client.query(query_string) } end
This method is called to execute a query which will return multiple result sets in an array
# File lib/mysql_framework/connector.rb, line 107 def query_multiple_results(query_string, provided_client = nil) results = with_client(provided_client) do |client| result = [] result << client.query(query_string) result << client.store_result while client.next_result result.compact end results.map(&:to_a) end
This method is called to setup a pool of MySQL connections.
# File lib/mysql_framework/connector.rb, line 13 def setup return unless connection_pool_enabled? @connection_pool = ::Queue.new start_pool_size.times { @connection_pool.push(new_client) } @created_connections = start_pool_size end
This method is called to use a client within a transaction
# File lib/mysql_framework/connector.rb, line 119 def transaction raise ArgumentError, 'No block was given' unless block_given? with_client do |client| begin client.query('BEGIN') yield client client.query('COMMIT') rescue StandardError => e client.query('ROLLBACK') raise e end end end
This method is called to use a client from the connection pool.
# File lib/mysql_framework/connector.rb, line 76 def with_client(provided = nil) client = provided || check_out yield client ensure check_in(client) unless provided end
Private Instance Methods
# File lib/mysql_framework/connector.rb, line 153 def connection_pool_enabled? @connection_pool_enabled ||= ENV.fetch('MYSQL_CONNECTION_POOL_ENABLED', 'true').casecmp?('true') end
# File lib/mysql_framework/connector.rb, line 136 def default_options { host: ENV.fetch('MYSQL_HOST'), port: ENV.fetch('MYSQL_PORT'), database: ENV.fetch('MYSQL_DATABASE'), username: ENV.fetch('MYSQL_USERNAME'), password: ENV.fetch('MYSQL_PASSWORD'), reconnect: true, read_timeout: Integer(ENV.fetch('MYSQL_READ_TIMEOUT', 30)), write_timeout: Integer(ENV.fetch('MYSQL_WRITE_TIMEOUT', 10)) } end
# File lib/mysql_framework/connector.rb, line 161 def max_pool_size @max_pool_size ||= Integer(ENV.fetch('MYSQL_MAX_POOL_SIZE', 5)) end
# File lib/mysql_framework/connector.rb, line 149 def new_client Mysql2::Client.new(@options) end
# File lib/mysql_framework/connector.rb, line 157 def start_pool_size @start_pool_size ||= Integer(ENV.fetch('MYSQL_START_POOL_SIZE', 1)) end