mirror of
https://gitea.invidious.io/iv-org/shard-crystal-db.git
synced 2024-08-15 00:53:32 +00:00
Introduce DB::ConnectionContext (#44)
* make Database a ConnectionContext. * introduce SingleConnectionContext for independant connections. * add `DB#connect` to create non pooled connections.
This commit is contained in:
parent
c63ea48748
commit
385cf70a8a
8 changed files with 115 additions and 23 deletions
|
@ -43,8 +43,8 @@ class FooDriver < DB::Driver
|
|||
@@row
|
||||
end
|
||||
|
||||
def build_connection(db : DB::Database) : DB::Connection
|
||||
FooConnection.new(db)
|
||||
def build_connection(context : DB::ConnectionContext) : DB::Connection
|
||||
FooConnection.new(context)
|
||||
end
|
||||
|
||||
class FooConnection < DB::Connection
|
||||
|
@ -106,8 +106,8 @@ class BarDriver < DB::Driver
|
|||
@@row
|
||||
end
|
||||
|
||||
def build_connection(db : DB::Database) : DB::Connection
|
||||
BarConnection.new(db)
|
||||
def build_connection(context : DB::ConnectionContext) : DB::Connection
|
||||
BarConnection.new(context)
|
||||
end
|
||||
|
||||
class BarConnection < DB::Connection
|
||||
|
|
|
@ -25,6 +25,25 @@ describe DB do
|
|||
connections.first.closed?.should be_true
|
||||
end
|
||||
|
||||
it "should create a connection and close it" do
|
||||
DummyDriver::DummyConnection.clear_connections
|
||||
DB.connect "dummy://localhost" do |cnn|
|
||||
cnn.should be_a(DummyDriver::DummyConnection)
|
||||
end
|
||||
connections.size.should eq(1)
|
||||
connections.first.closed?.should be_true
|
||||
end
|
||||
|
||||
it "should create a connection and wait for explicit closing" do
|
||||
DummyDriver::DummyConnection.clear_connections
|
||||
cnn = DB.connect "dummy://localhost"
|
||||
cnn.should be_a(DummyDriver::DummyConnection)
|
||||
connections.size.should eq(1)
|
||||
connections.first.closed?.should be_false
|
||||
cnn.close
|
||||
connections.first.closed?.should be_true
|
||||
end
|
||||
|
||||
it "query should close result_set" do
|
||||
with_witness do |w|
|
||||
with_dummy do |db|
|
||||
|
|
|
@ -2,13 +2,13 @@ require "spec"
|
|||
require "../src/db"
|
||||
|
||||
class DummyDriver < DB::Driver
|
||||
def build_connection(db : DB::Database) : DB::Connection
|
||||
DummyConnection.new(db)
|
||||
def build_connection(context : DB::ConnectionContext) : DB::Connection
|
||||
DummyConnection.new(context)
|
||||
end
|
||||
|
||||
class DummyConnection < DB::Connection
|
||||
def initialize(db)
|
||||
super(db)
|
||||
def initialize(context)
|
||||
super(context)
|
||||
@connected = true
|
||||
@@connections ||= [] of DummyConnection
|
||||
@@connections.not_nil! << self
|
||||
|
|
33
src/db.cr
33
src/db.cr
|
@ -113,12 +113,42 @@ module DB
|
|||
end
|
||||
end
|
||||
|
||||
# Opens a connection using the specified *uri*.
|
||||
# The scheme of the *uri* determines the driver to use.
|
||||
# Returned connection must be closed by `Connection#close`.
|
||||
# If a block is used the connection is yielded and closed automatically.
|
||||
def self.connect(uri : URI | String)
|
||||
build_connection(uri)
|
||||
end
|
||||
|
||||
# ditto
|
||||
def self.connect(uri : URI | String, &block)
|
||||
cnn = build_connection(uri)
|
||||
begin
|
||||
yield cnn
|
||||
ensure
|
||||
cnn.close
|
||||
end
|
||||
end
|
||||
|
||||
private def self.build_database(connection_string : String)
|
||||
build_database(URI.parse(connection_string))
|
||||
end
|
||||
|
||||
private def self.build_database(uri : URI)
|
||||
Database.new(driver_class(uri.scheme).new, uri)
|
||||
Database.new(build_driver(uri), uri)
|
||||
end
|
||||
|
||||
private def self.build_connection(connection_string : String)
|
||||
build_connection(URI.parse(connection_string))
|
||||
end
|
||||
|
||||
private def self.build_connection(uri : URI)
|
||||
build_driver(uri).build_connection(SingleConnectionContext.new(uri)).as(Connection)
|
||||
end
|
||||
|
||||
private def self.build_driver(uri : URI)
|
||||
driver_class(uri.scheme).new
|
||||
end
|
||||
|
||||
# :nodoc:
|
||||
|
@ -144,6 +174,7 @@ require "./db/disposable"
|
|||
require "./db/driver"
|
||||
require "./db/statement"
|
||||
require "./db/begin_transaction"
|
||||
require "./db/connection_context"
|
||||
require "./db/connection"
|
||||
require "./db/transaction"
|
||||
require "./db/statement"
|
||||
|
|
|
@ -24,15 +24,15 @@ module DB
|
|||
include BeginTransaction
|
||||
|
||||
# :nodoc:
|
||||
getter database
|
||||
getter context
|
||||
@statements_cache = StringKeyCache(Statement).new
|
||||
@transaction = false
|
||||
getter? prepared_statements : Bool
|
||||
# :nodoc:
|
||||
property auto_release : Bool = true
|
||||
|
||||
def initialize(@database : Database)
|
||||
@prepared_statements = @database.prepared_statements?
|
||||
def initialize(@context : ConnectionContext)
|
||||
@prepared_statements = @context.prepared_statements?
|
||||
end
|
||||
|
||||
# :nodoc:
|
||||
|
@ -59,7 +59,7 @@ module DB
|
|||
protected def do_close
|
||||
@statements_cache.each_value &.close
|
||||
@statements_cache.clear
|
||||
@database.pool.delete self
|
||||
@context.discard self
|
||||
end
|
||||
|
||||
# :nodoc:
|
||||
|
@ -75,7 +75,7 @@ module DB
|
|||
# managed by the database. Should be used
|
||||
# only if the connection was obtained by `Database#checkout`.
|
||||
def release
|
||||
@database.return_to_pool(self)
|
||||
@context.release(self)
|
||||
end
|
||||
|
||||
# :nodoc:
|
||||
|
|
36
src/db/connection_context.cr
Normal file
36
src/db/connection_context.cr
Normal file
|
@ -0,0 +1,36 @@
|
|||
module DB
|
||||
module ConnectionContext
|
||||
# Returns the uri with the connection settings to the database
|
||||
abstract def uri : URI
|
||||
|
||||
# Return whether the statements should be prepared by default
|
||||
abstract def prepared_statements? : Bool
|
||||
|
||||
# Indicates that the *connection* was permanently closed
|
||||
# and should not be used in the future.
|
||||
abstract def discard(connection : Connection)
|
||||
|
||||
# Indicates that the *connection* is no longer needed
|
||||
# and can be reused in the future.
|
||||
abstract def release(connection : Connection)
|
||||
end
|
||||
|
||||
# :nodoc:
|
||||
class SingleConnectionContext
|
||||
include ConnectionContext
|
||||
|
||||
getter uri : URI
|
||||
getter? prepared_statements : Bool
|
||||
|
||||
def initialize(@uri : URI)
|
||||
params = HTTP::Params.parse(uri.query || "")
|
||||
@prepared_statements = DB.fetch_bool(params, "prepared_statements", true)
|
||||
end
|
||||
|
||||
def discard(connection : Connection)
|
||||
end
|
||||
|
||||
def release(connection : Connection)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -23,6 +23,7 @@ module DB
|
|||
# Refer to `QueryMethods` and `SessionMethods` for documentation about querying the database.
|
||||
class Database
|
||||
include SessionMethods(Database, PoolStatement)
|
||||
include ConnectionContext
|
||||
|
||||
# :nodoc:
|
||||
getter driver
|
||||
|
@ -68,6 +69,16 @@ module DB
|
|||
@pool.close
|
||||
end
|
||||
|
||||
# :nodoc:
|
||||
def discard(connection : Connection)
|
||||
@pool.delete connection
|
||||
end
|
||||
|
||||
# :nodoc:
|
||||
def release(connection : Connection)
|
||||
@pool.release connection
|
||||
end
|
||||
|
||||
# :nodoc:
|
||||
def fetch_or_build_prepared_statement(query)
|
||||
@statements_cache.fetch(query) { build_prepared_statement(query) }
|
||||
|
@ -88,11 +99,6 @@ module DB
|
|||
@pool.checkout_some candidates
|
||||
end
|
||||
|
||||
# :nodoc:
|
||||
def return_to_pool(connection)
|
||||
@pool.release connection
|
||||
end
|
||||
|
||||
# yields a connection from the pool
|
||||
# the connection is returned to the pool
|
||||
# when the block ends
|
||||
|
|
|
@ -6,9 +6,9 @@ module DB
|
|||
# ```
|
||||
# require "db"
|
||||
#
|
||||
# class FakeDriver < Driver
|
||||
# def build_connection(db)
|
||||
# FakeConnection.new db
|
||||
# class FakeDriver < DB::Driver
|
||||
# def build_connection(context : DB::ConnectionContext)
|
||||
# FakeConnection.new context
|
||||
# end
|
||||
# end
|
||||
#
|
||||
|
@ -26,7 +26,7 @@ module DB
|
|||
# Refer to `Connection`, `Statement` and `ResultSet` for further
|
||||
# driver implementation instructions.
|
||||
abstract class Driver
|
||||
abstract def build_connection(db : Database) : Connection
|
||||
abstract def build_connection(context : ConnectionContext) : Connection
|
||||
|
||||
def connection_pool_options(params : HTTP::Params)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue