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-937188 changed session behavior #937

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
e727d1a
SNOW-937188 pool mode where a session gets destroyed on pooling when …
sfc-gh-mhofman Apr 26, 2024
afe21b9
SNOW-1353952 GetPool interface driven with user/password
sfc-gh-mhofman Apr 29, 2024
e84b33c
SNOW-937188 review fixes
sfc-gh-mhofman Apr 29, 2024
0429a48
Merge branch 'pool/SNOW-1353952-getpool_interface' into pool/SNOW-937…
sfc-gh-mhofman Apr 29, 2024
5e4ef69
SNOW-937188 introduction of full API for new pool
sfc-gh-mhofman Apr 29, 2024
7a9d811
SNOW-937188 changed default of ChangedSession flag, changes to public…
sfc-gh-mhofman Apr 30, 2024
a77e6e8
SNOW-937188 adoption of new pool interfaces among tests
sfc-gh-mhofman Apr 30, 2024
98dd1f9
SNOW-937188 adoption of new pool interfaces among tests
sfc-gh-mhofman Apr 30, 2024
fdc027f
SNOW-937188 review suggestions
sfc-gh-mhofman May 6, 2024
3ac0204
Merge branch 'pool/SNOW-860872-connection-pool' into pool/SNOW-937188…
sfc-gh-mhofman May 7, 2024
59013fa
make build work again
sfc-gh-knozderko May 7, 2024
a73b38d
fix review comments
sfc-gh-knozderko May 7, 2024
2849369
SNOW-937188 fixes to the unquoting and comparison of final session re…
sfc-gh-mhofman May 7, 2024
d705c21
SNOW-937188 fixes to the unquoting
sfc-gh-mhofman May 7, 2024
3cad13b
SNOW-937188 fixes to the unquoting
sfc-gh-mhofman May 7, 2024
6d6cc81
throw error when getting pool for invalid connection string
sfc-gh-knozderko May 7, 2024
6468c82
remove test for pool identification for invalid connection string
sfc-gh-knozderko May 8, 2024
459ead6
fix issues
sfc-gh-knozderko May 8, 2024
ca5efb5
SNOW-937188 fixes to returning a pool for connection string (and alte…
sfc-gh-mhofman May 8, 2024
04633e2
SNOW-938188 validation of session properties for protecting unauthori…
sfc-gh-mhofman May 9, 2024
caf1eed
SNOW-937188 fixes for KeyPairAuth params validation
sfc-gh-mhofman May 9, 2024
1963f28
SNOW-937188 fixes to Authenticator validation (moved validation from …
sfc-gh-mhofman May 9, 2024
191bacc
SNOW-937188 connection string validation fixes
sfc-gh-mhofman May 9, 2024
b8e3634
SNOW-937188 fixes to testing failures after moving validation to sess…
sfc-gh-mhofman May 9, 2024
bcce8ef
SNOW-937188 added test to cover pool retrieval not working for invali…
sfc-gh-mhofman May 9, 2024
280e00b
SNOW-937188 fixed tests with default timeouts + review fix about none…
sfc-gh-mhofman May 13, 2024
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
Expand Up @@ -50,7 +50,7 @@ public async Task TestAddToPoolOnOpenAsync()
}

[Test]
public async Task TestDoNotAddToPoolInvalidConnectionAsync()
public async Task TestFailForInvalidConnectionAsync()
{
// arrange
var invalidConnectionString = ";connection_timeout=123";
Expand All @@ -63,15 +63,10 @@ public async Task TestDoNotAddToPoolInvalidConnectionAsync()
Assert.Fail("OpenAsync should fail for invalid connection string");
}
catch {}
var thrown = Assert.Throws<SnowflakeDbException>(() => SnowflakeDbConnectionPool.GetPool(connection.ConnectionString));

// assert
var pool = SnowflakeDbConnectionPool.GetPool(connection.ConnectionString);
var poolState = pool.GetCurrentState();
logger.Warn($"Pool state: {poolState}");
Assert.Less(pool.GetCurrentPoolSize(), SFSessionHttpClientProperties.DefaultMinPoolSize); // for invalid connection string it is used default min pool size

// cleanup
await connection.CloseAsync(CancellationToken.None).ConfigureAwait(false);
Assert.That(thrown.Message, Does.Contain("Required property ACCOUNT is not provided"));
}

[Test]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public void TestBasicConnectionPool()
// assert
Assert.AreEqual(ConnectionState.Closed, conn1.State);
Assert.AreEqual(1, SnowflakeDbConnectionPool.GetPool(connectionString).GetCurrentPoolSize());
Assert.AreEqual(1, SnowflakeDbConnectionPool.GetPool(connectionString, null).GetCurrentPoolSize());
}

[Test]
Expand Down Expand Up @@ -177,7 +178,7 @@ public void TestWaitInAQueueForAnIdleSession()
{
// arrange
var connectionString = ConnectionString + "application=TestWaitForMaxSize3;waitingForIdleSessionTimeout=3s;maxPoolSize=2;minPoolSize=0";
var pool = SnowflakeDbConnectionPool.GetPool(connectionString);
var pool = SnowflakeDbConnectionPool.GetPoolInternal(connectionString);
Assert.AreEqual(0, pool.GetCurrentPoolSize(), "the pool is expected to be empty");
const long ADelay = 0;
const long BDelay = 400;
Expand Down Expand Up @@ -262,8 +263,7 @@ public void TestConnectionPoolNotPossibleToDisableForAllPools()
public void TestConnectionPoolDisable()
{
// arrange
var pool = SnowflakeDbConnectionPool.GetPool(ConnectionString);
pool.SetPooling(false);
var pool = SnowflakeDbConnectionPool.GetPool(ConnectionString + ";poolingEnabled=false");
var conn1 = new SnowflakeDbConnection();
conn1.ConnectionString = ConnectionString;

Expand Down Expand Up @@ -322,7 +322,7 @@ public void TestConnectionPoolExpirationWorks()
// arrange
const int ExpirationTimeoutInSeconds = 10;
var connectionString = ConnectionString + $"expirationTimeout={ExpirationTimeoutInSeconds};maxPoolSize=4;minPoolSize=2";
var pool = SnowflakeDbConnectionPool.GetPool(connectionString);
var pool = SnowflakeDbConnectionPool.GetPoolInternal(connectionString);
Assert.AreEqual(0, pool.GetCurrentPoolSize());

// act
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
using NUnit.Framework;
using Snowflake.Data.Client;
using Snowflake.Data.Core;
using Snowflake.Data.Core.Session;
using Snowflake.Data.Tests.Util;

namespace Snowflake.Data.Tests.IntegrationTests
{
[TestFixture]
[NonParallelizable]
public class ConnectionPoolChangedSessionIT : SFBaseTest
{
private readonly QueryExecResponseData _queryExecResponseChangedRole = new()
{
finalDatabaseName = TestEnvironment.TestConfig.database,
finalSchemaName = TestEnvironment.TestConfig.schema,
finalRoleName = "role change",
finalWarehouseName = TestEnvironment.TestConfig.warehouse
};

private readonly QueryExecResponseData _queryExecResponseChangedDatabase = new()
{
finalDatabaseName = "database changed",
finalSchemaName = TestEnvironment.TestConfig.schema,
finalRoleName = TestEnvironment.TestConfig.role,
finalWarehouseName = TestEnvironment.TestConfig.warehouse
};

private readonly QueryExecResponseData _queryExecResponseChangedSchema = new()
{
finalDatabaseName = TestEnvironment.TestConfig.database,
finalSchemaName = "schema changed",
finalRoleName = TestEnvironment.TestConfig.role,
finalWarehouseName = TestEnvironment.TestConfig.warehouse
};

private readonly QueryExecResponseData _queryExecResponseChangedWarehouse = new()
{
finalDatabaseName = TestEnvironment.TestConfig.database,
finalSchemaName = TestEnvironment.TestConfig.schema,
finalRoleName = TestEnvironment.TestConfig.role,
finalWarehouseName = "warehouse changed"
};

private static PoolConfig s_previousPoolConfigRestorer;

[OneTimeSetUp]
public static void BeforeAllTests()
{
s_previousPoolConfigRestorer = new PoolConfig();
SnowflakeDbConnectionPool.SetConnectionPoolVersion(ConnectionPoolType.MultipleConnectionPool);
}

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

[TearDown]
public new void AfterTest()
{
SnowflakeDbConnectionPool.ClearAllPools();
}

[OneTimeTearDown]
public static void AfterAllTests()
{
s_previousPoolConfigRestorer.Reset();
}

[Test]
public void TestPoolDestroysConnectionWhenChangedSessionProperties()
{
var connectionString = ConnectionString + "application=Destroy;ChangedSession=Destroy;minPoolSize=0;maxPoolSize=3";
var pool = SnowflakeDbConnectionPool.GetPool(connectionString);

var connection = new SnowflakeDbConnection(connectionString);
connection.Open();
connection.SfSession.UpdateSessionProperties(_queryExecResponseChangedDatabase);
connection.Close();

Assert.AreEqual(0, pool.GetCurrentPoolSize());
}

[Test]
public void TestPoolingWhenSessionPropertiesUnchanged()
{
var connectionString = ConnectionString + "application=NoSessionChanges;ChangedSession=Destroy;minPoolSize=0;maxPoolSize=3";
var pool = SnowflakeDbConnectionPool.GetPool(connectionString);

var connection = new SnowflakeDbConnection(connectionString);
connection.Open();
connection.Close();

Assert.AreEqual(1, pool.GetCurrentPoolSize());
}

[Test]
public void TestPoolingWhenConnectionPropertiesChangedForOriginalPoolMode()
{
var connectionString = ConnectionString + "application=OriginalPoolMode;ChangedSession=OriginalPool;minPoolSize=0;maxPoolSize=3";
var pool = SnowflakeDbConnectionPool.GetPool(connectionString);

var connection = new SnowflakeDbConnection(connectionString);
connection.Open();
connection.SfSession.UpdateSessionProperties(_queryExecResponseChangedWarehouse);
var sessionId = connection.SfSession.sessionId;
connection.Close();

Assert.AreEqual(1, pool.GetCurrentPoolSize());
connection.Close();

var connection2 = new SnowflakeDbConnection(connectionString);
connection2.Open();
Assert.AreEqual(sessionId, connection2.SfSession.sessionId);
connection2.Close();
}

[Test]
public void TestPoolingWhenConnectionPropertiesChangedForDefaultPoolMode()
{
var connectionString = ConnectionString + "application=DefaultPoolMode;minPoolSize=0;maxPoolSize=3";
var pool = SnowflakeDbConnectionPool.GetPool(connectionString);

var connection = new SnowflakeDbConnection(connectionString);
connection.Open();
connection.SfSession.UpdateSessionProperties(_queryExecResponseChangedRole);
var sessionId = connection.SfSession.sessionId;
connection.Close();

Assert.AreEqual(0, pool.GetCurrentPoolSize());

var connection2 = new SnowflakeDbConnection(connectionString);
connection2.Open();
Assert.AreNotEqual(sessionId, connection2.SfSession.sessionId);
connection2.Close();
}

[Test]
public void TestPoolDestroysAndRecreatesConnection()
{
var connectionString = ConnectionString + "application=DestroyRecreateSession;ChangedSession=Destroy;minPoolSize=1;maxPoolSize=3";

var connection = new SnowflakeDbConnection(connectionString);
connection.Open();
var sessionId = connection.SfSession.sessionId;
connection.SfSession.UpdateSessionProperties(_queryExecResponseChangedSchema);
connection.Close();

var pool = SnowflakeDbConnectionPool.GetPool(connectionString);
Assert.AreEqual(1, pool.GetCurrentPoolSize());

var connection2 = new SnowflakeDbConnection(connectionString);
connection2.Open();
Assert.AreNotEqual(sessionId, connection2.SfSession.sessionId);
connection2.Close();
}

[Test]
public void TestCompareSessionChangesCaseInsensitiveWhenUnquoted()
{
var connectionString = ConnectionString + "application=CompareCaseInsensitive;ChangedSession=Destroy;minPoolSize=1;maxPoolSize=3";

var responseData = new QueryExecResponseData()
{
finalDatabaseName = TestEnvironment.TestConfig.database.ToLower(),
finalSchemaName = TestEnvironment.TestConfig.schema.ToUpper(),
finalRoleName = $"{char.ToUpper(TestEnvironment.TestConfig.role[0])}{TestEnvironment.TestConfig.role.Substring(1).ToLower()}",
finalWarehouseName = TestEnvironment.TestConfig.warehouse.ToLower()
};

var connection = new SnowflakeDbConnection(connectionString);
connection.Open();
var sessionId = connection.SfSession.sessionId;
connection.SfSession.UpdateSessionProperties(responseData);
connection.Close();

var pool = SnowflakeDbConnectionPool.GetPool(connectionString);
Assert.AreEqual(1, pool.GetCurrentPoolSize());

var connection2 = new SnowflakeDbConnection(connectionString);
connection2.Open();
Assert.AreEqual(sessionId, connection2.SfSession.sessionId);
connection2.Close();
}

[Test]
public void TestCompareSessionChangesCaseSensitiveWhenQuoted()
{
var connectionString = ConnectionString + "application=CompareCaseSensitive;ChangedSession=Destroy;minPoolSize=1;maxPoolSize=3";

var responseData = new QueryExecResponseData()
{
finalDatabaseName = TestEnvironment.TestConfig.database,
finalSchemaName = TestEnvironment.TestConfig.schema,
finalRoleName = $"\\\"SomeQuotedValue\\\"",
finalWarehouseName = TestEnvironment.TestConfig.warehouse.ToLower()
};

var connection = new SnowflakeDbConnection(connectionString);
connection.Open();
var sessionId = connection.SfSession.sessionId;
connection.SfSession.UpdateSessionProperties(responseData);
connection.Close();

var pool = SnowflakeDbConnectionPool.GetPool(connectionString);
Assert.AreEqual(1, pool.GetCurrentPoolSize());

var connection2 = new SnowflakeDbConnection(connectionString);
connection2.Open();
Assert.AreNotEqual(sessionId, connection2.SfSession.sessionId);
connection2.Close();
}
}
}
11 changes: 9 additions & 2 deletions Snowflake.Data.Tests/IntegrationTests/ConnectionPoolCommonIT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,17 @@ 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());
if (_connectionPoolTypeUnderTest == ConnectionPoolType.SingleConnectionCache)
{
Assert.AreEqual(0, SnowflakeDbConnectionPool.GetPool(conn1.ConnectionString).GetCurrentPoolSize());
}
else
{
var thrown = Assert.Throws<SnowflakeDbException>(() => SnowflakeDbConnectionPool.GetPool(conn1.ConnectionString));
Assert.That(thrown.Message, Does.Contain("Connection string is invalid"));
}
}

[Test]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ public void TestConnectionPoolDisable()
{
// arrange
var pool = SnowflakeDbConnectionPool.GetPool(ConnectionString);
pool.SetPooling(false);
SnowflakeDbConnectionPool.SetPooling(false);
var conn1 = new SnowflakeDbConnection();
conn1.ConnectionString = ConnectionString;

Expand Down
Loading
Loading