Пример #1
0
        private MultiServerCluster CreateAndSetupCluster(ClusterDescription clusterDescription, OperationsCount[] operationsCounts)
        {
#pragma warning disable CS0618 // Type or member is obsolete
            var clusterSettings = new ClusterSettings(
                connectionMode: clusterDescription.ConnectionMode,
                connectionModeSwitch: clusterDescription.ConnectionModeSwitch,
                serverSelectionTimeout: TimeSpan.FromSeconds(30),
                endPoints: new Optional <IEnumerable <EndPoint> >(clusterDescription.Servers.Select(s => s.EndPoint)));
#pragma warning restore CS0618 // Type or member is obsolete

            var mockServerFactory = new Mock <IClusterableServerFactory>();
            mockServerFactory
            .Setup(s => s.CreateServer(It.IsAny <ClusterType>(), It.IsAny <ClusterId>(), It.IsAny <IClusterClock>(), It.IsAny <EndPoint>()))
            .Returns <ClusterType, ClusterId, IClusterClock, EndPoint>((_, _, _, endpoint) =>
            {
                var serverDescription = clusterDescription.Servers
                                        .Single(s => s.EndPoint == endpoint).
                                        With(state: ServerState.Connected);

                var operationsCount = operationsCounts.Single(o => endpoint.ToString().EndsWith(o.address));

                var server = new Mock <IClusterableServer>();
                server.Setup(s => s.ServerId).Returns(serverDescription.ServerId);
                server.Setup(s => s.Description).Returns(serverDescription);
                server.Setup(s => s.EndPoint).Returns(endpoint);
                server.Setup(s => s.OutstandingOperationsCount).Returns(operationsCount.operation_count);

                return(server.Object);
            });

            var result = new MultiServerCluster(clusterSettings, mockServerFactory.Object, new EventCapturer());
            result.Initialize();
            return(result);
        }
Пример #2
0
 private static object _maxElectionInfo(MultiServerCluster obj)
 {
     return(Reflector.GetFieldValue(obj, nameof(_maxElectionInfo)));
 }
Пример #3
0
        public static ElectionId _maxElectionInfo_electionId(this MultiServerCluster obj)
        {
            var maxElectionInfo = _maxElectionInfo(obj);

            return((ElectionId)Reflector.GetFieldValue(maxElectionInfo, "_electionId"));
        }
Пример #4
0
        public static int _maxElectionInfo_setVersion(this MultiServerCluster obj)
        {
            var maxElectionInfo = _maxElectionInfo(obj);

            return((int)Reflector.GetFieldValue(maxElectionInfo, "_setVersion"));
        }
Пример #5
0
        public async Task RapidHeartbeatTimerCallback_should_ignore_reentrant_calls()
        {
            var clusterSettings = new ClusterSettings(
                connectionMode: __clusterConnectionMode,
                connectionModeSwitch: __connectionModeSwitch,
                serverSelectionTimeout: TimeSpan.FromSeconds(30),
                endPoints: new[] { __endPoint1 });

            var       allHeartbeatsReceived = new TaskCompletionSource <bool>();
            const int heartbeatsExpectedMinCount = 3;
            int       heartbeatsCount = 0, isInHeartbeat = 0;
            var       calledReentrantly = false;

            var serverDescription = new ServerDescription(
                __serverId1,
                __endPoint1,
                type: ServerType.ReplicaSetPrimary,
                state: ServerState.Disconnected,
                replicaSetConfig: new ReplicaSetConfig(new[] { __endPoint1 }, "rs", __endPoint1, null));

            var serverMock = new Mock <IClusterableServer>();

            serverMock.Setup(s => s.EndPoint).Returns(__endPoint1);
            serverMock.Setup(s => s.IsInitialized).Returns(true);
            serverMock.Setup(s => s.Description).Returns(serverDescription);
            serverMock.Setup(s => s.RequestHeartbeat()).Callback(BlockHeartbeatRequested);

            var serverFactoryMock = new Mock <IClusterableServerFactory>();

            serverFactoryMock
            .Setup(f => f.CreateServer(It.IsAny <ClusterType>(), It.IsAny <ClusterId>(), It.IsAny <IClusterClock>(), It.IsAny <EndPoint>()))
            .Returns(serverMock.Object);

            using (var cluster = new MultiServerCluster(clusterSettings, serverFactoryMock.Object, new EventCapturer()))
            {
                cluster._minHeartbeatInterval(TimeSpan.FromMilliseconds(10));

                // _minHeartbeatInterval validation might not be necessary, and can be reconsidered along with Reflector testing
                cluster._minHeartbeatInterval().Should().Be(TimeSpan.FromMilliseconds(10));

                ForceClusterId(cluster, __clusterId);

                cluster.Initialize();

                // Trigger Cluster._rapidHeartbeatTimer
                var _ = cluster.SelectServerAsync(CreateWritableServerAndEndPointSelector(__endPoint1), CancellationToken.None);

                // Wait for all heartbeats to complete
                await Task.WhenAny(allHeartbeatsReceived.Task, Task.Delay(1000));
            }

            allHeartbeatsReceived.Task.Status.Should().Be(TaskStatus.RanToCompletion);
            calledReentrantly.Should().Be(false);

            void BlockHeartbeatRequested()
            {
                // Validate BlockHeartbeatRequested is not running already
                calledReentrantly |= Interlocked.Exchange(ref isInHeartbeat, 1) != 0;

                // Block Cluster._rapidHeartbeatTimer timer
                Thread.Sleep(40);

                Interlocked.Exchange(ref isInHeartbeat, 0);

                if (Interlocked.Increment(ref heartbeatsCount) == heartbeatsExpectedMinCount)
                {
                    allHeartbeatsReceived.SetResult(true);
                }
            }
        }