diff --git a/spec/database_spec.cr b/spec/database_spec.cr index 3915a02..a59ab4b 100644 --- a/spec/database_spec.cr +++ b/spec/database_spec.cr @@ -98,6 +98,22 @@ describe DB::Database do end end + it "should not return connection to pool if checkout explicitly" do + DummyDriver::DummyConnection.clear_connections + DB.open "dummy://localhost:1027?initial_pool_size=1&max_pool_size=1&retry_attempts=0" do |db| + the_cnn = uninitialized DB::Connection + db.using_connection do |cnn| + the_cnn = cnn + db.pool.is_available?(cnn).should be_false + 3.times do + cnn.exec("stmt1") + db.pool.is_available?(cnn).should be_false + end + end + db.pool.is_available?(the_cnn).should be_true + end + end + describe "prepared_statements connection option" do it "defaults to true" do with_dummy "dummy://localhost:1027" do |db| diff --git a/spec/pool_spec.cr b/spec/pool_spec.cr index 1f59aaa..6a1612c 100644 --- a/spec/pool_spec.cr +++ b/spec/pool_spec.cr @@ -42,9 +42,19 @@ end class Closable include DB::Disposable + property before_checkout_called : Bool = false + property after_release_called : Bool = false protected def do_close end + + def before_checkout + @before_checkout_called = true + end + + def after_release + @after_release_called = true + end end describe DB::Pool do @@ -56,7 +66,9 @@ describe DB::Pool do it "should get resource" do pool = DB::Pool.new { Closable.new } - pool.checkout.should be_a Closable + resource = pool.checkout + resource.should be_a Closable + resource.before_checkout_called.should be_true end it "should be available if not checkedout" do @@ -74,8 +86,10 @@ describe DB::Pool do it "should be available if returned" do pool = DB::Pool.new { Closable.new } resource = pool.checkout + resource.after_release_called.should be_false pool.release resource pool.is_available?(resource).should be_true + resource.after_release_called.should be_true end it "should wait for available resource" do diff --git a/src/db/connection.cr b/src/db/connection.cr index 4e02e01..2d256a0 100644 --- a/src/db/connection.cr +++ b/src/db/connection.cr @@ -28,6 +28,8 @@ module DB @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? @@ -60,9 +62,18 @@ module DB @database.pool.delete self end + # :nodoc: + protected def before_checkout + @auto_release = true + end + + # :nodoc: + protected def after_release + end + # :nodoc: def release_from_statement - @database.return_to_pool(self) unless @transaction + @database.return_to_pool(self) if @auto_release && !@transaction end # :nodoc: diff --git a/src/db/database.cr b/src/db/database.cr index f69d5b3..ecf4ffd 100644 --- a/src/db/database.cr +++ b/src/db/database.cr @@ -98,6 +98,7 @@ module DB # when the block ends def using_connection connection = @pool.checkout + connection.auto_release = false begin yield connection ensure diff --git a/src/db/pool.cr b/src/db/pool.cr index ada556d..7ad7c55 100644 --- a/src/db/pool.cr +++ b/src/db/pool.cr @@ -41,6 +41,7 @@ module DB end @available.delete resource + resource.before_checkout resource end @@ -56,6 +57,7 @@ module DB resource = ref.target if resource && is_available?(resource) @available.delete resource + resource.before_checkout return {resource, true} end end @@ -67,6 +69,7 @@ module DB def release(resource : T) : Nil if can_increase_idle_pool @available << resource + resource.after_release @availability_channel.send nil if are_waiting_for_resource? else resource.close