public void EnsureReliability(OutboundDisruptorEntry disruptorEntry, IMessage message, IEnumerable<MessageSubscription> concernedSubscriptions, MessageWireData messageData)
        {
            var messageOptions = _messageOptions[message.GetType().FullName];

            if (messageOptions.ReliabilityLevel != ReliabilityLevel.FireAndForget)
                foreach (var wireMessage in disruptorEntry.NetworkSenderData.WireMessages)
                {
                    int seqNum;
                    if (!_endpointToSequenceNumber.TryGetValue(wireMessage.Endpoint, out seqNum))
                    {
                        _endpointToSequenceNumber.Add(wireMessage.Endpoint, 0);
                        seqNum = 0;
                    }
                    wireMessage.MessageData.SequenceNumber = seqNum;
                    _endpointToSequenceNumber[wireMessage.Endpoint] = seqNum + 1;
                }

            if (disruptorEntry.MessageTargetHandlerData.IsAcknowledgement)
            {
                SendAcknowledgementShadowMessages(message, concernedSubscriptions, disruptorEntry, messageData);
            }
            else
            {
                if (messageOptions.ReliabilityLevel == ReliabilityLevel.Persisted)
                {
                    SendShadowMessages(concernedSubscriptions, messageData, disruptorEntry);

                }
            }
        }
        private void SendShadowMessages(IEnumerable<MessageSubscription> concernedSubscriptions, MessageWireData messageData, OutboundDisruptorEntry disruptorData)
        {
            foreach (var subscription in concernedSubscriptions)
            {
                HashSet<ServicePeer> targetShadows;
                if (_peersToShadows.TryGetValue(subscription.Peer, out targetShadows))
                {
                    var endpoints = targetShadows.Select(x => x.HandledMessages.Single(y => y.MessageType == typeof(ShadowMessageCommand)).Endpoint).Distinct();

                    foreach (var endpoint in endpoints)
                    {
                        var shadowMessage = new ShadowMessageCommand(messageData, subscription.Peer, true, subscription.Endpoint);
                        var shadowMessageData = CreateMessageWireData(shadowMessage);
                        var wireMessage = new WireSendingMessage(shadowMessageData, endpoint);
                        disruptorData.NetworkSenderData.WireMessages.Add(wireMessage);
                    }
                }
            }
        }
        private void SendToSelfShadows(Guid messageId, bool processSuccessful, PeerId originatingPeer, IEndpoint originalEndpoint, string originalMessageType, OutboundDisruptorEntry data)
        {
            var selfShadows = _selfShadows ?? Enumerable.Empty<ServicePeer>();
            if (selfShadows.Any())
            {
                var message = new ShadowCompletionMessage(messageId, originatingPeer, _peerConfiguration.PeerId, processSuccessful, originalEndpoint, originalMessageType);
                var endpoints = selfShadows.Select(x => x.HandledMessages.Single(y => y.MessageType == typeof(ShadowCompletionMessage)).Endpoint).Distinct();
                foreach (var shadowEndpoint in endpoints)
                {
                    var messageData = CreateMessageWireData(message);

                    var wireMessage = new WireSendingMessage(messageData, shadowEndpoint);
                    data.NetworkSenderData.WireMessages.Add(wireMessage);
                }
            }
        }
        private void SendAcknowledgementShadowMessages(IMessage message, IEnumerable<MessageSubscription> concernedSubscriptions, OutboundDisruptorEntry disruptorData, MessageWireData messageData)
        {
            var completionAcknowledgementMessage = (CompletionAcknowledgementMessage)message;
            if (_messageOptions[completionAcknowledgementMessage.MessageType].ReliabilityLevel == ReliabilityLevel.Persisted)
            {
                SendToSelfShadows(completionAcknowledgementMessage.MessageId,
                                  completionAcknowledgementMessage.ProcessingSuccessful,
                                  disruptorData.MessageTargetHandlerData.TargetPeer,
                                  completionAcknowledgementMessage.Endpoint,
                                  completionAcknowledgementMessage.MessageType,
                                  disruptorData);

                SendShadowMessages(concernedSubscriptions, messageData, disruptorData);
            }
        }