public void IfStartPeerMonitoringMessadeReceived_ConnectsToPeerHealthUri() { var healthUri = new Uri("tcp://127.0.0.2:9090"); var peerIdentifier = new ReceiverIdentifier(Guid.NewGuid().ToByteArray()); var payload = new StartPeerMonitoringMessage { Uri = "tcp://127.0.0.1:800", SocketIdentity = peerIdentifier.Identity, Health = new global::kino.Messaging.Messages.Health { Uri = healthUri.ToSocketAddress(), HeartBeatInterval = TimeSpan.FromMinutes(1) } }; var message = Message.Create(payload); var meta = new ClusterMemberMeta { HealthUri = payload.Health.Uri, HeartBeatInterval = payload.Health.HeartBeatInterval, ScaleOutUri = payload.Uri, LastKnownHeartBeat = DateTime.UtcNow, ConnectionEstablished = false }; connectedPeerRegistry.Setup(m => m.FindOrAdd(It.Is <ReceiverIdentifier>(id => id == peerIdentifier), It.IsAny <ClusterMemberMeta>())).Returns(meta); subscriberSocket.SetupMessageReceived(message, tokenSource.Token); // clusterHealthMonitor.Start(); TimeSpan.FromMilliseconds(100).Sleep(); tokenSource.Cancel(); clusterHealthMonitor.Stop(); // subscriberSocket.Verify(m => m.Connect(healthUri, false), Times.Once); Assert.IsTrue(meta.ConnectionEstablished); }
private bool ProcessHeartBeatMessage(IMessage message, ISocket socket) { var shouldHandle = message.Equals(KinoMessages.HeartBeat); if (shouldHandle) { var payload = message.GetPayload <HeartBeatMessage>(); var socketIdentifier = new ReceiverIdentifier(payload.SocketIdentity); var meta = connectedPeerRegistry.Find(socketIdentifier); if (meta != null) { meta.LastKnownHeartBeat = DateTime.UtcNow; //logger.Debug($"Received HeartBeat from node {socketIdentifier}"); } else { //TODO: Send DiscoveryMessage? What if peer is not supporting message Domains to be used by this node? logger.Warn($"HeartBeat came from unknown node {payload.SocketIdentity.GetAnyString()}. Will disconnect from HealthUri: {payload.HealthUri}"); try { socket.Disconnect(new Uri(payload.HealthUri)); } catch (Exception err) { logger.Error(err); } } } return(shouldHandle); }
public void WhenCheckPeerConnectionMessageArrives_ConnectionToPeerEstablishedAndMessageIsSent() { var peerIdentifier = new ReceiverIdentifier(Guid.NewGuid().ToByteArray()); var payload = new CheckPeerConnectionMessage { SocketIdentity = peerIdentifier.Identity }; var message = Message.Create(payload); subscriberSocket.SetupMessageReceived(message, tokenSource.Token); var meta = new ClusterMemberMeta { ScaleOutUri = "tcp://127.0.0.2:9009", ConnectionEstablished = false, LastKnownHeartBeat = DateTime.UtcNow - TimeSpan.FromMinutes(30) }; connectedPeerRegistry.Setup(m => m.Find(peerIdentifier)).Returns(meta); // clusterHealthMonitor.Start(); AsyncOp.Sleep(); tokenSource.Cancel(); clusterHealthMonitor.Stop(); // socketFactory.Verify(m => m.CreateRouterSocket(), Times.Once); routerSocket.Verify(m => m.SetMandatoryRouting(true), Times.Once); routerSocket.Verify(m => m.Connect(new Uri(meta.ScaleOutUri), true), Times.Once); routerSocket.Verify(m => m.SendMessage(It.Is <IMessage>(msg => msg.Equals(KinoMessages.Ping))), Times.Once); routerSocket.Verify(m => m.Disconnect(new Uri(meta.ScaleOutUri)), Times.Once); Assert.LessOrEqual(DateTime.UtcNow - meta.LastKnownHeartBeat, AsyncOp.MultiplyBy(3)); }
public void IfScaleOutSocketWasNotConnectedToRemoteNode_ConnectionIsEstablished() { messageRouter = CreateMessageRouter(null, externalRoutingTable.Object); var message = Message.Create(new SimpleMessage()).As <Message>(); var otherNodeIdentifier = new ReceiverIdentifier(Guid.NewGuid().ToByteArray()); var otherNode = new Node("tcp://127.0.0.1:9009", otherNodeIdentifier.Identity); var peerConnection = new PeerConnection { Node = otherNode, Health = new Health { Uri = "tcp://127.0.0.1:6767" } }; message.SetReceiverNode(otherNodeIdentifier); externalRoutingTable.Setup(m => m.FindRoutes(It.Is <ExternalRouteLookupRequest>(req => req.ReceiverNodeIdentity == otherNodeIdentifier))).Returns(new[] { peerConnection }); localRouterSocket.SetupMessageReceived(message, ReceiveMessageDelay); // messageRouter.Start(); ReceiveMessageCompletionDelay.Sleep(); messageRouter.Stop(); // externalRoutingTable.Verify(m => m.FindRoutes(It.Is <ExternalRouteLookupRequest>(req => req.Message.Equals(message) && req.ReceiverNodeIdentity == otherNodeIdentifier)), Times.Once); scaleOutSocket.Verify(m => m.Connect(It.Is <Uri>(uri => uri == peerConnection.Node.Uri), true), Times.Once); clusterHealthMonitor.Verify(m => m.StartPeerMonitoring(It.Is <Node>(node => node.Equals(otherNode)), It.Is <Health>(health => health == peerConnection.Health)), Times.Once); Assert.IsTrue(peerConnection.Connected); }
public void IfMessageReceiverNodeIdentitySetToRemoteNodeIdentity_MessageIsSentToThatNode() { messageRouter = CreateMessageRouter(internalRoutingTable.Object, externalRoutingTable.Object); var localSocket = new Mock <ILocalSocket <IMessage> >(); localSocket.Setup(m => m.GetIdentity()).Returns(ReceiverIdentities.CreateForActor); var routes = new[] { localSocket.Object }; internalRoutingTable.Setup(m => m.FindRoutes(It.IsAny <InternalRouteLookupRequest>())).Returns(routes); var message = Message.Create(new SimpleMessage()).As <Message>(); var otherNode = new ReceiverIdentifier(Guid.NewGuid().ToByteArray()); message.SetReceiverNode(otherNode); var peerConnection = new PeerConnection { Node = new Node("tcp://127.0.0.1:9009", otherNode.Identity) }; externalRoutingTable.Setup(m => m.FindRoutes(It.Is <ExternalRouteLookupRequest>(req => req.ReceiverNodeIdentity == otherNode))).Returns(new[] { peerConnection }); localRouterSocket.SetupMessageReceived(message, ReceiveMessageDelay); // messageRouter.Start(); ReceiveMessageCompletionDelay.Sleep(); messageRouter.Stop(); // internalRoutingTable.Verify(m => m.FindRoutes(It.Is <InternalRouteLookupRequest>(req => req.Message.Equals(message))), Times.Never); externalRoutingTable.Verify(m => m.FindRoutes(It.Is <ExternalRouteLookupRequest>(req => req.Message.Equals(message) && req.ReceiverNodeIdentity == otherNode)), Times.Once); scaleOutSocket.Verify(m => m.Connect(It.Is <Uri>(uri => uri == peerConnection.Node.Uri), true), Times.Once); scaleOutSocket.Verify(m => m.SendMessage(message)); }
public void IfScaleOutBackendSocketSendMessageThrowsHostUnreachableException_UnreachableNodeIsUnregistered() { messageRouter = CreateMessageRouter(null, externalRoutingTable.Object); var message = Message.Create(new SimpleMessage()).As <Message>(); var otherNode = new ReceiverIdentifier(Guid.NewGuid().ToByteArray()); message.SetReceiverNode(otherNode); var peerConnection = new PeerConnection { Node = new Node("tcp://127.0.0.1:9009", otherNode.Identity) }; externalRoutingTable.Setup(m => m.FindRoutes(It.IsAny <ExternalRouteLookupRequest>())).Returns(new[] { peerConnection }); localRouterSocket.SetupMessageReceived(message, ReceiveMessageDelay); scaleOutSocket.Setup(m => m.SendMessage(It.IsAny <IMessage>())).Throws <HostUnreachableException>(); var unregPayload = new UnregisterUnreachableNodeMessage { ReceiverNodeIdentity = peerConnection.Node.SocketIdentity }; var unregMessage = Message.Create(unregPayload); var serviceMessageHandler = new Mock <IServiceMessageHandler>(); serviceMessageHandlerRegistry.Setup(m => m.GetMessageHandler(It.Is <MessageIdentifier>(msg => msg.Equals(unregMessage)))).Returns(serviceMessageHandler.Object); // messageRouter.Start(); ReceiveMessageCompletionDelay.Sleep(); messageRouter.Stop(); // serviceMessageHandlerRegistry.Verify(m => m.GetMessageHandler(It.Is <MessageIdentifier>(msg => msg.Equals(unregMessage))), Times.Once); serviceMessageHandler.Verify(m => m.Handle(unregMessage, scaleOutSocket.Object)); }
private bool ProcessDeletePeerMessage(IMessage message, ISocket socket) { var shouldHandle = message.Equals(KinoMessages.DeletePeer); if (shouldHandle) { var payload = message.GetPayload <DeletePeerMessage>(); var socketIdentifier = new ReceiverIdentifier(payload.NodeIdentity); var meta = connectedPeerRegistry.Find(socketIdentifier); if (meta != null) { connectedPeerRegistry.Remove(socketIdentifier); logger.Debug($"Left {connectedPeerRegistry.Count()} nodes to monitor."); if (meta.ConnectionEstablished) { socket.Disconnect(new Uri(meta.HealthUri)); logger.Warn($"Stopped HeartBeat monitoring node {payload.NodeIdentity.GetAnyString()}@{meta.HealthUri}"); } } else { logger.Warn($"Unable to disconnect from unknown node [{payload.NodeIdentity.GetAnyString()}]"); } } return(shouldHandle); }
private void CheckPeerConnection(ReceiverIdentifier nodeIdentifier, ClusterMemberMeta meta) { if (!meta.ConnectionEstablished) { using (var socket = socketFactory.CreateRouterSocket()) { var uri = new Uri(meta.ScaleOutUri); try { socket.SetMandatoryRouting(); socket.Connect(uri, waitUntilConnected: true); var message = Message.Create(new PingMessage()) .As <Message>(); message.SetDomain(securityProvider.GetDomain(KinoMessages.Ping.Identity)); message.SetSocketIdentity(nodeIdentifier.Identity); message.SignMessage(securityProvider); socket.SendMessage(message); socket.Disconnect(uri); meta.LastKnownHeartBeat = DateTime.UtcNow; } catch (Exception err) { routerLocalSocket.Send(Message.Create(new UnregisterUnreachableNodeMessage { ReceiverNodeIdentity = nodeIdentifier.Identity })); logger.Warn($"Failed trying to check connectivity to node {nodeIdentifier}@{uri.ToSocketAddress()}. Peer deletion scheduled. {err}"); } } } }
public void WhenDeletePeerMessageArrives_PeerIsRemovedFromRegistryAndHealthUriDisconnected(bool connectionEstablished) { var peerIdentifier = new ReceiverIdentifier(Guid.NewGuid().ToByteArray()); var payload = new DeletePeerMessage { NodeIdentity = peerIdentifier.Identity }; var message = Message.Create(payload); subscriberSocket.SetupMessageReceived(message, tokenSource.Token); var meta = new ClusterMemberMeta { HealthUri = "tcp://127.0.0.2:9009", ConnectionEstablished = connectionEstablished }; connectedPeerRegistry.Setup(m => m.Find(peerIdentifier)).Returns(meta); // clusterHealthMonitor.Start(); AsyncOp.Sleep(); tokenSource.Cancel(); clusterHealthMonitor.Stop(); // connectedPeerRegistry.Verify(m => m.Remove(peerIdentifier), Times.Once); subscriberSocket.Verify(m => m.Disconnect(new Uri(meta.HealthUri)), Times.Exactly(connectionEstablished ? 1 : 0)); }
public void WhenAddPeerMessageArrives_PeerIsAddedToConnectedPeerRegistry() { var peerIdentifier = new ReceiverIdentifier(Guid.NewGuid().ToByteArray()); var payload = new AddPeerMessage { SocketIdentity = peerIdentifier.Identity, Uri = "tcp://127.0.0.1:8080", Health = new global::kino.Messaging.Messages.Health { Uri = "tcp://127.0.0.2:9090", HeartBeatInterval = TimeSpan.FromSeconds(10) } }; var message = Message.Create(payload); subscriberSocket.SetupMessageReceived(message, tokenSource.Token); // clusterHealthMonitor.Start(); AsyncOp.Sleep(); tokenSource.Cancel(); clusterHealthMonitor.Stop(); // Func <ClusterMemberMeta, bool> isPeerMetadata = meta => payload.Health.Uri == meta.HealthUri && payload.Health.HeartBeatInterval == meta.HeartBeatInterval && payload.Uri == meta.ScaleOutUri; connectedPeerRegistry.Verify(m => m.FindOrAdd(peerIdentifier, It.Is <ClusterMemberMeta>(meta => isPeerMetadata(meta))), Times.Once); }
public void Handle(IMessage message, ISocket _) { if (securityProvider.DomainIsAllowed(message.Domain)) { message.As <Message>().VerifySignature(securityProvider); var payload = message.GetPayload <RegisterExternalMessageRouteMessage>(); var peer = new Node(new Uri(payload.Uri), payload.NodeIdentity); var health = new Health { Uri = payload.Health.Uri, HeartBeatInterval = payload.Health.HeartBeatInterval }; var peerAddedForMonitoring = false; foreach (var route in payload.Routes) { var receiver = new ReceiverIdentifier(route.ReceiverIdentity); var messageRoutes = receiver.IsMessageHub() ? new MessageRoute { Receiver = receiver }.ToEnumerable() : route.MessageContracts.Select(mc => new MessageRoute { Receiver = receiver, Message = new MessageIdentifier(mc.Identity, mc.Version, mc.Partition) }); foreach (var messageRoute in messageRoutes) { try { //NOTE: Keep the order in if(...), hence MessageHub is not registered to receive any specific message if (receiver.IsMessageHub() || securityProvider.GetDomain(messageRoute.Message.Identity) == message.Domain) { if (!peerAddedForMonitoring) { clusterHealthMonitor.AddPeer(peer, health); peerAddedForMonitoring = true; } externalRoutingTable.AddMessageRoute(new ExternalRouteRegistration { Route = messageRoute, Peer = peer, Health = health }); } else { logger.Warn($"MessageIdentity {messageRoute.Message} doesn't belong to requested Domain {message.Domain}!"); } } catch (Exception err) { logger.Error(err); } } } } }
public LocalSocket() { dataAvailable = new ManualResetEvent(false); socketIdentity = ReceiverIdentifier.Create(); messageQueue = new BlockingCollection <T>(new ConcurrentQueue <T>()); lookAheadQueue = new BlockingCollection <T>(new ConcurrentQueue <T>()); hashCode = socketIdentity.GetHashCode(); }
private Bcl.IEnumerable <MessageHubRoute> GetMessageNodeHubs(ReceiverIdentifier node) => nodeMessageHubs.TryGetValue(node, out var messageHubs) ? messageHubs.Select(mh => new MessageHubRoute { MessageHub = mh, LocalRegistration = false }) .ToList() : Enumerable.Empty <MessageHubRoute>();
private void MapActorToNode(ExternalRouteRegistration routeRegistration, ReceiverIdentifier nodeIdentifier) { if (!nodeActors.TryGetValue(nodeIdentifier, out var actors)) { actors = new Bcl.HashSet <ReceiverIdentifier>(); nodeActors[nodeIdentifier] = actors; } actors.Add(routeRegistration.Route.Receiver); }
public SynodConfigurationProvider(SynodConfiguration config) { LocalNode = new Node(config.LocalNode.ParseAddress(), ReceiverIdentifier.CreateIdentity()); synod = config.Members .Select(uri => new DynamicUri(uri)) .ToList(); HeartBeatInterval = config.HeartBeatInterval; MissingHeartBeatsBeforeReconnect = config.MissingHeartBeatsBeforeReconnect; IntercomEndpoint = new Uri(config.IntercomEndpoint); }
private void RemoveMessageToNodeMap(ExternalRouteRemoval routeRemoval, ReceiverIdentifier receiverNode) { if (messageToNodeMap.TryGetValue(routeRemoval.Route.Message, out var nodes)) { nodes.Remove(receiverNode); if (!nodes.Any()) { messageToNodeMap.Remove(routeRemoval.Route.Message); } } }
public ScaleOutSocketConfiguration GetScaleOutConfiguration() { var uris = appConfig.ScaleOutAddressUri.GetAddressRange(); var socketIdentifier = ReceiverIdentifier.CreateIdentity(); return(new ScaleOutSocketConfiguration { ScaleOutReceiveMessageQueueLength = Math.Max(appConfig.ScaleOutReceiveMessageQueueLength, 10000), AddressRange = uris.Select(uri => new SocketEndpoint(uri, socketIdentifier)) .ToList() }); }
public MessageHub(IInternalRegistrationService internalRegistrationService, ILocalSocketFactory localSocketFactory, IMessageRouter messageRouter, ISecurityProvider securityProvider, ICallbackHandlerStack callbackHandlers) { ReceiverIdentifier = ReceiverIdentifier.Create(ReceiverKind.MessageHub); this.internalRegistrationService = internalRegistrationService; this.messageRouter = messageRouter; this.securityProvider = securityProvider; this.callbackHandlers = callbackHandlers; socket = localSocketFactory.Create(DispatchMessage); }
public void ReceiverNode_IsConsistentlyTransferredViaMultipartMessage() { var message = Message.CreateFlowStartMessage(new SimpleMessage()).As <Message>(); var receiverNode = ReceiverIdentifier.Create(); message.SetReceiverNode(receiverNode); var multipart = new MultipartMessage(message); message = Message.FromMultipartMessage(multipart); CollectionAssert.AreEqual(receiverNode.Identity, message.ReceiverNodeIdentity); }
public void IfReceiverIdentifierNeitherMessageHubNorActor_AddMessageRouteThrowsException() { var receiverIdentity = new ReceiverIdentifier(Guid.NewGuid().ToByteArray()); var localSocket = new LocalSocket <IMessage>(); var registration = new InternalRouteRegistration { ReceiverIdentifier = receiverIdentity, DestinationSocket = localSocket }; // Assert.Throws <ArgumentException>(() => internalRoutingTable.AddMessageRoute(registration)); }
private void RemoveNodeActor(ExternalRouteRemoval routeRemoval, ReceiverIdentifier nodeIdentifier) { if (nodeActors.TryGetValue(nodeIdentifier, out var actors)) { if (actors.Remove(routeRemoval.Route.Receiver)) { if (!actors.Any()) { nodeActors.Remove(nodeIdentifier); } RemoveMessageToNodeMap(routeRemoval, nodeIdentifier); } } }
private void MapMessageToNode(ExternalRouteRegistration routeRegistration, ReceiverIdentifier nodeIdentifier) { var messageIdentifier = routeRegistration.Route.Message; if (!messageToNodeMap.TryGetValue(messageIdentifier, out var nodes)) { nodes = new HashedLinkedList <ReceiverIdentifier>(); messageToNodeMap[messageIdentifier] = nodes; } if (!nodes.Contains(nodeIdentifier)) { nodes.InsertLast(nodeIdentifier); } }
public void Handle(IMessage message, ISocket scaleOutBackend) { var payload = message.GetPayload <UnregisterUnreachableNodeMessage>(); var nodeIdentifier = new ReceiverIdentifier(payload.ReceiverNodeIdentity); var peerRemoveResult = externalRoutingTable.RemoveNodeRoute(nodeIdentifier); if (peerRemoveResult.ConnectionAction == PeerConnectionAction.Disconnect) { scaleOutBackend.SafeDisconnect(peerRemoveResult.Uri); } if (peerRemoveResult.ConnectionAction != PeerConnectionAction.KeepConnection) { clusterHealthMonitor.DeletePeer(nodeIdentifier); } }
private static ExternalRouteRegistration CreateActorRouteRegistration(MessageIdentifier messageIdentifier, ReceiverIdentifier receiverIdentifier, byte[] nodeIdentity) => new ExternalRouteRegistration { Peer = new Node("tcp://127.0.0.2:8080", nodeIdentity), Health = new Health { Uri = "tcp://192.168.0.1:9090", HeartBeatInterval = TimeSpan.FromSeconds(4) }, Route = new MessageRoute { Message = messageIdentifier, Receiver = receiverIdentifier } };
private bool ProcessCheckPeerConnectionMessage(IMessage message) { var shouldHandle = message.Equals(KinoMessages.CheckPeerConnection); if (shouldHandle) { var suspiciousNode = new ReceiverIdentifier(message.GetPayload <CheckPeerConnectionMessage>().SocketIdentity); logger.Debug($"Connectivity check requested for node {suspiciousNode}"); var meta = connectedPeerRegistry.Find(suspiciousNode); if (meta != null) { CheckPeerConnection(suspiciousNode, meta); } } return(shouldHandle); }
private void RemoveActorRoute(ExternalRouteRemoval routeRemoval) { var nodeIdentifier = new ReceiverIdentifier(routeRemoval.NodeIdentifier); if (actorToMessageMap.TryGetValue(routeRemoval.Route.Receiver, out var messages)) { messages.Remove(routeRemoval.Route.Message); if (!messages.Any()) { actorToMessageMap.Remove(routeRemoval.Route.Receiver); RemoveNodeActor(routeRemoval, nodeIdentifier); } logger.Debug("External message route removed " + $"Node:[{nodeIdentifier}] " + $"Message:[{routeRemoval.Route.Message}]"); } }
public PeerRemoveResult RemoveNodeRoute(ReceiverIdentifier nodeIdentifier) { var peerConnectionAction = PeerConnectionAction.NotFound; if (nodeToConnectionMap.TryGetValue(nodeIdentifier, out var connection)) { nodeToConnectionMap.Remove(nodeIdentifier); peerConnectionAction = RemovePeerNode(connection); roundRobinList.Remove(connection.Node); nodeMessageHubs.Remove(nodeIdentifier); if (nodeActors.TryGetValue(nodeIdentifier, out var actors)) { nodeActors.Remove(nodeIdentifier); foreach (var actor in actors) { if (actorToMessageMap.TryGetValue(actor, out var messages)) { actorToMessageMap.Remove(actor); foreach (var message in messages) { if (messageToNodeMap.TryGetValue(message, out var nodes)) { nodes.Remove(nodeIdentifier); if (!nodes.Any()) { messageToNodeMap.Remove(message); } } } } } } logger.Debug($"External route removed Uri:{connection.Node.Uri.AbsoluteUri} " + $"Node:{nodeIdentifier.Identity.GetAnyString()}"); } return(new PeerRemoveResult { Uri = connection?.Node.Uri, ConnectionAction = peerConnectionAction }); }
public void IfMessageIsNotHandledLocaly_ItIsForwardedAway() { messageRouter = CreateMessageRouter(externalRoutingTable: externalRoutingTable.Object); var message = Message.Create(new SimpleMessage()).As <Message>(); var otherNode = new ReceiverIdentifier(Guid.NewGuid().ToByteArray()); var peerConnection = new PeerConnection { Node = new Node("tcp://127.0.0.1:9009", otherNode.Identity) }; externalRoutingTable.Setup(m => m.FindRoutes(It.IsAny <ExternalRouteLookupRequest>())).Returns(new[] { peerConnection }); localRouterSocket.SetupMessageReceived(message, ReceiveMessageDelay); // messageRouter.Start(); ReceiveMessageCompletionDelay.Sleep(); messageRouter.Stop(); // scaleOutSocket.Verify(m => m.SendMessage(message)); }
private void RemoveMessageHubRoute(ExternalRouteRemoval routeRemoval) { var nodeIdentifier = new ReceiverIdentifier(routeRemoval.NodeIdentifier); if (nodeMessageHubs.TryGetValue(nodeIdentifier, out var messageHubs)) { if (messageHubs.Remove(routeRemoval.Route.Receiver)) { if (!messageHubs.Any()) { nodeMessageHubs.Remove(nodeIdentifier); } logger.Debug("External MessageHub removed " + $"Node:[{nodeIdentifier}] " + $"Identity:[{routeRemoval.Route.Receiver}]"); } } }
public void FindRoutesByReceiverNode_ReturnsRouteRegardlessOfMessage() { var routeRegistration = CreateActorRouteRegistration(); var receiverIdentity = new ReceiverIdentifier(routeRegistration.Peer.SocketIdentity); externalRoutingTable.AddMessageRoute(routeRegistration); // var route = externalRoutingTable.FindRoutes(new ExternalRouteLookupRequest { ReceiverNodeIdentity = receiverIdentity }) .First(); // Assert.AreEqual(routeRegistration.Peer, route.Node); Assert.AreEqual(routeRegistration.Health.Uri, route.Health.Uri); Assert.AreEqual(routeRegistration.Health.HeartBeatInterval, route.Health.HeartBeatInterval); Assert.IsFalse(route.Connected); }