Beispiel #1
0
        public async Task Should_SendRequestToFirstHostOnly_When_PrepareOnAllHostsIsFalseAndAllHostsHaveConnectionsButFirstHostPoolDoesntHaveConnections()
        {
            var lbpCluster = new FakeLoadBalancingPolicy();
            var mockResult = BuildPrepareHandler(
                builder =>
            {
                builder.QueryOptions =
                    new QueryOptions()
                    .SetConsistencyLevel(ConsistencyLevel.LocalOne)
                    .SetSerialConsistencyLevel(ConsistencyLevel.LocalSerial)
                    .SetPrepareOnAllHosts(false);
                builder.SocketOptions =
                    new SocketOptions().SetReadTimeoutMillis(10);
                builder.Policies = new Cassandra.Policies(
                    lbpCluster,
                    new ConstantReconnectionPolicy(5),
                    new DefaultRetryPolicy(),
                    NoSpeculativeExecutionPolicy.Instance,
                    new AtomicMonotonicTimestampGenerator());
            });

            // mock connection send
            mockResult.ConnectionFactory.OnCreate += connection =>
            {
                Mock.Get(connection)
                .Setup(c => c.Send(It.IsAny <IRequest>()))
                .Returns <IRequest>(async req =>
                {
                    mockResult.SendResults.Enqueue(new ConnectionSendResult {
                        Connection = connection, Request = req
                    });
                    await Task.Delay(1).ConfigureAwait(false);
                    return(new ProxyResultResponse(
                               ResultResponse.ResultResponseKind.Void,
                               new OutputPrepared(new byte[0], new RowSetMetadata {
                        Columns = new CqlColumn[0]
                    })));
                });
            };
            var queryPlan = mockResult.Session.InternalCluster.GetResolvedEndpoints().Select(x => new Host(x.Value.First())).ToList();
            await mockResult.Session.GetOrCreateConnectionPool(queryPlan[1], HostDistance.Local).Warmup().ConfigureAwait(false);

            await mockResult.Session.GetOrCreateConnectionPool(queryPlan[2], HostDistance.Local).Warmup().ConfigureAwait(false);

            var pools = mockResult.Session.GetPools().ToList();

            Assert.AreEqual(2, pools.Count);
            var distanceCount = Interlocked.Read(ref lbpCluster.DistanceCount);
            var request       = new InternalPrepareRequest("TEST");

            await mockResult.PrepareHandler.Prepare(
                request,
                mockResult.Session,
                queryPlan.GetEnumerator()).ConfigureAwait(false);

            var results = mockResult.SendResults.ToArray();

            pools = mockResult.Session.GetPools().ToList();
            Assert.AreEqual(3, pools.Count);
            Assert.AreEqual(1, results.Length);
            Assert.AreEqual(distanceCount + 1, Interlocked.Read(ref lbpCluster.DistanceCount), 1);
            Assert.AreEqual(Interlocked.Read(ref lbpCluster.NewQueryPlanCount), 0);
            Assert.AreEqual(3, mockResult.ConnectionFactory.CreatedConnections.Count);
            Assert.LessOrEqual(1, mockResult.ConnectionFactory.CreatedConnections[queryPlan[0].Address].Count);
            Assert.LessOrEqual(1, mockResult.ConnectionFactory.CreatedConnections[queryPlan[1].Address].Count);
            Assert.LessOrEqual(1, mockResult.ConnectionFactory.CreatedConnections[queryPlan[2].Address].Count);
            // Assert that pool of first host contains only one connection that was called send
            var poolConnections =
                pools
                .Select(p => p.Value.ConnectionsSnapshot.Intersect(results.Select(r => r.Connection)))
                .Where(p => mockResult.ConnectionFactory.CreatedConnections[queryPlan[0].Address].Contains(p.SingleOrDefault()))
                .ToList();

            Assert.AreEqual(1, poolConnections.Count);
            foreach (var pool in poolConnections)
            {
                Mock.Get(pool.Single()).Verify(c => c.Send(request), Times.Once);
            }
        }