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

Pool/snow-902610 min pool size #880

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System.Threading;
using System.Threading.Tasks;
using NUnit.Framework;
using Snowflake.Data.Client;
using Snowflake.Data.Core.Session;
using Snowflake.Data.Tests.Util;

namespace Snowflake.Data.Tests.IntegrationTests
{
[TestFixture]
[NonParallelizable]
public class ConnectionMultiplePoolsAsyncIT: SFBaseTestAsync
{
private readonly PoolConfig _previousPoolConfig = new PoolConfig();

[SetUp]
public new void BeforeTest()
{
SnowflakeDbConnectionPool.SetConnectionPoolVersion(ConnectionPoolType.MultipleConnectionPool);
SnowflakeDbConnectionPool.ClearAllPools();
}

[TearDown]
public new void AfterTest()
{
_previousPoolConfig.Reset();
}

[Test]
public async Task TestMinPoolSizeAsync()
{
// arrange
var connection = new SnowflakeDbConnection();
connection.ConnectionString = ConnectionString + "application=TestMinPoolSizeAsync;minPoolSize=3";

// act
await connection.OpenAsync().ConfigureAwait(false);
Thread.Sleep(3000);

// assert
var pool = SnowflakeDbConnectionPool.GetPool(connection.ConnectionString);
Assert.AreEqual(3, pool.GetCurrentPoolSize());

// cleanup
await connection.CloseAsync(CancellationToken.None).ConfigureAwait(false);
}
}
}
57 changes: 39 additions & 18 deletions Snowflake.Data.Tests/IntegrationTests/ConnectionMultiplePoolsIT.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Data;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using NUnit.Framework;
using Snowflake.Data.Client;
Expand Down Expand Up @@ -51,37 +52,38 @@ public void TestBasicConnectionPool()
[Test]
public void TestReuseSessionInConnectionPool() // old name: TestConnectionPool
{
var conn1 = new SnowflakeDbConnection(ConnectionString);
var connectionString = ConnectionString + "minPoolSize=1";
var conn1 = new SnowflakeDbConnection(connectionString);
conn1.Open();
Assert.AreEqual(ConnectionState.Open, conn1.State);
conn1.Close();
Assert.AreEqual(1, SnowflakeDbConnectionPool.GetPool(ConnectionString).GetCurrentPoolSize());
Assert.AreEqual(1, SnowflakeDbConnectionPool.GetPool(connectionString).GetCurrentPoolSize());

var conn2 = new SnowflakeDbConnection();
conn2.ConnectionString = ConnectionString;
conn2.ConnectionString = connectionString;
conn2.Open();
Assert.AreEqual(ConnectionState.Open, conn2.State);
Assert.AreEqual(1, SnowflakeDbConnectionPool.GetPool(ConnectionString).GetCurrentPoolSize());
Assert.AreEqual(1, SnowflakeDbConnectionPool.GetPool(connectionString).GetCurrentPoolSize());

conn2.Close();
Assert.AreEqual(1, SnowflakeDbConnectionPool.GetPool(ConnectionString).GetCurrentPoolSize());
Assert.AreEqual(1, SnowflakeDbConnectionPool.GetPool(connectionString).GetCurrentPoolSize());
Assert.AreEqual(ConnectionState.Closed, conn1.State);
Assert.AreEqual(ConnectionState.Closed, conn2.State);
}

[Test]
public void TestReuseSessionInConnectionPoolReachingMaxConnections() // old name: TestConnectionPoolFull
{
var pool = SnowflakeDbConnectionPool.GetPool(ConnectionString);
pool.SetMaxPoolSize(2);
var connectionString = ConnectionString + "maxPoolSize=2;minPoolSize=1";
var pool = SnowflakeDbConnectionPool.GetPool(connectionString);

var conn1 = new SnowflakeDbConnection();
conn1.ConnectionString = ConnectionString;
conn1.ConnectionString = connectionString;
conn1.Open();
Assert.AreEqual(ConnectionState.Open, conn1.State);

var conn2 = new SnowflakeDbConnection();
conn2.ConnectionString = ConnectionString;
conn2.ConnectionString = connectionString;
conn2.Open();
Assert.AreEqual(ConnectionState.Open, conn2.State);

Expand All @@ -91,12 +93,12 @@ public void TestReuseSessionInConnectionPoolReachingMaxConnections() // old name
Assert.AreEqual(2, pool.GetCurrentPoolSize());

var conn3 = new SnowflakeDbConnection();
conn3.ConnectionString = ConnectionString;
conn3.ConnectionString = connectionString;
conn3.Open();
Assert.AreEqual(ConnectionState.Open, conn3.State);

var conn4 = new SnowflakeDbConnection();
conn4.ConnectionString = ConnectionString;
conn4.ConnectionString = connectionString;
conn4.Open();
Assert.AreEqual(ConnectionState.Open, conn4.State);

Expand All @@ -115,7 +117,7 @@ public void TestReuseSessionInConnectionPoolReachingMaxConnections() // old name
public void TestWaitForTheIdleConnectionWhenExceedingMaxConnectionsLimit()
{
// arrange
var connectionString = ConnectionString + "application=TestWaitForMaxSize1;waitingForIdleSessionTimeout=1s;maxPoolSize=2";
var connectionString = ConnectionString + "application=TestWaitForMaxSize1;waitingForIdleSessionTimeout=1s;maxPoolSize=2;minPoolSize=1";
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");
var conn1 = OpenedConnection(connectionString);
Expand All @@ -141,7 +143,7 @@ public void TestWaitForTheIdleConnectionWhenExceedingMaxConnectionsLimit()
public void TestWaitForTheIdleConnectionWhenExceedingMaxConnectionsLimitAsync()
{
// arrange
var connectionString = ConnectionString + "application=TestWaitForMaxSize2;waitingForIdleSessionTimeout=1s;maxPoolSize=2";
var connectionString = ConnectionString + "application=TestWaitForMaxSize2;waitingForIdleSessionTimeout=1s;maxPoolSize=2;minPoolSize=1";
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");
var conn1 = OpenedConnection(connectionString);
Expand Down Expand Up @@ -224,10 +226,10 @@ public void TestWaitInAQueueForAnIdleSession()
public void TestBusyAndIdleConnectionsCountedInPoolSize()
{
// arrange
var pool = SnowflakeDbConnectionPool.GetPool(ConnectionString);
pool.SetMaxPoolSize(2);
var connectionString = ConnectionString + "maxPoolSize=2;minPoolSize=1";
sfc-gh-mhofman marked this conversation as resolved.
Show resolved Hide resolved
var pool = SnowflakeDbConnectionPool.GetPool(connectionString);
var connection = new SnowflakeDbConnection();
connection.ConnectionString = ConnectionString;
connection.ConnectionString = connectionString;

// act
connection.Open();
Expand Down Expand Up @@ -279,7 +281,7 @@ public void TestConnectionPoolDisable()
[Test]
public void TestNewConnectionPoolClean()
{
var connectionString = ConnectionString + "maxPoolSize=2;";
var connectionString = ConnectionString + "maxPoolSize=2;minPoolSize=1;";
sfc-gh-mhofman marked this conversation as resolved.
Show resolved Hide resolved
var conn1 = new SnowflakeDbConnection();
conn1.ConnectionString = connectionString;
conn1.Open();
Expand Down Expand Up @@ -313,7 +315,7 @@ public void TestNewConnectionPoolClean()
[Test]
public void TestConnectionPoolExpirationWorks()
{
var connectionString = ConnectionString + "expirationTimeout=0;maxPoolSize=2";
var connectionString = ConnectionString + "expirationTimeout=0;maxPoolSize=2;minPoolSize=1";
sfc-gh-mhofman marked this conversation as resolved.
Show resolved Hide resolved
var conn1 = new SnowflakeDbConnection();
conn1.ConnectionString = connectionString;
conn1.Open();
Expand All @@ -333,6 +335,25 @@ public void TestConnectionPoolExpirationWorks()
Assert.AreEqual(0, SnowflakeDbConnectionPool.GetPool(connectionString).GetCurrentPoolSize());
}

[Test]
public void TestMinPoolSize()
{
// arrange
var connection = new SnowflakeDbConnection();
connection.ConnectionString = ConnectionString + "application=TestMinPoolSize;minPoolSize=3";

// act
connection.Open();
Thread.Sleep(3000);

// assert
var pool = SnowflakeDbConnectionPool.GetPool(connection.ConnectionString);
Assert.AreEqual(3, pool.GetCurrentPoolSize());

// cleanup
connection.Close();
}

private SnowflakeDbConnection OpenedConnection(string connectionString)
{
var connection = new SnowflakeDbConnection();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ public void TestConnectionPoolWithDispose()
conn1.ConnectionString = "bad connection string";
Assert.Throws<SnowflakeDbException>(() => conn1.Open());
conn1.Close();
Thread.Sleep(3000); // minPoolSize = 2 causes that another thread has been started. We sleep to make that thread finish.

Assert.AreEqual(ConnectionState.Closed, conn1.State);
Assert.AreEqual(0, SnowflakeDbConnectionPool.GetPool(conn1.ConnectionString).GetCurrentPoolSize());
Expand Down
4 changes: 2 additions & 2 deletions Snowflake.Data.Tests/UnitTests/ConnectionPoolManagerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ namespace Snowflake.Data.Tests.UnitTests
class ConnectionPoolManagerTest
{
private readonly ConnectionPoolManager _connectionPoolManager = new ConnectionPoolManager();
private const string ConnectionString1 = "database=D1;warehouse=W1;account=A1;user=U1;password=P1;role=R1;";
private const string ConnectionString2 = "database=D2;warehouse=W2;account=A2;user=U2;password=P2;role=R2;";
private const string ConnectionString1 = "database=D1;warehouse=W1;account=A1;user=U1;password=P1;role=R1;minPoolSize=1;";
sfc-gh-mhofman marked this conversation as resolved.
Show resolved Hide resolved
private const string ConnectionString2 = "database=D2;warehouse=W2;account=A2;user=U2;password=P2;role=R2;minPoolSize=1;";
private readonly SecureString _password = new SecureString();
private static PoolConfig s_poolConfig;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System;
using System.Linq;
using NUnit.Framework;
using Snowflake.Data.Core;
using Snowflake.Data.Core.Session;

namespace Snowflake.Data.Tests.UnitTests.Session
{
[TestFixture]
public class SessionOrCreationTokensTest
{
private SFSession _session = new SFSession("account=test;user=test;password=test", null);

[Test]
public void TestNoBackgroundSessionsToCreateWhenInitialisedWithSession()
{
// arrange
var sessionOrTokens = new SessionOrCreationTokens(_session);

// act
var backgroundCreationTokens = sessionOrTokens.BackgroundSessionCreationTokens();

Assert.AreEqual(0, backgroundCreationTokens.Count);
}

[Test]
public void TestReturnFirstCreationToken()
{
// arrange
var sessionCreationTokenCounter = new SessionCreationTokenCounter(TimeSpan.FromSeconds(10));
var tokens = Enumerable.Range(1, 3)
.Select(_ => sessionCreationTokenCounter.NewToken())
.ToList();
var sessionOrTokens = new SessionOrCreationTokens(tokens);

// act
var token = sessionOrTokens.SessionCreationToken();

// assert
Assert.AreSame(tokens[0], token);
}

[Test]
public void TestReturnCreationTokensFromTheSecondOneForBackgroundExecution()
{
// arrange
var sessionCreationTokenCounter = new SessionCreationTokenCounter(TimeSpan.FromSeconds(10));
var tokens = Enumerable.Range(1, 3)
.Select(_ => sessionCreationTokenCounter.NewToken())
.ToList();
var sessionOrTokens = new SessionOrCreationTokens(tokens);

// act
var backgroundTokens = sessionOrTokens.BackgroundSessionCreationTokens();

// assert
Assert.AreEqual(2, backgroundTokens.Count);
Assert.AreSame(tokens[1], backgroundTokens[0]);
Assert.AreSame(tokens[2], backgroundTokens[1]);
}
}
}
sfc-gh-knozderko marked this conversation as resolved.
Show resolved Hide resolved
22 changes: 0 additions & 22 deletions Snowflake.Data/Core/Session/SessionOrCreationToken.cs

This file was deleted.

41 changes: 41 additions & 0 deletions Snowflake.Data/Core/Session/SessionOrCreationTokens.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace Snowflake.Data.Core.Session
{
internal class SessionOrCreationTokens
{
private static readonly List<SessionCreationToken> s_emptySessionCreationTokenList = new List<SessionCreationToken>();
sfc-gh-mhofman marked this conversation as resolved.
Show resolved Hide resolved

public SFSession Session { get; }
public List<SessionCreationToken> SessionCreationTokens { get; }

public SessionOrCreationTokens(SFSession session)
{
Session = session ?? throw new Exception("Internal error: missing session");
SessionCreationTokens = s_emptySessionCreationTokenList;
sfc-gh-pbulawa marked this conversation as resolved.
Show resolved Hide resolved
}

public SessionOrCreationTokens(List<SessionCreationToken> sessionCreationTokens)
{
Session = null;
if (sessionCreationTokens == null || sessionCreationTokens.Count == 0)
{
throw new Exception("Internal error: missing session creation token");

Check warning on line 25 in Snowflake.Data/Core/Session/SessionOrCreationTokens.cs

View check run for this annotation

Codecov / codecov/patch

Snowflake.Data/Core/Session/SessionOrCreationTokens.cs#L24-L25

Added lines #L24 - L25 were not covered by tests
}
SessionCreationTokens = sessionCreationTokens;
}

public List<SessionCreationToken> BackgroundSessionCreationTokens()
{
if (Session == null)
{
return SessionCreationTokens.Skip(1).ToList();
}
return SessionCreationTokens;
}

public SessionCreationToken SessionCreationToken() => SessionCreationTokens.First();
}
}
Loading
Loading