Example #1
0
        public void Cursor_should_unpin_connection_for_operations_under_the_same_transaction_after_abortTransaction_and_cursor_dispose(
            [Values(1, 3)] int attempts,
            [Values(false, true)] bool forceCursorClose,
            [Values(false, true)] bool async)
        {
            SkipIfNotLoadBalancingMode();

            KillOpenTransactions();

            SetupData();

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

            List <IAsyncCursor <BsonDocument> > cursors = new();

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

                ICoreSessionHandle session;
                DisposableBindingBundle <IReadBindingHandle, RetryableReadContext> readBindingsBundle = null;

                using (session = CreateSession(cluster, isImplicit: false, withTransaction: true))
                {
                    for (int i = 1; i <= attempts; i++)
                    {
                        AssertSessionReferenceCount(session, i); // dynamic value because we don't close cursors in the loop

                        IAsyncCursor <BsonDocument> asyncCursor;
                        eventCapturer.Any().Should().BeFalse();
                        using (readBindingsBundle = CreateReadBindingsAndRetryableReadContext(cluster, session.Fork(), async))
                        {
                            AssertCheckOutOnlyEvents(eventCapturer, i, shouldNextAttemptTriggerCheckout: false);

                            asyncCursor = CreateAndRunFindOperation(readBindingsBundle.RetryableContext, async);

                            AssertCommand(eventCapturer, "find", noMoreEvents: true);
                        }
                        MoveNext(asyncCursor, async).Should().BeTrue(); // no op
                        MoveNext(asyncCursor, async).Should().BeTrue();

                        AssertCommand(eventCapturer, "getMore", noMoreEvents: true);

                        cursors.Add(asyncCursor);
                    }

                    AbortTransaction(session, async);
                    AssertCommand(eventCapturer, "abortTransaction", noMoreEvents: true);
                }

                for (int i = 0; i < cursors.Count; i++)
                {
                    IAsyncCursor <BsonDocument> cursor = cursors[i];
                    if (forceCursorClose)
                    {
                        cursor.Dispose();
                    }
                    else
                    {
                        var exception = Record.Exception(() => cursor.MoveNext());
                        exception
                        .Should()
                        .BeOfType <MongoCommandException>()
                        .Subject
                        .Message
                        .Should()
                        .StartWith("Command getMore failed: Cannot run getMore on cursor")
                        .And
                        .EndWith("without a txnNumber.");
                        cursor.Dispose();
                    }

                    AssertCommand(eventCapturer, "killCursors", noMoreEvents: i < cursors.Count - 1);
                }
                AssertCheckInOnlyEvents(eventCapturer);
                AssertSessionReferenceCount(session, 0);
                AssertChannelReferenceCount(readBindingsBundle.RetryableContext.Channel, 0);
            }
        }
Example #2
0
        public void Cursor_should_pin_connection_in_transaction_with_the_same_session_as_expected(
            [Values(1, 4)] int attempts,
            [Values(false, true)] bool forceCursorClose,
            [Values(false)] bool async)
        {
            SkipIfNotLoadBalancingMode();

            KillOpenTransactions();

            SetupData();

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

            List <IAsyncCursor <BsonDocument> > cursors = new();

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

                ICoreSessionHandle session;
                DisposableBindingBundle <IReadBindingHandle, RetryableReadContext> readBindingsBundle = null;

                using (session = CreateSession(cluster, isImplicit: false, withTransaction: true))
                {
                    for (int i = 1; i <= attempts; i++)
                    {
                        AssertSessionReferenceCount(session, i); // dynamic value because we don't close cursors in the loop

                        IAsyncCursor <BsonDocument> asyncCursor;
                        eventCapturer.Any().Should().BeFalse();
                        using (readBindingsBundle = CreateReadBindingsAndRetryableReadContext(cluster, session.Fork(), async))
                        {
                            AssertCheckOutOnlyEvents(eventCapturer, i, shouldNextAttemptTriggerCheckout: false);

                            asyncCursor = CreateAndRunFindOperation(readBindingsBundle.RetryableContext, async);

                            AssertCommand(eventCapturer, "find", noMoreEvents: true);
                        }
                        MoveNext(asyncCursor, async).Should().BeTrue(); // no op
                        MoveNext(asyncCursor, async).Should().BeTrue();

                        AssertCommand(eventCapturer, "getMore", noMoreEvents: true);

                        cursors.Add(asyncCursor);
                    }
                }

                for (int i = 0; i < cursors.Count; i++)
                {
                    IAsyncCursor <BsonDocument> cursor = cursors[i];
                    if (forceCursorClose)
                    {
                        cursor.Dispose();

                        AssertCommand(eventCapturer, "killCursors", noMoreEvents: i < cursors.Count - 1);
                    }
                    else
                    {
                        MoveNext(cursor, async).Should().BeTrue(); // returns cursorId = 0
                        MoveNext(cursor, async).Should().BeFalse();

                        AssertCommand(eventCapturer, "getMore", noMoreEvents: i < cursors.Count - 1);
                    }
                }
                AssertCommand(eventCapturer, "abortTransaction", noMoreEvents: false);
                AssertCheckInOnlyEvents(eventCapturer);
                AssertSessionReferenceCount(session, 0);
                AssertChannelReferenceCount(readBindingsBundle.RetryableContext.Channel, 0);
            }
        }