Skip to content

Commit

Permalink
Merge pull request #40 from Sage/mutex
Browse files Browse the repository at this point in the history
Use a mutex when checking out and checking in connections
  • Loading branch information
ianoxley authored Mar 12, 2021
2 parents 34c0f3a + c7983fe commit 3eb56ab
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 17 deletions.
39 changes: 23 additions & 16 deletions lib/mysql_framework/connector.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module MysqlFramework
class Connector
def initialize(options = {})
@options = default_options.merge(options)
@mutex = Mutex.new

Mysql2::Client.default_query_options.merge!(symbolize_keys: true, cast_booleans: true)
end
Expand All @@ -25,7 +26,7 @@ def dispose

until @connection_pool.empty?
conn = @connection_pool.pop(true)
conn.close
conn&.close
end

@connection_pool = nil
Expand All @@ -38,31 +39,37 @@ def connections

# This method is called to fetch a client from the connection pool.
def check_out
return new_client unless connection_pool_enabled?
@mutex.synchronize do
begin
return new_client unless connection_pool_enabled?

client = @connection_pool.pop(true)
client = @connection_pool.pop(true)

client.ping if @options[:reconnect]
client.ping if @options[:reconnect]

client
rescue ThreadError
if @created_connections < max_pool_size
client = new_client
@created_connections += 1
return client
end
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." }
MysqlFramework.logger.error { "[#{self.class}] - Database connection pool depleted." }

raise 'Database connection pool depleted.'
raise 'Database connection pool depleted.'
end
end
end

# This method is called to check a client back in to the connection when no longer needed.
def check_in(client)
return client&.close unless connection_pool_enabled?
@mutex.synchronize do
return client&.close unless connection_pool_enabled?

client = new_client if client.nil? || client.closed?
@connection_pool.push(client)
client = new_client if client&.closed?
@connection_pool.push(client)
end
end

# This method is called to use a client from the connection pool.
Expand Down
2 changes: 1 addition & 1 deletion lib/mysql_framework/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module MysqlFramework
VERSION = '2.1.3'
VERSION = '2.1.4'
end
12 changes: 12 additions & 0 deletions spec/lib/mysql_framework/connector_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,12 @@
end

describe '#check_out' do
it 'calls synchronize on the mutex' do
expect(subject.instance_variable_get(:@mutex)).to receive(:synchronize)

subject.check_out
end

context 'when connection pooling is enabled' do
context 'when there are available connections' do
before do
Expand Down Expand Up @@ -203,6 +209,12 @@
end

describe '#check_in' do
it 'calls synchronize on the mutex' do
expect(subject.instance_variable_get(:@mutex)).to receive(:synchronize)

subject.check_out
end

context 'when connection pooling is enabled' do
it 'returns the provided client to the connection pool' do
expect(subject.connections).to receive(:push).with(client)
Expand Down

0 comments on commit 3eb56ab

Please sign in to comment.