From 5b736d3f188a5314c59a3c1be22f865668327777 Mon Sep 17 00:00:00 2001 From: fatkodima Date: Mon, 11 Aug 2025 00:20:36 +0300 Subject: [PATCH] Support connection reaping --- lib/net/http/persistent/timed_stack_multi.rb | 27 +++++++++++++-- test/test_net_http_persistent.rb | 36 ++++++++++++++++++++ 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/lib/net/http/persistent/timed_stack_multi.rb b/lib/net/http/persistent/timed_stack_multi.rb index 9924a0a..aa4be89 100644 --- a/lib/net/http/persistent/timed_stack_multi.rb +++ b/lib/net/http/persistent/timed_stack_multi.rb @@ -27,6 +27,10 @@ def length @max - @created + @enqueued end + def idle + @enqueued + end + private def connection_stored? options = {} # :nodoc: @@ -38,7 +42,8 @@ def fetch_connection options = {} # :nodoc: @enqueued -= 1 lru_update connection_args - @ques[connection_args].pop + connection, = @ques[connection_args].pop + connection end def lru_update connection_args # :nodoc: @@ -53,7 +58,7 @@ def shutdown_connections # :nodoc: end def store_connection obj, options = {} # :nodoc: - @ques[options[:connection_args]].push obj + @ques[options[:connection_args]].push [obj, current_time] @enqueued += 1 end @@ -63,7 +68,7 @@ def try_create options = {} # :nodoc: if @created >= @max && @enqueued >= 1 oldest, = @lru.first @lru.delete oldest - connection = @ques[oldest].pop + connection, = @ques[oldest].pop connection.close if connection.respond_to?(:close) @created -= 1 @@ -76,5 +81,21 @@ def try_create options = {} # :nodoc: end end + def reserve_idle_connection(idle_seconds) + @ques.each_value do |que| + next if que.empty? + + if current_time - que.first.last > idle_seconds + @created -= 1 + @enqueued -= 1 + + connection, = que.shift + return connection + end + end + + nil + end + end diff --git a/test/test_net_http_persistent.rb b/test/test_net_http_persistent.rb index 145f3cc..ce4a4fe 100644 --- a/test/test_net_http_persistent.rb +++ b/test/test_net_http_persistent.rb @@ -1530,4 +1530,40 @@ def test_connection_pool_after_fork connection.close end end + + def test_reap_pool_removes_idle_connections + assert_equal 0, @http.pool.idle + + connection + @http.request(@uri) + + assert_equal 1, @http.pool.idle + + @http.pool.reap(0) {} + assert_equal 0, @http.pool.idle + end + + def test_reap_pool_removes_all_idle_connections + connection + connection @uri_v6 + + @http.request(@uri) + @http.request(@uri_v6) + + assert_equal 2, @http.pool.idle + + @http.pool.reap(0) {} + assert_equal 0, @http.pool.idle + end + + def test_reap_pool_does_not_remove_connections_if_outside_idle_time + connection + @http.request(@uri) + + assert_equal 1, @http.pool.idle + + @http.pool.reap(1000) {} + assert_equal 1, @http.pool.idle + end + end