From 78b7db17f4bc7b7352a2eac9dfff3ee7b8e063f8 Mon Sep 17 00:00:00 2001 From: syeopite Date: Wed, 9 Apr 2025 13:07:01 -0700 Subject: [PATCH] Add support for setting max idle http pool size --- config/config.example.yml | 15 ++++++- src/invidious.cr | 11 ++++-- src/invidious/config.cr | 6 ++- src/invidious/yt_backend/connection_pool.cr | 44 +++++++++++++++++---- 4 files changed, 63 insertions(+), 13 deletions(-) diff --git a/config/config.example.yml b/config/config.example.yml index d6119f29..781d0961 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -206,7 +206,7 @@ https_only: false #disable_proxy: false ## -## Size of the HTTP pool used to connect to youtube. Each +## Max size of the HTTP pool used to connect to youtube. Each ## domain ('youtube.com', 'ytimg.com', ...) has its own pool. ## ## Accepted values: a positive integer @@ -215,6 +215,19 @@ https_only: false #pool_size: 100 +## +## Idle size of the HTTP pool used to connect to youtube. Each +## domain ('youtube.com', 'ytimg.com', ...) has its own pool. +## +## When unset this value has the same value as pool_size +## +## Accepted values: a positive integer +## Default: (internally this means that it has the same value as pool_size) +## +#idle pool_size: 100 + + + ## ## Additional cookies to be sent when requesting the youtube API. ## diff --git a/src/invidious.cr b/src/invidious.cr index d3300ece..eb22e9f8 100644 --- a/src/invidious.cr +++ b/src/invidious.cr @@ -91,14 +91,19 @@ SOFTWARE = { "branch" => "#{CURRENT_BRANCH}", } -YT_POOL = YoutubeConnectionPool.new(YT_URL, capacity: CONFIG.pool_size) +YT_POOL = YoutubeConnectionPool.new(YT_URL, max_capacity: CONFIG.pool_size, idle_capacity: CONFIG.idle_pool_size) # Image request pool -GGPHT_POOL = YoutubeConnectionPool.new(URI.parse("https://yt3.ggpht.com"), capacity: CONFIG.pool_size) +GGPHT_POOL = YoutubeConnectionPool.new( + URI.parse("https://yt3.ggpht.com"), + max_capacity: CONFIG.pool_size, + idle_capacity: CONFIG.idle_pool_size +) COMPANION_POOL = CompanionConnectionPool.new( - capacity: CONFIG.pool_size + max_capacity: CONFIG.pool_size, + idle_capacity: CONFIG.idle_pool_size ) # CLI diff --git a/src/invidious/config.cr b/src/invidious/config.cr index 4d69854c..00897371 100644 --- a/src/invidious/config.cr +++ b/src/invidious/config.cr @@ -157,8 +157,12 @@ class Config property host_binding : String = "0.0.0.0" # Path and permissions to make Invidious listen on a UNIX socket instead of a TCP port property socket_binding : SocketBindingConfig? = nil - # Pool size for HTTP requests to youtube.com and ytimg.com (each domain has a separate pool of `pool_size`) + + # Max pool size for HTTP requests to youtube.com and ytimg.com (each domain has a separate pool) property pool_size : Int32 = 100 + # Idle pool size for HTTP requests to youtube.com and ytimg.com (each domain has a separate pool) + property idle_pool_size : Int32? = nil + # HTTP Proxy configuration property http_proxy : HTTPProxyConfig? = nil diff --git a/src/invidious/yt_backend/connection_pool.cr b/src/invidious/yt_backend/connection_pool.cr index 0daed46c..da6f6556 100644 --- a/src/invidious/yt_backend/connection_pool.cr +++ b/src/invidious/yt_backend/connection_pool.cr @@ -4,11 +4,24 @@ private YTIMG_POOLS = {} of String => YoutubeConnectionPool struct YoutubeConnectionPool property! url : URI - property! capacity : Int32 + property! max_capacity : Int32 + property! idle_capacity : Int32 property! timeout : Float64 property pool : DB::Pool(HTTP::Client) - def initialize(url : URI, @capacity = 5, @timeout = 5.0) + def initialize( + url : URI, + *, + @max_capacity : Int32 = 5, + idle_capacity : Int32? = nil, + @timeout : Float64 = 5.0, + ) + if idle_capacity.nil? + @idle_capacity = @max_capacity + else + @idle_capacity = idle_capacity + end + @url = url @pool = build_pool() end @@ -33,10 +46,12 @@ struct YoutubeConnectionPool end private def build_pool + # We call the getter for the instance variables instead of using them directly + # because the getters defined by property! ensures that the value is not a nil options = DB::Pool::Options.new( initial_pool_size: 0, - max_pool_size: capacity, - max_idle_pool_size: capacity, + max_pool_size: max_capacity, + max_idle_pool_size: idle_capacity, checkout_timeout: timeout ) @@ -47,13 +62,22 @@ struct YoutubeConnectionPool end struct CompanionConnectionPool + property! max_capacity : Int32 + property! idle_capacity : Int32 + property! timeout : Float64 property pool : DB::Pool(HTTP::Client) - def initialize(capacity = 5, timeout = 5.0) + def initialize(*, @max_capacity : Int32 = 5, idle_capacity : Int32? = nil, @timeout : Float64 = 5.0) + if idle_capacity.nil? + @idle_capacity = @max_capacity + else + @idle_capacity = idle_capacity + end + options = DB::Pool::Options.new( initial_pool_size: 0, - max_pool_size: capacity, - max_idle_pool_size: capacity, + max_pool_size: max_capacity, + max_idle_pool_size: idle_capacity.not_nil!, checkout_timeout: timeout ) @@ -145,7 +169,11 @@ def get_ytimg_pool(subdomain) return pool else LOGGER.info("ytimg_pool: Creating a new HTTP pool for \"https://#{subdomain}.ytimg.com\"") - pool = YoutubeConnectionPool.new(URI.parse("https://#{subdomain}.ytimg.com"), capacity: CONFIG.pool_size) + pool = YoutubeConnectionPool.new( + URI.parse("https://#{subdomain}.ytimg.com"), + max_capacity: CONFIG.pool_size, + idle_capacity: CONFIG.idle_pool_size + ) YTIMG_POOLS[subdomain] = pool return pool