public async Task MaxPoolSizeNotViolated()
        {
            using (var pool = new SessionPool())
            {
                pool.Options.MaximumPooledSessions = 2;

                var client   = CreateMockClient();
                var sessions = await Task.WhenAll(
                    pool.CreateSessionFromPoolAsync(
                        client.Object, s_defaultName.ProjectId,
                        s_defaultName.InstanceId, s_defaultName.DatabaseId, null, CancellationToken.None),
                    pool.CreateSessionFromPoolAsync(
                        client.Object, s_defaultName.ProjectId,
                        s_defaultName.InstanceId, s_defaultName.DatabaseId, null, CancellationToken.None),
                    pool.CreateSessionFromPoolAsync(
                        client.Object, s_defaultName.ProjectId,
                        s_defaultName.InstanceId, s_defaultName.DatabaseId, null, CancellationToken.None))
                               .ConfigureAwait(false);

                pool.ReleaseToPool(client.Object, sessions[0]);
                pool.ReleaseToPool(client.Object, sessions[1]);
                pool.ReleaseToPool(client.Object, sessions[2]);

                Assert.Equal(
                    2, pool.GetPoolSize(
                        client.Object, s_defaultName.ProjectId,
                        s_defaultName.InstanceId, s_defaultName.DatabaseId));
            }
        }
Example #2
0
        /// <summary>
        /// Creates <paramref name="parallelCount"/> read sessions simultaneously over
        /// <paramref name="iterations"/> number of iterations.
        /// </summary>
        private async Task CreateReleaseReadSessions(
            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 readOptions = new TransactionOptions {
                    ReadOnly = new TransactionOptions.Types.ReadOnly()
                };
                var readSessions = await Task.WhenAll(
                    DuplicateTaskAsync(() => CreateSessionAsync(pool, client, readOptions), parallelCount));

                await Task.Delay(TimeSpan.FromMilliseconds(10));

                foreach (var session in readSessions)
                {
                    pool.ReleaseToPool(client, session);
                }
            }
        }
Example #3
0
        /// <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);
                }
            }
        }
Example #4
0
        public async Task MaxActiveViolation_WaitOnResourcesExhausted_Blocks()
        {
            using (var pool = new SessionPool())
            {
                pool.Options.WaitOnResourcesExhausted = true;
                pool.Options.MaximumActiveSessions    = 2;

                var client   = new FakeClient();
                var session1 = await CreateSessionAsync(pool, client);

                var session2 = await CreateSessionAsync(pool, client);

                var createTask = CreateSessionAsync(pool, client);

                await Task.WhenAll(createTask, ReleaseAfterDelay(session1));

                Assert.Same(session1, await createTask);

                async Task ReleaseAfterDelay(Session session)
                {
                    await Task.Delay(TimeSpan.FromMilliseconds(10));

                    pool.ReleaseToPool(client, session);
                }
            }
        }
        public async Task MaxActiveViolationBlocks()
        {
            using (var pool = new SessionPool())
            {
                pool.Options.WaitOnResourcesExhausted = true;
                pool.Options.MaximumActiveSessions    = 2;

                var client   = CreateMockClient();
                var session1 = await pool.CreateSessionFromPoolAsync(
                    client.Object, s_defaultName.ProjectId,
                    s_defaultName.InstanceId, s_defaultName.DatabaseId, null, CancellationToken.None)
                               .ConfigureAwait(false);

                await pool.CreateSessionFromPoolAsync(
                    client.Object, s_defaultName.ProjectId,
                    s_defaultName.InstanceId, s_defaultName.DatabaseId, null, CancellationToken.None)
                .ConfigureAwait(false);

                async Task ReleaseTask()
                {
                    await Task.Delay(TimeSpan.FromMilliseconds(10));

                    pool.ReleaseToPool(client.Object, session1);
                }

                var createTask = pool.CreateSessionFromPoolAsync(
                    client.Object, s_defaultName.ProjectId,
                    s_defaultName.InstanceId, s_defaultName.DatabaseId, null, CancellationToken.None);

                await Task.WhenAll(createTask, ReleaseTask()).ConfigureAwait(false);

                Assert.Same(session1, createTask.ResultWithUnwrappedExceptions());
            }
        }
        public async Task ClientsHaveDifferentPools()
        {
            using (var pool = new SessionPool())
            {
                var client1 = CreateMockClient();
                var client2 = CreateMockClient();

                var session = await pool.CreateSessionFromPoolAsync(
                    client1.Object, s_defaultName.ProjectId,
                    s_defaultName.InstanceId, s_defaultName.DatabaseId, null, CancellationToken.None)
                              .ConfigureAwait(false);

                pool.ReleaseToPool(client1.Object, session);

                var session2 = await pool.CreateSessionFromPoolAsync(
                    client2.Object, s_defaultName.ProjectId,
                    s_defaultName.InstanceId, s_defaultName.DatabaseId, null, CancellationToken.None)
                               .ConfigureAwait(false);

                Assert.NotSame(session, session2);
                Assert.Equal(2, _createdSessions.Count);
                Assert.Equal(1, _createdSessions[client1].Count);
                Assert.Equal(1, _createdSessions[client2].Count);
            }
        }
        /// <summary>
        /// Creates <paramref name="parallelCount"/> read sessions simultaneously over
        /// <paramref name="iterations"/> number of iterations.
        /// </summary>
        private async Task CreateReleaseReadSessions(
            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 readOptions = new TransactionOptions {
                    ReadOnly = new TransactionOptions.Types.ReadOnly()
                };
                var readSessions = await Task.WhenAll(
                    DuplicateTaskAsync(
                        () =>
                        pool.CreateSessionFromPoolAsync(
                            client, s_defaultName.ProjectId,
                            s_defaultName.InstanceId, s_defaultName.DatabaseId, readOptions,
                            CancellationToken.None),
                        parallelCount))
                                   .ConfigureAwait(false);

                await Task.Delay(TimeSpan.FromMilliseconds(10)).ConfigureAwait(false);

                foreach (var session in readSessions)
                {
                    pool.ReleaseToPool(client, session);
                }
            }
        }
Example #8
0
        public async Task MaxPoolSizeNotViolated()
        {
            using (var pool = new SessionPool())
            {
                pool.Options.MaximumPooledSessions = 2;

                var client   = new FakeClient();
                var sessions = await Task.WhenAll(
                    CreateSessionAsync(pool, client),
                    CreateSessionAsync(pool, client),
                    CreateSessionAsync(pool, client));

                pool.ReleaseToPool(client, sessions[0]);
                pool.ReleaseToPool(client, sessions[1]);
                pool.ReleaseToPool(client, sessions[2]);

                var actualSize = pool.GetPoolSize(client, s_defaultName.ProjectId, s_defaultName.InstanceId, s_defaultName.DatabaseId);
                Assert.Equal(2, actualSize);
            }
        }
Example #9
0
        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);
            }
        }
Example #10
0
        public async Task SynchronousRelease()
        {
            using (var pool = new SessionPool())
            {
                var client = new FakeClient();

                var session1 = await CreateSessionAsync(pool, client);

                pool.ReleaseToPool(client, session1);
                var session2 = await CreateSessionAsync(pool, client);

                Assert.Same(session1, session2);
            }
        }
Example #11
0
        public async Task ExpiredSessionsNotPooled()
        {
            using (var pool = new SessionPool())
            {
                var client  = new FakeClient();
                var session = await CreateSessionAsync(pool, client);

                SessionPool.MarkSessionExpired(session);
                pool.ReleaseToPool(client, session);
                var session2 = await CreateSessionAsync(pool, client);

                Assert.NotSame(session, session2);
                Assert.Equal(2, client.Sessions.Count);
            }
        }
Example #12
0
        public async Task DatabasesHaveDifferentPools()
        {
            using (var pool = new SessionPool())
            {
                var client = new FakeClient();

                var session1 = await CreateSessionAsync(pool, client);

                pool.ReleaseToPool(client, session1);

                var session2 = await pool.CreateSessionFromPoolAsync(
                    client, "newproject", "newinstance", "newdbid", s_defaultTransactionOptions, CancellationToken.None);

                Assert.NotSame(session1, session2);
                Assert.Equal(2, client.Sessions.Count);
            }
        }
        public async Task SessionPreWarmTx()
        {
            using (var pool = new SessionPool())
            {
                var client = CreateMockClient();

                var txOptions = new TransactionOptions {
                    ReadWrite = new TransactionOptions.Types.ReadWrite()
                };
                var session1 = await pool.CreateSessionFromPoolAsync(
                    client.Object, s_defaultName.ProjectId,
                    s_defaultName.InstanceId, s_defaultName.DatabaseId, txOptions, CancellationToken.None)
                               .ConfigureAwait(false);

                var transactionAwaited = await client.Object.BeginPooledTransactionAsync(session1, txOptions)
                                         .ConfigureAwait(false);

                Transaction transaction;
                Assert.True(_transactions.TryPop(out transaction));
                Assert.Same(transaction, transactionAwaited);
                await transaction.CommitAsync(session1, null, SpannerOptions.Instance.Timeout).ConfigureAwait(false);

                //Releasing should start the tx prewarm
                pool.ReleaseToPool(client.Object, session1);
                Transaction preWarmTx;
                var         stopwatch = Stopwatch.StartNew();
                while (!_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 pool.CreateSessionFromPoolAsync(
                    client.Object, s_defaultName.ProjectId,
                    s_defaultName.InstanceId, s_defaultName.DatabaseId, txOptions, CancellationToken.None)
                               .ConfigureAwait(false);

                var transaction2 = await client.Object.BeginPooledTransactionAsync(session2, txOptions)
                                   .ConfigureAwait(false);

                Assert.Same(preWarmTx, transaction2);
                Assert.True(_transactions.IsEmpty);
            }
        }
Example #14
0
        public async Task ClientsHaveDifferentPools()
        {
            using (var pool = new SessionPool())
            {
                var client1 = new FakeClient();
                var client2 = new FakeClient();

                var session1 = await CreateSessionAsync(pool, client1);

                pool.ReleaseToPool(client1, session1);

                var session2 = await CreateSessionAsync(pool, client2);

                Assert.NotSame(session1, session2);
                Assert.Equal(1, client1.Sessions.Count);
                Assert.Equal(1, client2.Sessions.Count);
            }
        }
        public async Task SynchronousRelease()
        {
            using (var pool = new SessionPool())
            {
                var client  = CreateMockClient();
                var session = await pool.CreateSessionFromPoolAsync(
                    client.Object, s_defaultName.ProjectId,
                    s_defaultName.InstanceId, s_defaultName.DatabaseId, null, CancellationToken.None)
                              .ConfigureAwait(false);

                pool.ReleaseToPool(client.Object, session);
                var session2 = await pool.CreateSessionFromPoolAsync(
                    client.Object, s_defaultName.ProjectId,
                    s_defaultName.InstanceId, s_defaultName.DatabaseId, null, CancellationToken.None)
                               .ConfigureAwait(false);

                Assert.Same(session, session2);
            }
        }
Example #16
0
        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);
            }
        }