From a25f33611c15b19b365eeba3ce4d585909d93566 Mon Sep 17 00:00:00 2001 From: Stephen von Takach Date: Fri, 10 Sep 2021 21:36:01 +1000 Subject: [PATCH] feat(error): close resources on resource lost (#155) --- spec/database_spec.cr | 15 +++++++++++++++ src/db/error.cr | 1 + src/db/pool.cr | 8 +++++--- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/spec/database_spec.cr b/spec/database_spec.cr index e35a98f..31db8bd 100644 --- a/spec/database_spec.cr +++ b/spec/database_spec.cr @@ -172,6 +172,21 @@ describe DB::Database do end end + it "should close connection on ConnectionLost" do + DummyDriver::DummyConnection.clear_connections + DB.open "dummy://localhost:1027?initial_pool_size=1&max_pool_size=1&retry_attempts=1" do |db| + db.exec("stmt1") + DummyDriver::DummyConnection.connections.size.should eq(1) + connection = DummyDriver::DummyConnection.connections.first + connection.disconnect! + connection.closed?.should be_false + db.exec("stmt1") + # A new connection was used for the last statement + DummyDriver::DummyConnection.connections.size.should eq(2) + connection.closed?.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/src/db/error.cr b/src/db/error.cr index 5923479..d3c5862 100644 --- a/src/db/error.cr +++ b/src/db/error.cr @@ -18,6 +18,7 @@ module DB getter resource : T def initialize(@resource : T) + @resource.close end end diff --git a/src/db/pool.cr b/src/db/pool.cr index 5964de8..28ea417 100644 --- a/src/db/pool.cr +++ b/src/db/pool.cr @@ -179,10 +179,12 @@ module DB sleep @retry_delay if i >= current_available return yield rescue e : PoolResourceLost(T) - # if the connection is lost close it to release resources - # and remove it from the known pool. + # if the connection is lost it will be closed by + # the exception to release resources + # we still need to remove it from the known pool. + # Closed connection will be evicted from statement cache + # in PoolPreparedStatement#clean_connections sync { delete(e.resource) } - e.resource.close rescue e : PoolResourceRefused # a ConnectionRefused means a new connection # was intended to be created