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));
            }
        }
        public async Task MaxActiveViolationThrows()
        {
            using (var pool = new SessionPool())
            {
                pool.Options.WaitOnResourcesExhausted = false;
                pool.Options.MaximumActiveSessions    = 2;
                var exceptionThrown = false;

                var client = CreateMockClient();
                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);

                try
                {
                    await pool.CreateSessionFromPoolAsync(
                        client.Object, s_defaultName.ProjectId,
                        s_defaultName.InstanceId, s_defaultName.DatabaseId, null, CancellationToken.None)
                    .ConfigureAwait(false);
                }
                catch (RpcException e)
                {
                    Assert.Equal(StatusCode.ResourceExhausted, e.Status.StatusCode);
                    exceptionThrown = true;
                }

                Assert.True(exceptionThrown);
            }
        }
        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);
                }
            }
        }
        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);
            }
        }
        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);
            }
        }
예제 #8
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 EmptyPoolCreatesNewSession()
        {
            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);

                Assert.Equal(1, _createdSessions.Count);
                Assert.Equal(1, _createdSessions[client].Count);
                Assert.Same(session, _createdSessions[client][0]);
                client.Verify(
                    x => x.CreateSessionAsync(
                        It.Is <DatabaseName>(y => y.Equals(s_defaultName)),
                        It.IsAny <CancellationToken>()), Times.Once);
            }
        }
        public async Task SessionCreateIsThrottled()
        {
            using (var pool = new SessionPool())
            {
                pool.Options.MaximumConcurrentSessionCreates = 2;

                //we use a specially designed mock that records simultaneous create calls.
                //Moq actually does internal synchronization that disallows parallel calls.
                var mockClient = new ParallelSpannerClient();

                var sessionList = Enumerable.Range(0, 100).Select(
                    x => pool.CreateSessionFromPoolAsync(
                        mockClient, s_defaultName.ProjectId,
                        s_defaultName.InstanceId, s_defaultName.DatabaseId, null, CancellationToken.None)).ToList();

                await Task.WhenAll(sessionList).ConfigureAwait(false);

                Assert.True(mockClient.MaxConcurrentRequests <= pool.Options.MaximumConcurrentSessionCreates);
            }
        }
예제 #11
0
 /// <summary>
 /// Helper to create a session with default project/instance/database arguments.
 /// (Most tests use these.)
 /// </summary>
 private static Task <Session> CreateSessionAsync(SessionPool pool, SpannerClient client, TransactionOptions options = null) =>
 pool.CreateSessionFromPoolAsync(
     client, s_defaultName.ProjectId, s_defaultName.InstanceId, s_defaultName.DatabaseId,
     options ?? s_defaultTransactionOptions, CancellationToken.None);