expose database in connection

get/return from pool while result set is been used. still single connection pool
This commit is contained in:
Brian J. Cardiff 2016-02-03 19:30:51 -03:00
parent fa111fd698
commit d45427dfdd
8 changed files with 59 additions and 31 deletions

View file

@ -13,20 +13,18 @@ describe DB do
it "should instantiate driver with connection uri" do it "should instantiate driver with connection uri" do
db = DB.open "dummy://localhost:1027" db = DB.open "dummy://localhost:1027"
db.driver_class.should eq(DummyDriver) db.driver.should be_a(DummyDriver)
db.uri.scheme.should eq("dummy") db.uri.scheme.should eq("dummy")
db.uri.host.should eq("localhost") db.uri.host.should eq("localhost")
db.uri.port.should eq(1027) db.uri.port.should eq(1027)
end end
it "should create a connection and close it" do it "should create a connection and close it" do
cnn = nil DummyDriver::DummyConnection.clear_connections
DB.open "dummy://localhost" do |db| DB.open "dummy://localhost" do |db|
cnn = db.connection
end end
connections.size.should eq(1)
cnn.should be_a(DummyDriver::DummyConnection) connections.first.closed?.should be_true
cnn.not_nil!.closed?.should be_true
end end
it "query should close result_set" do it "query should close result_set" do
@ -61,4 +59,14 @@ describe DB do
end end
connections.first.closed?.should be_true connections.first.closed?.should be_true
end end
it "should raise if the sole connection is been used" do
with_dummy do |db|
db.query "1" do |rs|
expect_raises Exception, /DB Pool Exhausted/ do
db.scalar "2"
end
end
end
end
end end

View file

@ -1,14 +1,13 @@
require "spec" require "spec"
class DummyDriver < DB::Driver class DummyDriver < DB::Driver
def build_connection def build_connection(db : DB::Database) : DB::Connection
DummyConnection.new(uri) DummyConnection.new(db)
end end
class DummyConnection < DB::Connection class DummyConnection < DB::Connection
getter uri def initialize(db)
super(db)
def initialize(@uri)
@@connections ||= [] of DummyConnection @@connections ||= [] of DummyConnection
@@connections.not_nil! << self @@connections.not_nil! << self
end end
@ -60,6 +59,7 @@ class DummyDriver < DB::Driver
end end
protected def do_close protected def do_close
super
end end
end end
@ -74,6 +74,7 @@ class DummyDriver < DB::Driver
end end
protected def do_close protected def do_close
super
end end
def self.last_result_set def self.last_result_set

View file

@ -17,8 +17,14 @@ module DB
abstract class Connection abstract class Connection
include Disposable include Disposable
include QueryMethods include QueryMethods
# :nodoc:
getter database
@statements_cache = {} of String => Statement @statements_cache = {} of String => Statement
def initialize(@database : Database)
end
# :nodoc: # :nodoc:
def prepare(query) : Statement def prepare(query) : Statement
stmt = @statements_cache.fetch(query, nil) stmt = @statements_cache.fetch(query, nil)

View file

@ -8,30 +8,37 @@ module DB
# Refer to `QueryMethods` for documentation about querying the database. # Refer to `QueryMethods` for documentation about querying the database.
class Database class Database
# :nodoc: # :nodoc:
getter driver_class getter driver
# Connection configuration to the database. # Returns the uri with the connection settings to the database
getter uri getter uri
# :nodoc: # :nodoc:
def initialize(@driver_class, @uri) def initialize(@driver, @uri)
@driver = @driver_class.new(@uri) @in_pool = true
@connection = @driver.build_connection @connection = @driver.build_connection(self)
end end
# Closes all connection to the database. # Closes all connection to the database.
def close def close
@connection.close @connection.try &.close
end
# :nodoc:
def connection
@connection
end end
# :nodoc: # :nodoc:
def prepare(query) def prepare(query)
connection.prepare(query) get_from_pool.prepare(query)
end
# :nodoc:
def get_from_pool
raise "DB Pool Exhausted" unless @in_pool
@in_pool = false
@connection.not_nil!
end
# :nodoc:
def return_to_pool(connection)
@in_pool = true
end end
include QueryMethods include QueryMethods

View file

@ -105,7 +105,7 @@ module DB
end end
private def self.build_database(uri : URI) private def self.build_database(uri : URI)
Database.new(driver_class(uri.scheme), uri) Database.new(driver_class(uri.scheme).new, uri)
end end
end end

View file

@ -7,8 +7,8 @@ module DB
# require "db" # require "db"
# #
# class FakeDriver < Driver # class FakeDriver < Driver
# def build_connection # def build_connection(db)
# FakeConnection.new uri # FakeConnection.new db
# end # end
# end # end
# #
@ -18,7 +18,7 @@ module DB
# Access to this fake datbase will be available with # Access to this fake datbase will be available with
# #
# ``` # ```
# DB.open "fake", "..." do |db| # DB.open "fake://..." do |db|
# # ... use db ... # # ... use db ...
# end # end
# ``` # ```
@ -26,11 +26,9 @@ module DB
# Refer to `Connection`, `Statement` and `ResultSet` for further # Refer to `Connection`, `Statement` and `ResultSet` for further
# driver implementation instructions. # driver implementation instructions.
abstract class Driver abstract class Driver
getter uri def initialize
def initialize(@uri : URI)
end end
abstract def build_connection : Connection abstract def build_connection(db : Database) : Connection
end end
end end

View file

@ -21,6 +21,11 @@ module DB
def initialize(@statement : Statement) def initialize(@statement : Statement)
end end
protected def do_close
cnn = statement.connection
cnn.database.return_to_pool(cnn)
end
# TODO add_next_result_set : Bool # TODO add_next_result_set : Bool
# Iterates over all the rows # Iterates over all the rows

View file

@ -18,6 +18,9 @@ module DB
def initialize(@connection) def initialize(@connection)
end end
protected def do_close
end
# See `QueryMethods#exec` # See `QueryMethods#exec`
def exec def exec
perform_exec(Slice(Any).new(0)) # no overload matches ... with types Slice(NoReturn) perform_exec(Slice(Any).new(0)) # no overload matches ... with types Slice(NoReturn)