Beispiel #1
0
        public async Task should_issue_gossip_to_gossip_seed()
        {
            HttpRequestMessage?request = null;
            var gossip = new ClusterMessages.ClusterInfo {
                Members = new[] {
                    new ClusterMessages.MemberInfo {
                        State               = ClusterMessages.VNodeState.Leader,
                        InstanceId          = Guid.NewGuid(),
                        HttpEndPointAddress = IPAddress.Any.ToString(),
                        HttpEndPointPort    = 4444,
                        IsAlive             = true,
                    },
                }
            };

            var handler = new CustomMessageHandler(req => {
                request = req;
                _fixture.CurrentClusterInfo.Members = gossip.Members;
            });

            var gossipSeed = new DnsEndPoint(_fixture.Host, _fixture.Port);

            var sut = new ClusterEndpointDiscoverer(1, new[] {
                gossipSeed,
            }, Timeout.InfiniteTimeSpan, TimeSpan.Zero, NodePreference.Leader, handler);

            await sut.DiscoverAsync();

            Assert.Equal(Uri.UriSchemeHttps, request?.RequestUri.Scheme);
            Assert.Equal(gossipSeed.Host, request?.RequestUri.Host);
            Assert.Equal(gossipSeed.Port, request?.RequestUri.Port);
        }
Beispiel #2
0
        public async Task falls_back_to_first_alive_node_if_a_preferred_node_is_not_found()
        {
            var gossip = new ClusterMessages.ClusterInfo {
                Members = new[] {
                    new ClusterMessages.MemberInfo {
                        State            = ClusterMessages.VNodeState.Leader,
                        InstanceId       = Guid.NewGuid(),
                        ExternalHttpIp   = IPAddress.Any.ToString(),
                        ExternalHttpPort = 1111,
                        IsAlive          = false,
                    },
                    new ClusterMessages.MemberInfo {
                        State            = ClusterMessages.VNodeState.Follower,
                        InstanceId       = Guid.NewGuid(),
                        ExternalHttpIp   = IPAddress.Any.ToString(),
                        ExternalHttpPort = 2222,
                        IsAlive          = true,
                    },
                }
            };
            var handler = new FakeMessageHandler(req => ResponseFromGossip(gossip));

            var sut = new ClusterEndpointDiscoverer(1, new[] {
                new DnsEndPoint("localhost", 1113)
            }, Timeout.InfiniteTimeSpan, TimeSpan.Zero, NodePreference.Leader, handler);

            var result = await sut.DiscoverAsync();

            Assert.Equal(result.Port,
                         gossip.Members.Last(x => x.State == ClusterMessages.VNodeState.Follower).ExternalHttpPort);
        }
Beispiel #3
0
        public async Task falls_back_to_first_alive_node_if_a_preferred_node_is_not_found()
        {
            var gossip = new ClusterMessages.ClusterInfo {
                Members = new[] {
                    new ClusterMessages.MemberInfo {
                        State               = ClusterMessages.VNodeState.Leader,
                        InstanceId          = Guid.NewGuid(),
                        HttpEndPointAddress = IPAddress.Any.ToString(),
                        HttpEndPointPort    = 1111,
                        IsAlive             = false,
                    },
                    new ClusterMessages.MemberInfo {
                        State               = ClusterMessages.VNodeState.Follower,
                        InstanceId          = Guid.NewGuid(),
                        HttpEndPointAddress = IPAddress.Any.ToString(),
                        HttpEndPointPort    = 2222,
                        IsAlive             = true,
                    },
                }
            };
            var handler = new CustomMessageHandler(req => {
                _fixture.CurrentClusterInfo.Members = gossip.Members;
            });

            var sut = new ClusterEndpointDiscoverer(1, new[] {
                new DnsEndPoint(_fixture.Host, _fixture.Port)
            }, Timeout.InfiniteTimeSpan, TimeSpan.Zero, NodePreference.Leader, handler);

            var result = await sut.DiscoverAsync();

            Assert.Equal(result.GetPort(),
                         gossip.Members.Last(x => x.State == ClusterMessages.VNodeState.Follower).HttpEndPointPort);
        }
Beispiel #4
0
        public async Task should_issue_gossip_to_gossip_seed()
        {
            HttpRequestMessage request = null;
            var gossip = new ClusterMessages.ClusterInfo {
                Members = new[] {
                    new ClusterMessages.MemberInfo {
                        State            = ClusterMessages.VNodeState.Leader,
                        InstanceId       = Guid.NewGuid(),
                        ExternalHttpIp   = IPAddress.Any.ToString(),
                        ExternalHttpPort = 4444,
                        IsAlive          = true,
                    },
                }
            };

            var handler = new FakeMessageHandler(req => {
                request = req;
                return(ResponseFromGossip(gossip));
            });

            var gossipSeed = new DnsEndPoint("gossip_seed_endpoint", 1114);

            var sut = new ClusterEndpointDiscoverer(1, new[] {
                gossipSeed,
            }, Timeout.InfiniteTimeSpan, TimeSpan.Zero, NodePreference.Leader, handler);

            await sut.DiscoverAsync();

            Assert.Equal(Uri.UriSchemeHttps, request?.RequestUri.Scheme);
            Assert.Equal(gossipSeed.Host, request?.RequestUri.Host);
            Assert.Equal(gossipSeed.Port, request?.RequestUri.Port);
        }
Beispiel #5
0
        public async Task should_pick_node_based_on_preference(NodePreference preference,
                                                               ClusterMessages.VNodeState expectedState)
        {
            var gossip = new ClusterMessages.ClusterInfo {
                Members = new[] {
                    new ClusterMessages.MemberInfo {
                        State               = ClusterMessages.VNodeState.Leader,
                        InstanceId          = Guid.NewGuid(),
                        HttpEndPointAddress = IPAddress.Any.ToString(),
                        HttpEndPointPort    = 1111,
                        IsAlive             = true,
                    },
                    new ClusterMessages.MemberInfo {
                        State               = ClusterMessages.VNodeState.Follower,
                        InstanceId          = Guid.NewGuid(),
                        HttpEndPointAddress = IPAddress.Any.ToString(),
                        HttpEndPointPort    = 2222,
                        IsAlive             = true,
                    },
                    new ClusterMessages.MemberInfo {
                        State = expectedState == ClusterMessages.VNodeState.ReadOnlyLeaderless
                                                        ? expectedState
                                                        : ClusterMessages.VNodeState.ReadOnlyReplica,
                        InstanceId          = Guid.NewGuid(),
                        HttpEndPointAddress = IPAddress.Any.ToString(),
                        HttpEndPointPort    = 3333,
                        IsAlive             = true,
                    },
                    new ClusterMessages.MemberInfo {
                        State               = ClusterMessages.VNodeState.Manager,
                        InstanceId          = Guid.NewGuid(),
                        HttpEndPointAddress = IPAddress.Any.ToString(),
                        HttpEndPointPort    = 4444,
                        IsAlive             = true,
                    },
                }
            };
            var handler = new CustomMessageHandler(req => {
                _fixture.CurrentClusterInfo.Members = gossip.Members;
            });

            var sut = new ClusterEndpointDiscoverer(1, new[] {
                new DnsEndPoint(_fixture.Host, _fixture.Port)
            }, Timeout.InfiniteTimeSpan, TimeSpan.Zero, preference, handler);

            var result = await sut.DiscoverAsync();

            Assert.Equal(result.GetPort(),
                         gossip.Members.Last(x => x.State == expectedState).HttpEndPointPort);
        }
Beispiel #6
0
        public async Task should_pick_node_based_on_preference(NodePreference preference,
                                                               ClusterMessages.VNodeState expectedState)
        {
            var gossip = new ClusterMessages.ClusterInfo {
                Members = new[] {
                    new ClusterMessages.MemberInfo {
                        State            = ClusterMessages.VNodeState.Leader,
                        InstanceId       = Guid.NewGuid(),
                        ExternalHttpIp   = IPAddress.Any.ToString(),
                        ExternalHttpPort = 1111,
                        IsAlive          = true,
                    },
                    new ClusterMessages.MemberInfo {
                        State            = ClusterMessages.VNodeState.Follower,
                        InstanceId       = Guid.NewGuid(),
                        ExternalHttpIp   = IPAddress.Any.ToString(),
                        ExternalHttpPort = 2222,
                        IsAlive          = true,
                    },
                    new ClusterMessages.MemberInfo {
                        State = expectedState == ClusterMessages.VNodeState.ReadOnlyLeaderless
                                                        ? expectedState
                                                        : ClusterMessages.VNodeState.ReadOnlyReplica,
                        InstanceId       = Guid.NewGuid(),
                        ExternalHttpIp   = IPAddress.Any.ToString(),
                        ExternalHttpPort = 3333,
                        IsAlive          = true,
                    },
                    new ClusterMessages.MemberInfo {
                        State            = ClusterMessages.VNodeState.Manager,
                        InstanceId       = Guid.NewGuid(),
                        ExternalHttpIp   = IPAddress.Any.ToString(),
                        ExternalHttpPort = 4444,
                        IsAlive          = true,
                    },
                }
            };
            var handler = new FakeMessageHandler(req => ResponseFromGossip(gossip));

            var sut = new ClusterEndpointDiscoverer(1, new[] {
                new DnsEndPoint("localhost", 1113)
            }, Timeout.InfiniteTimeSpan, TimeSpan.Zero, preference, handler);

            var result = await sut.DiscoverAsync();

            Assert.Equal(result.Port,
                         gossip.Members.Last(x => x.State == expectedState).ExternalHttpPort);
        }
Beispiel #7
0
        public async Task should_not_exceed_max_discovery_attempts()
        {
            int maxDiscoveryAttempts = 5;
            int discoveryAttempts    = 0;

            var handler = new CustomMessageHandler(request => {
                discoveryAttempts++;
                throw new Exception();
            });

            var sut = new ClusterEndpointDiscoverer(maxDiscoveryAttempts, new[] {
                new DnsEndPoint(_fixture.Host, _fixture.Port),
            }, Timeout.InfiniteTimeSpan, TimeSpan.Zero, NodePreference.Leader, handler);

            await Assert.ThrowsAsync <DiscoveryException>(() => sut.DiscoverAsync());

            Assert.Equal(maxDiscoveryAttempts, discoveryAttempts);
        }
Beispiel #8
0
        public async Task should_not_be_able_to_pick_invalid_node(ClusterMessages.VNodeState invalidState)
        {
            var gossip = new ClusterMessages.ClusterInfo {
                Members = new[] {
                    new ClusterMessages.MemberInfo {
                        State            = invalidState,
                        InstanceId       = Guid.NewGuid(),
                        ExternalHttpIp   = IPAddress.Any.ToString(),
                        ExternalHttpPort = 4444,
                        IsAlive          = true,
                    },
                }
            };

            var handler = new FakeMessageHandler(req => ResponseFromGossip(gossip));

            var sut = new ClusterEndpointDiscoverer(1, new[] { new DnsEndPoint("localhost", 1113), }, Timeout.InfiniteTimeSpan, TimeSpan.Zero, NodePreference.Leader, handler);

            await Assert.ThrowsAsync <DiscoveryException>(() => sut.DiscoverAsync());
        }
Beispiel #9
0
        public async Task should_not_be_able_to_pick_invalid_node(ClusterMessages.VNodeState invalidState)
        {
            var gossip = new ClusterMessages.ClusterInfo {
                Members = new[] {
                    new ClusterMessages.MemberInfo {
                        State               = invalidState,
                        InstanceId          = Guid.NewGuid(),
                        HttpEndPointAddress = IPAddress.Any.ToString(),
                        HttpEndPointPort    = 4444,
                        IsAlive             = true,
                    },
                }
            };

            var handler = new CustomMessageHandler(req => {
                _fixture.CurrentClusterInfo.Members = gossip.Members;
            });

            var sut = new ClusterEndpointDiscoverer(1, new[] { new DnsEndPoint(_fixture.Host, _fixture.Port), }, Timeout.InfiniteTimeSpan, TimeSpan.Zero, NodePreference.Leader, handler);

            await Assert.ThrowsAsync <DiscoveryException>(() => sut.DiscoverAsync());
        }
Beispiel #10
0
        public async Task should_be_able_to_discover_twice()
        {
            bool isFirstGossip = true;
            var  firstGossip   = new ClusterMessages.ClusterInfo {
                Members = new[] {
                    new ClusterMessages.MemberInfo {
                        State               = ClusterMessages.VNodeState.Leader,
                        InstanceId          = Guid.NewGuid(),
                        HttpEndPointAddress = IPAddress.Any.ToString(),
                        HttpEndPointPort    = 1111,
                        IsAlive             = true,
                    },
                    new ClusterMessages.MemberInfo {
                        State               = ClusterMessages.VNodeState.Follower,
                        InstanceId          = Guid.NewGuid(),
                        HttpEndPointAddress = IPAddress.Any.ToString(),
                        HttpEndPointPort    = 2222,
                        IsAlive             = true,
                    },
                }
            };
            var secondGossip = new ClusterMessages.ClusterInfo {
                Members = new[] {
                    new ClusterMessages.MemberInfo {
                        State               = ClusterMessages.VNodeState.Leader,
                        InstanceId          = Guid.NewGuid(),
                        HttpEndPointAddress = IPAddress.Any.ToString(),
                        HttpEndPointPort    = 1111,
                        IsAlive             = false,
                    },
                    new ClusterMessages.MemberInfo {
                        State               = ClusterMessages.VNodeState.Leader,
                        InstanceId          = Guid.NewGuid(),
                        HttpEndPointAddress = IPAddress.Any.ToString(),
                        HttpEndPointPort    = 2222,
                        IsAlive             = true,
                    },
                }
            };

            var handler = new CustomMessageHandler(req => {
                if (isFirstGossip)
                {
                    isFirstGossip = false;
                    _fixture.CurrentClusterInfo.Members = firstGossip.Members;
                }
                else
                {
                    _fixture.CurrentClusterInfo.Members = secondGossip.Members;
                }
            });

            var gossipSeed = new DnsEndPoint(_fixture.Host, _fixture.Port);

            var sut = new ClusterEndpointDiscoverer(5, new[] {
                gossipSeed,
            }, Timeout.InfiniteTimeSpan, TimeSpan.Zero, NodePreference.Leader, handler);

            var result = await sut.DiscoverAsync();

            var expected = firstGossip.Members.First(x => x.HttpEndPointPort == 1111);

            Assert.Equal(expected.HttpEndPointAddress, result.GetHost());
            Assert.Equal(expected.HttpEndPointPort, result.GetPort());

            result = await sut.DiscoverAsync();

            expected = secondGossip.Members.First(x => x.HttpEndPointPort == 2222);

            Assert.Equal(expected.HttpEndPointAddress, result.GetHost());
            Assert.Equal(expected.HttpEndPointPort, result.GetPort());
        }
Beispiel #11
0
        public async Task should_be_able_to_discover_twice()
        {
            bool isFirstGossip = true;
            var  firstGossip   = new ClusterMessages.ClusterInfo {
                Members = new[] {
                    new ClusterMessages.MemberInfo {
                        State            = ClusterMessages.VNodeState.Leader,
                        InstanceId       = Guid.NewGuid(),
                        ExternalHttpIp   = IPAddress.Any.ToString(),
                        ExternalHttpPort = 1111,
                        IsAlive          = true,
                    },
                    new ClusterMessages.MemberInfo {
                        State            = ClusterMessages.VNodeState.Follower,
                        InstanceId       = Guid.NewGuid(),
                        ExternalHttpIp   = IPAddress.Any.ToString(),
                        ExternalHttpPort = 2222,
                        IsAlive          = true,
                    },
                }
            };
            var secondGossip = new ClusterMessages.ClusterInfo {
                Members = new[] {
                    new ClusterMessages.MemberInfo {
                        State            = ClusterMessages.VNodeState.Leader,
                        InstanceId       = Guid.NewGuid(),
                        ExternalHttpIp   = IPAddress.Any.ToString(),
                        ExternalHttpPort = 1111,
                        IsAlive          = false,
                    },
                    new ClusterMessages.MemberInfo {
                        State            = ClusterMessages.VNodeState.Leader,
                        InstanceId       = Guid.NewGuid(),
                        ExternalHttpIp   = IPAddress.Any.ToString(),
                        ExternalHttpPort = 2222,
                        IsAlive          = true,
                    },
                }
            };

            var handler = new FakeMessageHandler(req => {
                if (isFirstGossip)
                {
                    isFirstGossip = false;
                    return(ResponseFromGossip(firstGossip));
                }
                else
                {
                    return(ResponseFromGossip(secondGossip));
                }
            });

            var gossipSeed = new DnsEndPoint("gossip_seed_endpoint", 1114);

            var sut = new ClusterEndpointDiscoverer(5, new[] {
                gossipSeed,
            }, Timeout.InfiniteTimeSpan, TimeSpan.Zero, NodePreference.Leader, handler);

            var result = await sut.DiscoverAsync();

            var expected = firstGossip.Members.First(x => x.ExternalHttpPort == 1111);

            Assert.Equal(expected.ExternalHttpIp, result.Address.ToString());
            Assert.Equal(expected.ExternalHttpPort, result.Port);

            result = await sut.DiscoverAsync();

            expected = secondGossip.Members.First(x => x.ExternalHttpPort == 2222);

            Assert.Equal(expected.ExternalHttpIp, result.Address.ToString());
            Assert.Equal(expected.ExternalHttpPort, result.Port);
        }