/// <summary> /// Performs processing on single message /// </summary> /// <exception cref="SyncRelayOperationException"> /// When the type of an object is defined with settings /// <see cref="MySpace.DataRelay.Common.Schemas.TypeSettings"></see> with /// SyncInMessages=true and /// ThrowOnSyncFailure=true /// failed "in" executions will throw this exception /// </exception> /// <param name="message">Message to be processed</param> public void HandleMessage(RelayMessage message) { Node node; if (message.IsTwoWayMessage) { int allowedRetries = NodeManager.Instance.GetRetryCountForMessage(message); bool triedBefore = false; do { if (PrepareMessage(message, triedBefore).Pop(out node)) { triedBefore = true; node.HandleOutMessage(message); } else { message.SetError(RelayErrorType.NoNodesAvailable); } }while (message.ErrorType == RelayErrorType.NodeUnreachable && --allowedRetries >= 0); } else { SimpleLinkedList <Node> nodes = PrepareMessage(message, false); SerializedRelayMessage serializedMessage = new SerializedRelayMessage(message); SerializedRelayMessage serializedMessageInterZone = null; bool messageHandled = true; // start with "true" so that we do not pop // if there are no items in "nodes" if (nodes.Count == 0) { message.SetError(RelayErrorType.NoNodesAvailable); } else { while (nodes.Pop(out node)) { TypeSetting typeSetting = NodeManager.Instance.Config.TypeSettings.TypeSettingCollection[message.TypeId]; bool typesettingThrowOnSyncFailure = false; bool typesettingSyncInMessages = false; if (null != typeSetting && !node.NodeCluster.MeInThisCluster) { typesettingSyncInMessages = typeSetting.SyncInMessages; typesettingThrowOnSyncFailure = typeSetting.ThrowOnSyncFailure; } if (_myNodeDefinition != null && _myNodeDefinition.Zone != node.NodeDefinition.Zone) { // Message needs to cross Zone bounderies if (serializedMessageInterZone == null) { serializedMessageInterZone = new SerializedRelayMessage(RelayMessage.CreateInterZoneMessageFrom(message)); } if (message.ResultOutcome == null) { message.ResultOutcome = RelayOutcome.Queued; } node.HandleInMessage(serializedMessageInterZone); } else if (typesettingSyncInMessages) { messageHandled = node.HandleInMessageSync(message, typesettingSyncInMessages, typesettingThrowOnSyncFailure); } else { if (message.ResultOutcome == null) { message.ResultOutcome = RelayOutcome.Queued; } node.HandleInMessage(serializedMessage); } if (!messageHandled) { throw new SyncRelayOperationException(string.Format("Node {0} failed to process message {1}\r\n", node, message)); } } } } }
/// <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); }