diff --git a/src/Orbit.Infrastructure/Persistence/OrbitConnectionStringFactory.cs b/src/Orbit.Infrastructure/Persistence/OrbitConnectionStringFactory.cs index 3f464dd97..651130fc9 100644 --- a/src/Orbit.Infrastructure/Persistence/OrbitConnectionStringFactory.cs +++ b/src/Orbit.Infrastructure/Persistence/OrbitConnectionStringFactory.cs @@ -11,7 +11,9 @@ namespace Orbit.Infrastructure.Persistence; /// migrations, the design-time factory, and the Hangfire durable queue use /// ConnectionStrings:SessionConnection (the session pooler), falling back to /// DefaultConnection when it is unset. The configured -/// pool caps override any pool size present in the raw connection string. +/// pool caps override any pool size present in the raw connection string. Idle session-pool connections +/// are pruned after 60 seconds, and open inactive session connections receive keepalive queries after +/// 30 seconds to detect connections closed by the pooler or network. /// public static class OrbitConnectionStringFactory { @@ -28,7 +30,15 @@ public static string ForSession(IConfiguration configuration) if (string.IsNullOrWhiteSpace(sessionConnectionString)) sessionConnectionString = configuration.GetConnectionString("DefaultConnection"); - return ApplyPoolCap(sessionConnectionString, settings.SessionMaxPoolSize); + var cappedConnectionString = ApplyPoolCap(sessionConnectionString, settings.SessionMaxPoolSize); + if (string.IsNullOrEmpty(cappedConnectionString)) + return cappedConnectionString; + + return new NpgsqlConnectionStringBuilder(cappedConnectionString) + { + ConnectionIdleLifetime = 60, + KeepAlive = 30 + }.ConnectionString; } private static string ApplyPoolCap(string? connectionString, int maxPoolSize) diff --git a/tests/Orbit.Infrastructure.Tests/Persistence/OrbitConnectionStringFactoryTests.cs b/tests/Orbit.Infrastructure.Tests/Persistence/OrbitConnectionStringFactoryTests.cs index a75ac180a..f27901425 100644 --- a/tests/Orbit.Infrastructure.Tests/Persistence/OrbitConnectionStringFactoryTests.cs +++ b/tests/Orbit.Infrastructure.Tests/Persistence/OrbitConnectionStringFactoryTests.cs @@ -54,6 +54,9 @@ public void ForSession_PrefersSessionConnection_OverDefault() result.Host.Should().Be("session"); result.Port.Should().Be(5432); result.MaxPoolSize.Should().Be(5); + result.MinPoolSize.Should().Be(0); + result.ConnectionIdleLifetime.Should().Be(60); + result.KeepAlive.Should().Be(30); } [Theory]