コード例 #1
0
        public async Task GetStatisticsSnapshot_MultipleDatabases()
        {
            var client  = new SessionTestingSpannerClient();
            var options = new SessionPoolOptions
            {
                MinimumPooledSessions = 10,
            };
            var sessionPool      = new SessionPool(client, options);
            var acquisitionTask1 = sessionPool.AcquireSessionAsync(s_sampleDatabaseName, new TransactionOptions(), default);
            var acquisitionTask2 = sessionPool.AcquireSessionAsync(s_sampleDatabaseName2, new TransactionOptions(), default);
            var stats            = sessionPool.GetStatisticsSnapshot();

            Assert.Equal(2, stats.PerDatabaseStatistics.Count);
            Assert.Equal(2, stats.TotalActiveSessionCount);
            Assert.Equal(0, stats.TotalReadPoolCount);
            // We've asked for 2 sessions, and the databases "know" they need 10 in the pool (each), so
            // there will be 22 in-flight requests in total.
            Assert.Equal(22, stats.TotalInFlightCreationCount);

            Assert.Contains(stats.PerDatabaseStatistics, s => s.DatabaseName == s_sampleDatabaseName);
            Assert.Contains(stats.PerDatabaseStatistics, s => s.DatabaseName == s_sampleDatabaseName2);

            // xUnit waits until tasks registered in its synchronization context have completed before considering the
            // test itself complete, so we need to let the pool complete the acquisition tasks.
            await client.Scheduler.RunAsync(TimeSpan.FromMinutes(2));
        }
コード例 #2
0
        public async Task ScheduledMaintenanceEvictsSessions_DifferentEvictionTimes()
        {
            var client  = new SessionTestingSpannerClient();
            var options = new SessionPoolOptions
            {
                // We'll never actually hit a refresh, as the eviction delay is shorter.
                IdleSessionRefreshDelay         = TimeSpan.FromMinutes(30),
                PoolEvictionDelay               = TimeSpan.FromMinutes(3),
                MaintenanceLoopDelay            = TimeSpan.FromMinutes(1),
                SessionEvictionJitter           = RetrySettings.NoJitter,
                MinimumPooledSessions           = 10,
                MaximumConcurrentSessionCreates = 20,
                WriteSessionsFraction           = 0
            };
            var sessionPool     = new SessionPool(client, options);
            var acquisitionTask = sessionPool.AcquireSessionAsync(s_sampleDatabaseName, new TransactionOptions(), default);

            await client.Scheduler.RunAsync(TimeSpan.FromMinutes(1));

            // Our session should be ready, the pool should be up to size, and we should
            // have created 11 sessions in total.
            var session = await acquisitionTask;
            var stats   = sessionPool.GetStatisticsSnapshot(s_sampleDatabaseName);

            Assert.Equal(10, stats.ReadPoolCount);
            Assert.Equal(11, client.SessionsCreated);
            Assert.Equal(0, client.SessionsDeleted);

            // Force the creation of a newer session by acquiring one.
            // The new one will be created to satisfy the minimum size of the pool
            // and will sit on top of the stack.
            // First move the pool to T=2, so that the new session will be created in T=3
            // so that its eviction time will be T=6 so as to make sure that it's not
            // being evicted when we check at T=5.
            await client.Scheduler.RunAsync(TimeSpan.FromMinutes(1));

            acquisitionTask = sessionPool.AcquireSessionAsync(s_sampleDatabaseName, new TransactionOptions(), default);
            await client.Scheduler.RunAsync(TimeSpan.FromMinutes(1));

            session = await acquisitionTask;
            stats   = sessionPool.GetStatisticsSnapshot(s_sampleDatabaseName);
            Assert.Equal(10, stats.ReadPoolCount);
            Assert.Equal(12, client.SessionsCreated);
            Assert.Equal(0, client.SessionsDeleted);

            // If we allow the maintenance pool to run until T=5 minutes, we should have evicted
            // all the old 9 sessions in the pool and replaced them with 9 new ones.
            await client.Scheduler.RunAsync(TimeSpan.FromMinutes(2));

            stats = sessionPool.GetStatisticsSnapshot(s_sampleDatabaseName);
            Assert.Equal(10, stats.ReadPoolCount);
            Assert.Equal(21, client.SessionsCreated);
            Assert.Equal(9, client.SessionsDeleted);
        }
コード例 #3
0
        public async Task ShutdownPoolAsync()
        {
            var client  = new SessionTestingSpannerClient();
            var options = new SessionPoolOptions
            {
                IdleSessionRefreshDelay         = TimeSpan.FromMinutes(30),
                PoolEvictionDelay               = TimeSpan.FromMinutes(30),
                MaintenanceLoopDelay            = TimeSpan.FromMinutes(1),
                MinimumPooledSessions           = 10,
                MaximumConcurrentSessionCreates = 20,
                WriteSessionsFraction           = 0
            };
            var sessionPool     = new SessionPool(client, options);
            var acquisitionTask = sessionPool.AcquireSessionAsync(s_sampleDatabaseName, new TransactionOptions(), default);

            // After a minute, we should have a session. Release it immediately for simplicity.
            await client.Scheduler.RunAsync(TimeSpan.FromMinutes(1));

            var session = await acquisitionTask;

            session.ReleaseToPool(false);

            // Shut the pool down, and wait a minute. (It won't take that long, as nothing's pending.)
            var shutdownTask = sessionPool.ShutdownPoolAsync(s_sampleDatabaseName, default);
            await client.Scheduler.RunAsync(TimeSpan.FromMinutes(1));

            // Now the shutdown task should have completed, and the stats will know that it's shut down.
            await shutdownTask;

            var stats = sessionPool.GetStatisticsSnapshot(s_sampleDatabaseName);

            Assert.True(stats.Shutdown);

            // We can't get sessions any more for this database
            await Assert.ThrowsAsync <InvalidOperationException>(() => sessionPool.AcquireSessionAsync(s_sampleDatabaseName, new TransactionOptions(), default));

            // But we can for a different database. (It shuts down a single database pool, not the whole session pool.)
            var acquisitionTask2 = sessionPool.AcquireSessionAsync(s_sampleDatabaseName2, new TransactionOptions(), default);
            await client.Scheduler.RunAsync(TimeSpan.FromMinutes(1));

            await acquisitionTask2;
        }
コード例 #4
0
    public async Task <long> CustomTimeoutsAndRetriesAsync(string projectId, string instanceId, string databaseId)
    {
        // Create a SessionPool.
        SpannerClient client      = SpannerClient.Create();
        SessionPool   sessionPool = new SessionPool(client, new SessionPoolOptions());

        // Acquire a session with a read-write transaction to run a query.
        DatabaseName databaseName =
            DatabaseName.FromProjectInstanceDatabase(projectId, instanceId, databaseId);
        TransactionOptions transactionOptions = new TransactionOptions
        {
            ReadWrite = new ReadWrite()
        };

        using PooledSession session = await sessionPool.AcquireSessionAsync(
                  databaseName, transactionOptions, CancellationToken.None);

        ExecuteSqlRequest request = new ExecuteSqlRequest
        {
            Sql = "INSERT Singers (SingerId, FirstName, LastName) VALUES (20, 'George', 'Washington')"
        };

        // Prepare the call settings with custom timeout and retry settings.
        CallSettings settings = CallSettings
                                .FromExpiration(Expiration.FromTimeout(TimeSpan.FromSeconds(60)))
                                .WithRetry(RetrySettings.FromExponentialBackoff(
                                               maxAttempts: 12,
                                               initialBackoff: TimeSpan.FromMilliseconds(500),
                                               maxBackoff: TimeSpan.FromMilliseconds(6400),
                                               backoffMultiplier: 1.5,
                                               retryFilter: RetrySettings.FilterForStatusCodes(
                                                   new StatusCode[] { StatusCode.Unavailable, StatusCode.DeadlineExceeded })));

        ResultSet result = await session.ExecuteSqlAsync(request, settings);

        await session.CommitAsync(new CommitRequest(), null);

        return(result.Stats.RowCountExact);
    }
コード例 #5
0
        public async Task ScheduledMaintenanceEvictsSessions()
        {
            var client  = new SessionTestingSpannerClient();
            var options = new SessionPoolOptions
            {
                // We'll never actually hit a refresh, as the eviction delay is shorter.
                IdleSessionRefreshDelay         = TimeSpan.FromMinutes(30),
                PoolEvictionDelay               = TimeSpan.FromMinutes(3),
                MaintenanceLoopDelay            = TimeSpan.FromMinutes(1),
                SessionEvictionJitter           = RetrySettings.NoJitter,
                MinimumPooledSessions           = 10,
                MaximumConcurrentSessionCreates = 20,
                WriteSessionsFraction           = 0
            };
            var sessionPool     = new SessionPool(client, options);
            var acquisitionTask = sessionPool.AcquireSessionAsync(s_sampleDatabaseName, new TransactionOptions(), default);

            await client.Scheduler.RunAsync(TimeSpan.FromMinutes(1));

            // Our session should be ready, the pool should be up to size, and we should
            // have created 11 sessions in total.
            var session = await acquisitionTask;
            var stats   = sessionPool.GetStatisticsSnapshot(s_sampleDatabaseName);

            Assert.Equal(10, stats.ReadPoolCount);
            Assert.Equal(11, client.SessionsCreated);
            Assert.Equal(0, client.SessionsDeleted);

            // If we allow the maintenance pool to run until T=5 minutes, we should have evicted
            // all the 10 sessions in the pool and replaced them.
            await client.Scheduler.RunAsync(TimeSpan.FromMinutes(4));

            stats = sessionPool.GetStatisticsSnapshot(s_sampleDatabaseName);
            Assert.Equal(10, stats.ReadPoolCount);
            Assert.Equal(21, client.SessionsCreated);
            Assert.Equal(10, client.SessionsDeleted);
        }
コード例 #6
0
        public async Task WhenPoolReady()
        {
            var client  = new SessionTestingSpannerClient();
            var options = new SessionPoolOptions
            {
                IdleSessionRefreshDelay         = TimeSpan.FromMinutes(30),
                PoolEvictionDelay               = TimeSpan.FromMinutes(30),
                MaintenanceLoopDelay            = TimeSpan.FromMinutes(1),
                MinimumPooledSessions           = 10,
                MaximumConcurrentSessionCreates = 20,
                WriteSessionsFraction           = 0
            };
            var sessionPool = new SessionPool(client, options);

            // Ask when the pool is ready, which shouldn't take a minute.
            var poolReadyTask = sessionPool.WhenPoolReady(s_sampleDatabaseName, default);
            await client.Scheduler.RunAsync(TimeSpan.FromMinutes(1));

            await poolReadyTask;

            // When the pool *is* ready, we should be able to acquire a session directly from the pool,
            // without any further delays.
            await sessionPool.AcquireSessionAsync(s_sampleDatabaseName, new TransactionOptions(), default);
        }