/// <summary> /// Creates <paramref name="parallelCount"/> write sessions simultaneously over /// <paramref name="iterations"/> number of iterations. /// </summary> private async Task CreateReleaseWriteSessions( SessionPool pool, SpannerClient client, int iterations, int parallelCount) { // We yield to increase contention among parallel tasks that are kicked off. // This increases the amount of work they are doing on another thread. await Task.Yield(); for (var i = 0; i < iterations; i++) { var readWriteOptions = new TransactionOptions { ReadWrite = new TransactionOptions.Types.ReadWrite() }; var writeSessions = await Task.WhenAll( DuplicateTaskAsync(() => CreateSessionAsync(pool, client, readWriteOptions), parallelCount)); await Task.Delay(TimeSpan.FromMilliseconds(10)); foreach (var session in writeSessions) { var transaction = await TransactionPool.BeginPooledTransactionAsync(client, session, readWriteOptions); await TransactionPool.CommitAsync(transaction, session, new Mutation[0], SpannerOptions.Instance.Timeout, CancellationToken.None); pool.ReleaseToPool(client, session); } } }
public async Task TransactionOptionsAreMatched() { using (var pool = new SessionPool()) { var client = new FakeClient(); var readWriteOptions = new TransactionOptions { ReadWrite = new TransactionOptions.Types.ReadWrite() }; // First acquire and use a session with a read/write transaction var rwSession = await CreateSessionAsync(pool, client, readWriteOptions); var transaction = await TransactionPool.BeginPooledTransactionAsync(client, rwSession, readWriteOptions); // Acquire a second session using the default transaction options var readOnlySession = await CreateSessionAsync(pool, client, s_defaultTransactionOptions); Assert.NotSame(rwSession, readOnlySession); // Finish with the read-only session pool.ReleaseToPool(client, readOnlySession); // Finish with the read/write session await TransactionPool.CommitAsync(transaction, rwSession, new Mutation[0], SpannerOptions.Instance.Timeout, CancellationToken.None); pool.ReleaseToPool(client, rwSession); // At this point, our MRU list has: // - The r/w session // - The read-only session // If we ask for another read-only session, we should skip the r/w one, and get back the read-only one. // This test needs the r/w session to be there, as if the match attempt doesn't find anything, we just return // the most recently used session. var readOnlySession2 = await CreateSessionAsync(pool, client, s_defaultTransactionOptions); Assert.Same(readOnlySession, readOnlySession2); } }
public async Task SessionPreWarmTx() { using (var pool = new SessionPool()) { var client = new FakeClient(); var txOptions = new TransactionOptions { ReadWrite = new TransactionOptions.Types.ReadWrite() }; var session1 = await CreateSessionAsync(pool, client, txOptions); var transactionAwaited = await TransactionPool.BeginPooledTransactionAsync(client, session1, txOptions); Transaction transaction; Assert.True(client.Transactions.TryPop(out transaction)); Assert.Same(transaction, transactionAwaited); await TransactionPool.CommitAsync(transaction, session1, new Mutation[0], SpannerOptions.Instance.Timeout, CancellationToken.None); // Releasing should create a new transaction as a prewarm pool.ReleaseToPool(client, session1); Transaction preWarmTx; var stopwatch = Stopwatch.StartNew(); while (!client.Transactions.TryPop(out preWarmTx)) { await Task.Yield(); //everything is simulated, so the prewarm should be immediate. Assert.True(stopwatch.Elapsed < TimeSpan.FromMilliseconds(500)); } var session2 = await CreateSessionAsync(pool, client, txOptions); var transaction2 = await TransactionPool.BeginPooledTransactionAsync(client, session2, txOptions); Assert.Same(preWarmTx, transaction2); Assert.True(client.Transactions.IsEmpty); } }