Skip to content

Commit c599d33

Browse files
committed
feat: Spanner.DATA impl and adapt integration tests to multiplex sessions
test: Fix Mutation tests to be in keeping with mux sessions test: Fix unit tests
1 parent f9d1b98 commit c599d33

29 files changed

+417
-351
lines changed

apis/Google.Cloud.Spanner.Data/Google.Cloud.Spanner.Data.CommonTesting/SpannerTestDatabaseBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ public async Task<ManagedSession> GetManagedSession()
200200
private async Task<ManagedSession> CreateMultiplexSession(ManagedSessionOptions options)
201201
{
202202
var poolManager = SessionPoolManager.Create(options);
203-
var muxSession = await poolManager.AcquireMultiplexSessionAsync(SpannerClientCreationOptions, DatabaseName, null);
203+
var muxSession = await poolManager.AcquireManagedSessionAsync(SpannerClientCreationOptions, DatabaseName, null);
204204

205205
return muxSession;
206206
}

apis/Google.Cloud.Spanner.Data/Google.Cloud.Spanner.Data.IntegrationTests/AdminTests.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,6 @@ StringValue STRING(MAX),
9595
var dropCommand = connection.CreateDdlCommand($"DROP DATABASE {dbName}");
9696
await dropCommand.ExecuteNonQueryAsync();
9797
}
98-
99-
await SessionPoolHelpers.ShutdownPoolAsync(builder.WithDatabase(dbName));
10098
}
10199

102100
[Fact]
@@ -146,8 +144,6 @@ StringValue STRING(MAX),
146144
var dropCommand = connection.CreateDdlCommand($"DROP DATABASE {dbName}");
147145
await dropCommand.ExecuteNonQueryAsync();
148146
}
149-
150-
await SessionPoolHelpers.ShutdownPoolAsync(builder.WithDatabase(dbName));
151147
}
152148

153149
[Fact]

apis/Google.Cloud.Spanner.Data/Google.Cloud.Spanner.Data.IntegrationTests/BatchDmlTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2018 Google LLC
1+
// Copyright 2018 Google LLC
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.

apis/Google.Cloud.Spanner.Data/Google.Cloud.Spanner.Data.IntegrationTests/MutationsTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ private async Task AssertEmptyMutationsFailAsync(SpannerCommand emptyMutation)
6565
// "the amount of values does not match the number of columns in the key".
6666
if (!_fixture.RunningOnEmulator) // The message is different on the emulator.
6767
{
68-
Assert.Contains("does not specify any value", exception.RpcException.Message);
68+
// This error is expected for Multiplex Sesions as they expect a mutation key during commit for mutation only transactions
69+
Assert.Contains("Failed to initialize transaction due to invalid mutation key.", exception.RpcException.Message);
6970
}
7071
}
7172

apis/Google.Cloud.Spanner.Data/Google.Cloud.Spanner.Data.IntegrationTests/ReadTests.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,6 @@ public async Task BadDbName()
7171
Assert.Equal(ErrorCode.NotFound, e.ErrorCode);
7272
Assert.False(e.IsTransientSpannerFault());
7373
}
74-
75-
// Shut the pool associated with the bad database down, to avoid seeing spurious connection failures
76-
// later in the log.
77-
await SessionPoolHelpers.ShutdownPoolAsync(connectionString);
7874
}
7975

8076
[Fact]

apis/Google.Cloud.Spanner.Data/Google.Cloud.Spanner.Data.IntegrationTests/SpannerStressTests.cs

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -150,30 +150,21 @@ private async Task RunStress(Func<SpannerConnectionStringBuilder, Task> func, in
150150
// The maximum roundtrip time for Spanner (and MySQL) is about 200ms per
151151
// write. If we initialize with the target sustained # sessions,
152152
// we shouldn't see any more sessions created.
153-
int countToPreWarm = Math.Min(TargetQps / 4, 800);
154-
var options = new SessionPoolOptions
155-
{
156-
MaximumActiveSessions = Math.Max(countToPreWarm + 50, 400),
157-
MinimumPooledSessions = countToPreWarm,
158-
MaximumConcurrentSessionCreates = Math.Min(countToPreWarm, 50)
159-
};
153+
var options = new ManagedSessionOptions();
160154

161155
var sessionPoolManager = SessionPoolManager.Create(options);
162156
var connectionStringBuilder = new SpannerConnectionStringBuilder(_fixture.ConnectionString)
163157
{
164158
SessionPoolManager = sessionPoolManager,
165159
MaximumGrpcChannels = Math.Max(4, 8 * TargetQps / 2000)
166160
};
167-
var pool = await connectionStringBuilder.AcquireSessionPoolAsync();
161+
var managedSession = await connectionStringBuilder.AcquireManagedSessionAsync();
168162
var logger = Logger.DefaultLogger;
169163
logger.ResetPerformanceData();
170164

171165
logger.Info("Prewarming session pool for stress test");
172166
// Prewarm step: allow up to 30 seconds for the session pool to be populated.
173167
var cancellationToken = new CancellationTokenSource(30000).Token;
174-
await pool.WhenPoolReady(_fixture.DatabaseName, cancellationToken);
175-
176-
logger.Info($"Prewarm complete. Pool stats: {pool.GetSegmentStatisticsSnapshot(_fixture.DatabaseName)}");
177168

178169
// Now run the test, with performance logging enabled, but without debug logging.
179170
// (Debug logging can write a lot to our log file, breaking the test.)
@@ -193,8 +184,6 @@ private async Task RunStress(Func<SpannerConnectionStringBuilder, Task> func, in
193184
}
194185
logger.Info($"Spanner latency = {latencyMs}ms");
195186

196-
await SessionPoolHelpers.ShutdownPoolAsync(connectionStringBuilder);
197-
198187
// Spanner latency with 100 qps simulated is usually around 75ms.
199188
// We allow for a latency multiplier from callers, because callers may be executing,
200189
// more than one command. In particular, with inline transactions, mutation commits

apis/Google.Cloud.Spanner.Data/Google.Cloud.Spanner.Data.IntegrationTests/TransactionTests.cs

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -86,50 +86,6 @@ private async Task IncrementByOneAsync(SpannerConnection connection, bool orphan
8686
}
8787
}
8888

89-
[Fact]
90-
public async Task Commit_ReturnsToPool()
91-
{
92-
using var connection = new SpannerConnection(_fixture.ConnectionString);
93-
await connection.OpenAsync();
94-
95-
using var transaction = await connection.BeginTransactionAsync();
96-
using var command = connection.CreateSelectCommand($"SELECT Int64Value FROM {_fixture.TableName} WHERE K=@k");
97-
command.Parameters.Add("k", SpannerDbType.String, _key);
98-
command.Transaction = transaction;
99-
100-
var value = await command.ExecuteScalarAsync();
101-
102-
transaction.Commit();
103-
104-
var poolStatistics = connection.GetSessionPoolSegmentStatistics();
105-
106-
// Because the session is eagerly returned to the pool after a commit, there shouldn't
107-
// be any active sessions even before we dispose of the transaction explicitly.
108-
Assert.Equal(0, poolStatistics.ActiveSessionCount);
109-
}
110-
111-
[Fact]
112-
public async Task Rollback_ReturnsToPool()
113-
{
114-
using var connection = new SpannerConnection(_fixture.ConnectionString);
115-
await connection.OpenAsync();
116-
117-
using var transaction = await connection.BeginTransactionAsync();
118-
using var command = connection.CreateSelectCommand($"SELECT Int64Value FROM {_fixture.TableName} WHERE K=@k");
119-
command.Parameters.Add("k", SpannerDbType.String, _key);
120-
command.Transaction = transaction;
121-
122-
var value = await command.ExecuteScalarAsync();
123-
124-
transaction.Rollback();
125-
126-
var poolStatistics = connection.GetSessionPoolSegmentStatistics();
127-
128-
// Because the session is eagerly returned to the pool after a rollback, there shouldn't
129-
// be any active sessions even before we dispose of the transaction explicitly.
130-
Assert.Equal(0, poolStatistics.ActiveSessionCount);
131-
}
132-
13389
[Fact]
13490
public async Task DetachOnDisposeTransactionIsDetached()
13591
{

apis/Google.Cloud.Spanner.Data/Google.Cloud.Spanner.Data.IntegrationTests/V1/Internal/ExecuteHelperTests.cs

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -30,37 +30,17 @@ public class ExecuteHelperTests
3030
public ExecuteHelperTests(SpannerDatabaseFixture fixture) =>
3131
_fixture = fixture;
3232

33-
[Fact]
34-
public Task SessionNotFound() => WithSessionPool(async pool =>
35-
{
36-
var session = await pool.Client.CreateSessionAsync(_fixture.DatabaseName);
37-
await pool.Client.DeleteSessionAsync(session.SessionName);
38-
39-
// The session doesn't become invalid immediately after deletion.
40-
// Wait for a minute to ensure the session is really expired.
41-
await Task.Delay(TimeSpan.FromMinutes(1));
42-
43-
var request = new ExecuteSqlRequest
44-
{
45-
Sql = $"SELECT 1",
46-
Session = session.Name
47-
};
48-
var exception = await Assert.ThrowsAsync<RpcException>(() => pool.Client.ExecuteSqlAsync(request));
49-
Assert.True(ExecuteHelper.IsSessionExpiredError(exception));
50-
});
51-
5233
// This code is separated out in case we need more tests. It's really just fluff.
53-
private async Task WithSessionPool(Func<SessionPool, Task> action)
34+
private async Task WithManagedSession(Func<ManagedSession, Task> action)
5435
{
5536
var builder = new SpannerConnectionStringBuilder(_fixture.ConnectionString);
56-
var pool = await builder.AcquireSessionPoolAsync();
37+
var managedSession = await builder.AcquireManagedSessionAsync();
5738
try
5839
{
59-
await action(pool);
40+
await action(managedSession);
6041
}
6142
finally
6243
{
63-
builder.SessionPoolManager.Release(pool);
6444
}
6545
}
6646
}

apis/Google.Cloud.Spanner.Data/Google.Cloud.Spanner.Data.IntegrationTests/V1/ReliableStreamReaderTests.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2019 Google LLC
1+
// Copyright 2019 Google LLC
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -14,6 +14,7 @@
1414

1515
using Google.Cloud.Spanner.Data;
1616
using Google.Cloud.Spanner.Data.IntegrationTests;
17+
using Google.Cloud.Spanner.V1.Internal.Logging;
1718
using Google.Protobuf.WellKnownTypes;
1819
using System.Threading.Tasks;
1920
using Xunit;
@@ -41,12 +42,14 @@ public async Task HasDataAsync(string key, int expectedValueCount)
4142
ParamTypes = { { "Key", new Type { Code = TypeCode.String } } }
4243
};
4344
var builder = new SpannerConnectionStringBuilder(_fixture.ConnectionString);
44-
var pool = await builder.AcquireSessionPoolAsync();
45+
var managedSession = await builder.AcquireManagedSessionAsync();
4546
try
4647
{
47-
using (var pooledSession = await pool.AcquireSessionAsync(_fixture.DatabaseName, null, default))
48+
using (SpannerConnection connection = new SpannerConnection(builder))
4849
{
49-
using (var reader = pooledSession.ExecuteSqlStreamReader(request, null))
50+
await connection.OpenAsync(default);
51+
ManagedTransaction managedTransaction = connection.AcquireManagedTransaction(null, out _);
52+
using (var reader = managedTransaction.ExecuteSqlStreamReader(request, null))
5053
{
5154
// While there are more values to read, HasDataAsync should return true
5255
for (int valuesRead = 0; valuesRead < expectedValueCount; valuesRead++)
@@ -69,7 +72,7 @@ public async Task HasDataAsync(string key, int expectedValueCount)
6972
}
7073
finally
7174
{
72-
builder.SessionPoolManager.Release(pool);
75+
// Nothing to clean here
7376
}
7477
}
7578
}

apis/Google.Cloud.Spanner.Data/Google.Cloud.Spanner.Data.IntegrationTests/WriteTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ public async Task BadColumnType()
334334
cmd.Parameters.Add("K", SpannerDbType.Float64, 0.1);
335335
var e = await Assert.ThrowsAsync<SpannerException>(() => cmd.ExecuteNonQueryAsyncWithRetry());
336336
Logger.DefaultLogger.Debug($"BadColumnType: Caught error code: {e.ErrorCode}");
337-
Assert.Equal(ErrorCode.FailedPrecondition, e.ErrorCode);
337+
Assert.Equal(ErrorCode.InvalidArgument, e.ErrorCode);
338338
Assert.False(e.IsTransientSpannerFault());
339339
}
340340
}

0 commit comments

Comments
 (0)