Example #1
0
        public void Stop_should_trigger_immidiate_maintenace_call(
            [Values(false, true)] bool checkOutConnection,
            [Values(false, true)] bool closeInUseConnection)
        {
            var eventCapturer = new EventCapturer()
                                .Capture <ConnectionPoolAddedConnectionEvent>()
                                .Capture <ConnectionPoolRemovedConnectionEvent>();

            int connectionId = 0;

            using (var pool = CreatePool(
                       eventCapturer,
                       minPoolSize: 1,
                       connectionFactoryConfigurator: (factory) =>
            {
                factory
                .Setup(f => f.CreateConnection(__serverId, __endPoint))
                .Returns(() => new MockConnection(new ConnectionId(__serverId, ++connectionId), new ConnectionSettings(), eventCapturer));
            }))     // use to ensure that Maintenance attempt has been called
            {
                var subject = pool._maintenanceHelper();

                var maitenanceInPlayTimeout = TimeSpan.FromMilliseconds(50);
                eventCapturer.WaitForEventOrThrowIfTimeout <ConnectionPoolAddedConnectionEvent>(maitenanceInPlayTimeout);
                eventCapturer.Next().Should().BeOfType <ConnectionPoolAddedConnectionEvent>().Which.ConnectionId.LocalValue.Should().Be(1);  // minPoolSize has been enrolled
                eventCapturer.Any().Should().BeFalse();

                SpinWait.SpinUntil(() => pool.ConnectionHolder._connections().Count > 0, TimeSpan.FromSeconds(1)).Should().BeTrue(); // wait until connection 1 has been returned to the pool after minPoolSize logic

                IConnection acquiredConnection = null;
                if (checkOutConnection)
                {
                    acquiredConnection = pool.AcquireConnection(CancellationToken.None);
                    acquiredConnection.ConnectionId.LocalValue.Should().Be(1);
                }

                IncrementGeneration(pool);
                subject.Stop(maxGenerationToReap: closeInUseConnection ? pool.Generation : null);

                var requestInPlayTimeout = TimeSpan.FromMilliseconds(100);
                if (!closeInUseConnection && checkOutConnection)
                {
                    // connection in progress should be not touched
                    Thread.Sleep(requestInPlayTimeout);
                }
                else
                {
                    eventCapturer.WaitForOrThrowIfTimeout((events) => events.OfType <ConnectionPoolRemovedConnectionEvent>().Count() >= 1, requestInPlayTimeout);
                    eventCapturer.Next().Should().BeOfType <ConnectionPoolRemovedConnectionEvent>();
                }
                eventCapturer.Any().Should().BeFalse();

                pool.AvailableCount.Should().Be(checkOutConnection ? pool.Settings.MaxConnections - 1 : pool.Settings.MaxConnections);
                pool.CreatedCount.Should().Be(checkOutConnection ? 1 : 0);
                pool.DormantCount.Should().Be(0);
                pool.PendingCount.Should().Be(0);
                pool.UsedCount.Should().Be(checkOutConnection ? 1 : 0);
            }
        }
        public void Dispose_should_raise_the_correct_events()
        {
            _subject.Dispose();

            _capturedEvents.Next().Should().BeOfType <ConnectionClosingEvent>();
            _capturedEvents.Next().Should().BeOfType <ConnectionClosedEvent>();
            _capturedEvents.Any().Should().BeFalse();
        }
        public void Dispose_should_dispose_the_server()
        {
            _subject.Initialize();
            _capturedEvents.Clear();

            _subject.Dispose();
            _connectionPool.Received().Dispose();
            _serverMonitor.Received().Dispose();

            _capturedEvents.Next().Should().BeOfType <ServerClosingEvent>();
            _capturedEvents.Next().Should().BeOfType <ServerClosedEvent>();
            _capturedEvents.Any().Should().BeFalse();
        }
Example #4
0
        public void Initialize_should_create_and_initialize_the_server()
        {
            var subject = CreateSubject();

            subject.Initialize();

            _serverFactory.GetServer(_endPoint).Received().Initialize();

            _capturedEvents.Next().Should().BeOfType <ClusterOpeningEvent>();
            _capturedEvents.Next().Should().BeOfType <ClusterAddingServerEvent>();
            _capturedEvents.Next().Should().BeOfType <ClusterAddedServerEvent>();
            _capturedEvents.Next().Should().BeOfType <ClusterOpenedEvent>();
            _capturedEvents.Next().Should().BeOfType <ClusterDescriptionChangedEvent>();
            _capturedEvents.Any().Should().BeFalse();
        }
Example #5
0
        public void Description_should_contain_expected_server_description()
        {
            var subject = CreateSubject();

            subject.Description.Servers.Should().BeEmpty();
            subject.Initialize();
            _capturedEvents.Clear();

            PublishDescription(_endPoint);

            var description = subject.Description;

            description.Servers.Should().ContainSingle(s => EndPointHelper.Equals(s.EndPoint, _endPoint) && s.State == ServerState.Connected);

            _capturedEvents.Next().Should().BeOfType <ClusterDescriptionChangedEvent>();
            _capturedEvents.Any().Should().BeFalse();
        }
Example #6
0
        public void DescriptionChanged_should_be_raised_when_moving_from_disconnected_to_connected()
        {
            var changes = new List <ServerDescriptionChangedEventArgs>();

            _subject.DescriptionChanged += (o, e) => changes.Add(e);

            SetupHeartbeatConnection();
            _subject.Initialize();
            SpinWait.SpinUntil(() => _subject.Description.State == ServerState.Connected, TimeSpan.FromSeconds(5)).Should().BeTrue();

            changes.Count.Should().Be(1);
            changes[0].OldServerDescription.State.Should().Be(ServerState.Disconnected);
            changes[0].NewServerDescription.State.Should().Be(ServerState.Connected);

            _capturedEvents.Next().Should().BeOfType <ServerHeartbeatStartedEvent>();
            _capturedEvents.Next().Should().BeOfType <ServerHeartbeatSucceededEvent>();
            _capturedEvents.Any().Should().BeFalse();
        }
        public void BulkWrite_should_pin_connection_as_expected(
            [Values(1, 3)] int attempts,
            [Values(false, true)] bool async)
        {
            SkipIfNotLoadBalancingMode();

            KillOpenTransactions();

            SetupData();

            ServiceIdHelper.IsServiceIdEmulationEnabled = true; // TODO: temporary solution to enable emulating serviceId in a server response

            var eventCapturer = new EventCapturer()
                                .Capture <ConnectionPoolCheckedOutConnectionEvent>()
                                .Capture <ConnectionPoolCheckingOutConnectionEvent>()
                                .Capture <ConnectionPoolCheckedInConnectionEvent>()
                                .Capture <ConnectionPoolCheckingInConnectionEvent>()
                                .Capture <CommandSucceededEvent>();

            using (var cluster = CreateLoadBalancedCluster(eventCapturer))
            {
                eventCapturer.Clear();

                for (int i = 1; i <= attempts; i++)
                {
                    ICoreSessionHandle session;
                    DisposableBindingBundle <IReadWriteBindingHandle, RetryableWriteContext> writeBindingsBundle;

                    using (session = CreateSession(cluster, isImplicit: false, withTransaction: true))
                    {
                        eventCapturer.Any().Should().BeFalse();
                        using (writeBindingsBundle = CreateReadWriteBindingsAndRetryableWriteContext(cluster, session.Fork(), async))
                        {
                            AssertCheckOutOnlyEvents(eventCapturer, i);

                            _ = CreateAndRunBulkOperation(writeBindingsBundle.RetryableContext, async);

                            AssertCommand(eventCapturer, "insert", noMoreEvents: true);
                        }
                    }
                    AssertCommand(eventCapturer, "abortTransaction", noMoreEvents: false);
                    AssertCheckInOnlyEvents(eventCapturer);
                    AssertSessionReferenceCount(session, 0);
                    AssertChannelReferenceCount(writeBindingsBundle.RetryableContext.Channel, 0);
                }
            }
        }
        public void Description_should_return_default_when_disposed()
        {
            _subject.Dispose();

            var description = _subject.Description;

            description.EndPoint.Should().Be(_endPoint);
            description.Type.Should().Be(ServerType.Unknown);
            description.State.Should().Be(ServerState.Disconnected);

            _capturedEvents.Next().Should().BeOfType <ServerClosingEvent>();
            _capturedEvents.Next().Should().BeOfType <ServerClosedEvent>();
            _capturedEvents.Any().Should().BeFalse();
        }
Example #9
0
        public void AcquireConnectionAsync_should_return_a_connection()
        {
            InitializeAndWait();
            _capturedEvents.Clear();

            var connection = _subject.AcquireConnectionAsync(CancellationToken.None).Result;

            connection.Should().NotBeNull();
            _subject.AvailableCount.Should().Be(_settings.MaxConnections - 1);
            _subject.CreatedCount.Should().Be(_settings.MinConnections);
            _subject.DormantCount.Should().Be(_settings.MinConnections - 1);
            _subject.UsedCount.Should().Be(1);

            _capturedEvents.Next().Should().BeOfType <ConnectionPoolCheckingOutConnectionEvent>();
            _capturedEvents.Next().Should().BeOfType <ConnectionPoolCheckedOutConnectionEvent>();
            _capturedEvents.Any().Should().BeFalse();
        }