Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SNOW-902632 connection string driven pool config #873

Merged
69 changes: 38 additions & 31 deletions README.md

Large diffs are not rendered by default.

40 changes: 29 additions & 11 deletions Snowflake.Data.Tests/IntegrationTests/ConnectionMultiplePoolsIT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,20 +102,16 @@ public void TestReuseSessionInConnectionPoolReachingMaxConnections() // old name
public void TestWaitForTheIdleConnectionWhenExceedingMaxConnectionsLimit()
{
// arrange
var connectionString = ConnectionString + "application=TestWaitForMaxSize1";
var connectionString = ConnectionString + "application=TestWaitForMaxSize1;waitingForIdleSessionTimeout=1s;maxPoolSize=2";
sfc-gh-mhofman marked this conversation as resolved.
Show resolved Hide resolved
var pool = SnowflakeDbConnectionPool.GetPool(connectionString);
Assert.AreEqual(0, pool.GetCurrentPoolSize(), "expecting pool to be empty");
sfc-gh-knozderko marked this conversation as resolved.
Show resolved Hide resolved
pool.SetMaxPoolSize(2);
pool.SetWaitingForSessionToReuseTimeout(1000);
var conn1 = OpenedConnection(connectionString);
var conn2 = OpenedConnection(connectionString);
var watch = new StopWatch();

// act
watch.Start();
var start = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
var thrown = Assert.Throws<SnowflakeDbException>(() => OpenedConnection(connectionString));
var stop = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
watch.Stop();

// assert
Expand All @@ -132,11 +128,9 @@ public void TestWaitForTheIdleConnectionWhenExceedingMaxConnectionsLimit()
public void TestWaitForTheIdleConnectionWhenExceedingMaxConnectionsLimitAsync()
{
// arrange
var connectionString = ConnectionString + "application=TestWaitForMaxSize2";
var connectionString = ConnectionString + "application=TestWaitForMaxSize2;waitingForIdleSessionTimeout=1s;maxPoolSize=2";
var pool = SnowflakeDbConnectionPool.GetPool(connectionString);
Assert.AreEqual(0, pool.GetCurrentPoolSize(), "expecting pool to be empty");
pool.SetMaxPoolSize(2);
pool.SetWaitingForSessionToReuseTimeout(1000);
var conn1 = OpenedConnection(connectionString);
var conn2 = OpenedConnection(connectionString);
var watch = new StopWatch();
Expand All @@ -163,11 +157,9 @@ public void TestWaitForTheIdleConnectionWhenExceedingMaxConnectionsLimitAsync()
public void TestWaitInAQueueForAnIdleSession()
{
// arrange
var connectionString = ConnectionString + "application=TestWaitForMaxSize3";
var connectionString = ConnectionString + "application=TestWaitForMaxSize3;waitingForIdleSessionTimeout=3s;maxPoolSize=2";
var pool = SnowflakeDbConnectionPool.GetPool(connectionString);
Assert.AreEqual(0, pool.GetCurrentPoolSize(), "the pool is expected to be empty");
pool.SetMaxPoolSize(2);
pool.SetWaitingForSessionToReuseTimeout(3000);
const long ADelay = 0;
const long BDelay = 400;
const long CDelay = 2 * BDelay;
Expand Down Expand Up @@ -305,6 +297,32 @@ public void TestNewConnectionPoolClean()
Assert.AreEqual(ConnectionState.Closed, conn2.State);
Assert.AreEqual(ConnectionState.Closed, conn3.State);
}

[Test]
public void TestConnectionPoolExpirationWorks()
{
var conn1 = new SnowflakeDbConnection();
conn1.ConnectionString = ConnectionString;
conn1.Open();
conn1.Close();
sfc-gh-mhofman marked this conversation as resolved.
Show resolved Hide resolved
SnowflakeDbConnectionPool.SetTimeout(0);
sfc-gh-knozderko marked this conversation as resolved.
Show resolved Hide resolved
SnowflakeDbConnectionPool.SetMaxPoolSize(2);

var conn2 = new SnowflakeDbConnection();
conn2.ConnectionString = ConnectionString;
conn2.Open();
conn2.Close();

var conn3 = new SnowflakeDbConnection();
conn3.ConnectionString = ConnectionString;
conn3.Open();
conn3.Close();

// The pooling timeout should apply to all connections being pooled,
// not just the connections created after the new setting,
// so expected result should be 0
sfc-gh-knozderko marked this conversation as resolved.
Show resolved Hide resolved
Assert.AreEqual(0, SnowflakeDbConnectionPool.GetPool(ConnectionString).GetCurrentPoolSize());
}

private SnowflakeDbConnection OpenedConnection(string connectionString)
{
Expand Down
28 changes: 0 additions & 28 deletions Snowflake.Data.Tests/IntegrationTests/ConnectionPoolCommonIT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,34 +64,6 @@ public void TestBasicConnectionPool()
Assert.AreEqual(1, SnowflakeDbConnectionPool.GetPool(ConnectionString).GetCurrentPoolSize());
}

[Test]
sfc-gh-mhofman marked this conversation as resolved.
Show resolved Hide resolved
public void TestConnectionPoolExpirationWorks()
{
SnowflakeDbConnectionPool.SetMaxPoolSize(2);
SnowflakeDbConnectionPool.SetTimeout(10);

var conn1 = new SnowflakeDbConnection();
conn1.ConnectionString = ConnectionString;

conn1.Open();
conn1.Close();
SnowflakeDbConnectionPool.SetTimeout(-1);

var conn2 = new SnowflakeDbConnection();
conn2.ConnectionString = ConnectionString;
conn2.Open();
conn2.Close();
var conn3 = new SnowflakeDbConnection();
conn3.ConnectionString = ConnectionString;
conn3.Open();
conn3.Close();

// The pooling timeout should apply to all connections being pooled,
// not just the connections created after the new setting,
// so expected result should be 0
Assert.AreEqual(0, SnowflakeDbConnectionPool.GetPool(ConnectionString).GetCurrentPoolSize());
}

[Test]
public void TestConnectionPoolMultiThreading()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,5 +256,34 @@ public void TestConnectionPoolClean()
Assert.AreEqual(ConnectionState.Closed, conn2.State);
Assert.AreEqual(ConnectionState.Closed, conn3.State);
}

[Test]
public void TestConnectionPoolExpirationWorks()
{
SnowflakeDbConnectionPool.SetMaxPoolSize(2);
SnowflakeDbConnectionPool.SetTimeout(10);

var conn1 = new SnowflakeDbConnection();
conn1.ConnectionString = ConnectionString;

conn1.Open();
conn1.Close();
SnowflakeDbConnectionPool.SetTimeout(0);
sfc-gh-mhofman marked this conversation as resolved.
Show resolved Hide resolved

var conn2 = new SnowflakeDbConnection();
conn2.ConnectionString = ConnectionString;
conn2.Open();
conn2.Close();

var conn3 = new SnowflakeDbConnection();
conn3.ConnectionString = ConnectionString;
conn3.Open();
conn3.Close();

// The pooling timeout should apply to all connections being pooled,
// not just the connections created after the new setting,
// so expected result should be 0
Assert.AreEqual(0, SnowflakeDbConnectionPool.GetPool(ConnectionString).GetCurrentPoolSize());
}
}
}
19 changes: 10 additions & 9 deletions Snowflake.Data.Tests/IntegrationTests/SFDbCommandIT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ namespace Snowflake.Data.Tests.IntegrationTests
using System.Collections.Generic;
using System.Globalization;
using Snowflake.Data.Tests.Mock;
using Snowflake.Data.Core;

[TestFixture]
class SFDbCommandITAsync : SFBaseTestAsync
Expand Down Expand Up @@ -102,7 +101,7 @@ public void TestExecuteAsyncWithMaxRetryReached()

using (DbConnection conn = new MockSnowflakeDbConnection(mockRestRequester))
{
string maxRetryConnStr = ConnectionString + "maxHttpRetries=5";
string maxRetryConnStr = ConnectionString + "maxHttpRetries=8";

conn.ConnectionString = maxRetryConnStr;
conn.Open();
Expand All @@ -124,10 +123,11 @@ public void TestExecuteAsyncWithMaxRetryReached()
}
stopwatch.Stop();

// retry 5 times with backoff 1, 2, 4, 8, 16 seconds
var totalDelaySeconds = 1 + 2 + 4 + 8 + 16 + 16 + 16 + 16;
// retry 8 times with backoff 1, 2, 4, 8, 16, 16, 16, 16 seconds
// but should not delay more than another 16 seconds
Assert.Less(stopwatch.ElapsedMilliseconds, 51 * 1000);
Assert.GreaterOrEqual(stopwatch.ElapsedMilliseconds, 30 * 1000);
Assert.Less(stopwatch.ElapsedMilliseconds, (totalDelaySeconds + 20) * 1000);
Assert.GreaterOrEqual(stopwatch.ElapsedMilliseconds, totalDelaySeconds * 1000);
}
}
}
Expand Down Expand Up @@ -594,7 +594,7 @@ public void TestExecuteWithMaxRetryReached()

using (IDbConnection conn = new MockSnowflakeDbConnection(mockRestRequester))
{
string maxRetryConnStr = ConnectionString + "maxHttpRetries=5";
string maxRetryConnStr = ConnectionString + "maxHttpRetries=8";

conn.ConnectionString = maxRetryConnStr;
conn.Open();
Expand All @@ -615,10 +615,11 @@ public void TestExecuteWithMaxRetryReached()
}
stopwatch.Stop();

// retry 5 times with backoff 1, 2, 4, 8, 16 seconds
var totalDelaySeconds = 1 + 2 + 4 + 8 + 16 + 16 + 16 + 16;
// retry 8 times with backoff 1, 2, 4, 8, 16, 16, 16, 16 seconds
// but should not delay more than another 16 seconds
Assert.Less(stopwatch.ElapsedMilliseconds, 51 * 1000);
Assert.GreaterOrEqual(stopwatch.ElapsedMilliseconds, 30 * 1000);
Assert.Less(stopwatch.ElapsedMilliseconds, (totalDelaySeconds + 20) * 1000);
Assert.GreaterOrEqual(stopwatch.ElapsedMilliseconds, totalDelaySeconds * 1000);
}
}

Expand Down
24 changes: 9 additions & 15 deletions Snowflake.Data.Tests/UnitTests/ConnectionPoolManagerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
*/

using System;
using System.Collections.Generic;
using System.Security;
using System.Threading;
using System.Threading.Tasks;
Expand Down Expand Up @@ -34,12 +33,18 @@ public static void BeforeAllTests()
}

[OneTimeTearDown]
public void AfterAllTests()
public static void AfterAllTests()
{
s_poolConfig.Reset();
SessionPool.SessionFactory = new SessionFactory();
}

[SetUp]
public void BeforeEach()
{
_connectionPoolManager.ClearAllPools();
}

[Test]
public void TestPoolManagerReturnsSessionPoolForGivenConnectionString()
{
Expand Down Expand Up @@ -105,7 +110,6 @@ public async Task TestGetSessionAsyncWorksForSpecifiedConnectionString()
}

[Test]
[Ignore("Enable after completion of SNOW-937189")] // TODO:
public void TestCountingOfSessionProvidedByPool()
{
// Act
Expand Down Expand Up @@ -161,7 +165,6 @@ public void TestSetTimeoutForAllPools()
}

[Test]
[Ignore("Enable when disabling pooling in connection string enabled - SNOW-902632")]
public void TestSetPoolingDisabledForAllPoolsNotPossible()
{
// Arrange
Expand Down Expand Up @@ -279,19 +282,10 @@ private void EnsurePoolSize(string connectionString, int requiredCurrentSize)
{
var sessionPool = _connectionPoolManager.GetPool(connectionString, _password);
sessionPool.SetMaxPoolSize(requiredCurrentSize);
var busySessions = new List<SFSession>();
for (var i = 0; i < requiredCurrentSize; i++)
{
var sfSession = _connectionPoolManager.GetSession(connectionString, _password);
busySessions.Add(sfSession);
_connectionPoolManager.GetSession(connectionString, _password);
}

foreach (var session in busySessions) // TODO: remove after SNOW-937189 since sessions will be already counted by GetCurrentPool size
{
session.close();
_connectionPoolManager.AddSession(session);
}

Assert.AreEqual(requiredCurrentSize, sessionPool.GetCurrentPoolSize());
}
}
Expand All @@ -304,7 +298,7 @@ public SFSession NewSession(string connectionString, SecureString password)
mockSfSession.Setup(x => x.Open()).Verifiable();
mockSfSession.Setup(x => x.OpenAsync(default)).Returns(Task.FromResult(this));
mockSfSession.Setup(x => x.IsNotOpen()).Returns(false);
mockSfSession.Setup(x => x.IsExpired(It.IsAny<long>(), It.IsAny<long>())).Returns(false);
mockSfSession.Setup(x => x.IsExpired(It.IsAny<TimeSpan>(), It.IsAny<long>())).Returns(false);
return mockSfSession.Object;
}
}
Expand Down
Loading
Loading