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); }
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); }
public async Task falls_back_to_first_alive_node_if_a_preferred_node_is_not_found(bool useHttps) { var gossip = new ClusterMessages.ClusterInfo { Members = new[] { new ClusterMessages.MemberInfo { State = ClusterMessages.VNodeState.Leader, InstanceId = Guid.NewGuid(), EndPoint = new DnsEndPoint(IPAddress.Any.ToString(), 1111), IsAlive = false, }, new ClusterMessages.MemberInfo { State = ClusterMessages.VNodeState.Follower, InstanceId = Guid.NewGuid(), EndPoint = new DnsEndPoint(IPAddress.Any.ToString(), 2222), IsAlive = true, }, } }; var sut = new GossipBasedEndpointDiscoverer( new EventStoreClientConnectivitySettings { MaxDiscoverAttempts = 1, GossipTimeout = System.Threading.Timeout.InfiniteTimeSpan, Insecure = !useHttps, DiscoveryInterval = TimeSpan.Zero, NodePreference = NodePreference.Leader, DnsGossipSeeds = new[] { _gossipSeed } }, new CallbackTestGossipClient(gossip)); var result = await sut.DiscoverAsync(); Assert.Equal(result.GetPort(), gossip.Members.Last(x => x.State == ClusterMessages.VNodeState.Follower).EndPoint.Port); }
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); }
public async Task should_issue_gossip_to_gossip_seed(bool useHttps) { var endPoint = new DnsEndPoint(IPAddress.Any.ToString(), 4444); var gossip = new ClusterMessages.ClusterInfo { Members = new[] { new ClusterMessages.MemberInfo { State = ClusterMessages.VNodeState.Leader, InstanceId = Guid.NewGuid(), EndPoint = endPoint, IsAlive = true, }, } }; var sut = new GossipBasedEndpointDiscoverer( new EventStoreClientConnectivitySettings { MaxDiscoverAttempts = 1, GossipTimeout = System.Threading.Timeout.InfiniteTimeSpan, Insecure = !useHttps, DiscoveryInterval = TimeSpan.Zero, NodePreference = NodePreference.Leader, DnsGossipSeeds = new[] { _gossipSeed } }, new CallbackTestGossipClient(gossip)); var result = await sut.DiscoverAsync(); Assert.Equal(result, endPoint); }
internal async Task should_not_be_able_to_pick_invalid_node(bool useHttps, ClusterMessages.VNodeState invalidState) { var gossip = new ClusterMessages.ClusterInfo { Members = new[] { new ClusterMessages.MemberInfo { State = invalidState, InstanceId = Guid.NewGuid(), EndPoint = new DnsEndPoint(IPAddress.Any.ToString(), 4444), IsAlive = true, }, } }; var sut = new GossipBasedEndpointDiscoverer( new EventStoreClientConnectivitySettings { MaxDiscoverAttempts = 1, GossipTimeout = System.Threading.Timeout.InfiniteTimeSpan, Insecure = !useHttps, DiscoveryInterval = TimeSpan.Zero, NodePreference = NodePreference.Leader, DnsGossipSeeds = new[] { _gossipSeed } }, new CallbackTestGossipClient(gossip)); var ex = await Assert.ThrowsAsync <DiscoveryException>(async() => await sut.DiscoverAsync()); Assert.Equal(1, ex.MaxDiscoverAttempts); }
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); }
private HttpResponseMessage ResponseFromGossip(ClusterMessages.ClusterInfo gossip) => new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(JsonSerializer.Serialize(gossip, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, PropertyNameCaseInsensitive = true, Converters = { new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) } })) };
public async Task should_be_able_to_discover_twice(bool useHttps) { var firstGossip = new ClusterMessages.ClusterInfo { Members = new[] { new ClusterMessages.MemberInfo { State = ClusterMessages.VNodeState.Leader, InstanceId = Guid.NewGuid(), EndPoint = new DnsEndPoint(IPAddress.Any.ToString(), 1111), IsAlive = true, }, new ClusterMessages.MemberInfo { State = ClusterMessages.VNodeState.Follower, InstanceId = Guid.NewGuid(), EndPoint = new DnsEndPoint(IPAddress.Any.ToString(), 2222), IsAlive = true, }, } }; var secondGossip = new ClusterMessages.ClusterInfo { Members = new[] { new ClusterMessages.MemberInfo { State = ClusterMessages.VNodeState.Leader, InstanceId = Guid.NewGuid(), EndPoint = new DnsEndPoint(IPAddress.Any.ToString(), 1111), IsAlive = false, }, new ClusterMessages.MemberInfo { State = ClusterMessages.VNodeState.Leader, InstanceId = Guid.NewGuid(), EndPoint = new DnsEndPoint(IPAddress.Any.ToString(), 2222), IsAlive = true, }, } }; var sut = new GossipBasedEndpointDiscoverer( new EventStoreClientConnectivitySettings { MaxDiscoverAttempts = 5, GossipTimeout = System.Threading.Timeout.InfiniteTimeSpan, Insecure = !useHttps, DiscoveryInterval = TimeSpan.Zero, NodePreference = NodePreference.Leader, DnsGossipSeeds = new[] { _gossipSeed } }, new MultiGossipCallback(firstGossip, secondGossip)); var result = await sut.DiscoverAsync(); var expected = firstGossip.Members.First(x => x.EndPoint.Port == 1111); Assert.Equal(expected.EndPoint.Host, result.GetHost()); Assert.Equal(expected.EndPoint.Port, result.GetPort()); result = await sut.DiscoverAsync(); expected = secondGossip.Members.First(x => x.EndPoint.Port == 2222); Assert.Equal(expected.EndPoint.Host, result.GetHost()); Assert.Equal(expected.EndPoint.Port, result.GetPort()); }
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); }
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); }
internal async Task should_pick_node_based_on_preference(bool useHttps, NodePreference preference, ClusterMessages.VNodeState expectedState) { var gossip = new ClusterMessages.ClusterInfo { Members = new[] { new ClusterMessages.MemberInfo { State = ClusterMessages.VNodeState.Leader, InstanceId = Guid.NewGuid(), EndPoint = new DnsEndPoint(IPAddress.Any.ToString(), 1111), IsAlive = true, }, new ClusterMessages.MemberInfo { State = ClusterMessages.VNodeState.Follower, InstanceId = Guid.NewGuid(), EndPoint = new DnsEndPoint(IPAddress.Any.ToString(), 2222), IsAlive = true, }, new ClusterMessages.MemberInfo { State = expectedState == ClusterMessages.VNodeState.ReadOnlyLeaderless ? expectedState : ClusterMessages.VNodeState.ReadOnlyReplica, InstanceId = Guid.NewGuid(), EndPoint = new DnsEndPoint(IPAddress.Any.ToString(), 3333), IsAlive = true, }, new ClusterMessages.MemberInfo { State = ClusterMessages.VNodeState.Manager, InstanceId = Guid.NewGuid(), EndPoint = new DnsEndPoint(IPAddress.Any.ToString(), 4444), IsAlive = true, }, } }; var sut = new GossipBasedEndpointDiscoverer( new EventStoreClientConnectivitySettings { MaxDiscoverAttempts = 1, GossipTimeout = System.Threading.Timeout.InfiniteTimeSpan, Insecure = !useHttps, DiscoveryInterval = TimeSpan.Zero, NodePreference = preference, DnsGossipSeeds = new[] { _gossipSeed } }, new CallbackTestGossipClient(gossip)); var result = await sut.DiscoverAsync(); Assert.Equal(result.GetPort(), gossip.Members.Last(x => x.State == expectedState).EndPoint.Port); }
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()); }
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()); }
public CallbackTestGossipClient(ClusterMessages.ClusterInfo gossip, Action?callback = null) { _gossip = gossip; _callback = callback; }
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()); }
public GossipImplementation(ClusterMessages.ClusterInfo currentClusterInfo) { _currentClusterInfo = currentClusterInfo; }
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); }