/// <summary> /// Create a list of nodes with messages that can be retried according to Relay Group settings. /// </summary> /// <param name="distributedMessages">A list of distributed messages have been previously attempted.</param> /// <returns>A redistribution of nodes with messages left to retry, or null if no retries are needed or allowed.</returns> internal NodeWithMessagesCollection RedistributeRetryMessages(NodeWithMessagesCollection distributedMessages) { var redistributedMessages = new NodeWithMessagesCollection(); foreach (var nodeWithMessages in distributedMessages) { var retriesAllowed = nodeWithMessages.NodeWithInfo.Node.NodeGroup.GroupDefinition.RetryCount; var retriesAttempted = nodeWithMessages.AttemptedNodes.Count; if (nodeWithMessages.Messages.OutMessageCount > 0 && retriesAttempted < retriesAllowed) { var firstMessage = nodeWithMessages.Messages.OutMessages[0]; var retryable = firstMessage.IsRetryable(Instance.GetRelayRetryPolicyForMessage(firstMessage)); // the first message's outcome should be the same as every message in the list for these specific conditions if (retryable) { nodeWithMessages.AttemptedNodes.Add(nodeWithMessages.NodeWithInfo.Node); var retryNode = nodeWithMessages.NodeWithInfo.Node.GetRetryNodeFromCluster(nodeWithMessages.AttemptedNodes); if (retryNode != null) { // only try to redistribute this node if a retryNode is available. Otherwise, retries are not possible. nodeWithMessages.NodeWithInfo.Node = retryNode; // prepare each message in the list for retry. foreach (var message in nodeWithMessages.Messages.OutMessages) { message.RelayTTL++; message.SetError(RelayErrorType.None); message.ResultOutcome = RelayOutcome.NotSent; } // wipe out any potential IN messages. nodeWithMessages.Messages.InMessages = null; redistributedMessages.Add(nodeWithMessages); } } } } return(redistributedMessages); }
/// <summary> /// Splits messages into various lists of in and out message destined for different nodes. /// </summary> /// <param name="messages"></param> /// <returns></returns> internal NodeWithMessagesCollection DistributeMessages(IList <RelayMessage> messages) { NodeWithMessagesCollection distribution = new NodeWithMessagesCollection(); RelayMessage message; Node node; for (int i = 0; i < messages.Count; i++) { if (messages[i] != null) { message = messages[i]; RelayMessage interZoneMessage = null; SimpleLinkedList <Node> nodesForMessage = GetNodesForMessage(message); SimpleLinkedList <Node> nodesForInterZoneMessage = null; if (nodesForMessage.Count > 0) { message.AddressHistory.Add(MyIpAddress); } message.RelayTTL--; #region Identify InterZone Messages if (message.IsTwoWayMessage == false) { message.ResultOutcome = RelayOutcome.Queued; //will be queued, if sync will not get overwritten // Identify nodes in foreign zones int nodeCount = nodesForMessage.Count; for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) { nodesForMessage.Pop(out node); if (_myNodeDefinition != null && _myNodeDefinition.Zone != node.NodeDefinition.Zone) { // Message needs to cross Zone bounderies if (interZoneMessage == null) { interZoneMessage = RelayMessage.CreateInterZoneMessageFrom(message); nodesForInterZoneMessage = new SimpleLinkedList <Node>(); } nodesForInterZoneMessage.Push(node); } else { nodesForMessage.Push(node); } } } #endregion if (nodesForMessage.Count > 0) { DebugWriter.WriteDebugInfo(message, nodesForMessage); distribution.Add(message, nodesForMessage); } if (nodesForInterZoneMessage != null && nodesForInterZoneMessage.Count > 0) { DebugWriter.WriteDebugInfo(interZoneMessage, nodesForInterZoneMessage); distribution.Add(interZoneMessage, nodesForInterZoneMessage); } } } return(distribution); }