/// <summary> /// This method processes an individual payload returned from a client. /// </summary> /// <param name="clientId">The originating client.</param> /// <param name="payload">The payload.</param> private void PayloadSubmit(Guid clientId, TransmissionPayload payload) { try { payload.TraceConfigure(mPolicy.TransmissionPayloadTraceEnabled); payload.TraceWrite("Incoming", "CommunicationContainer/PayloadSubmit"); //Ensure the priority cannot spoof the internal priority of -1 if (payload.Message.ChannelPriority < 0) { payload.Message.ChannelPriority = 0; } mClientCollection.QueueTimeLog(clientId, payload.Message.EnqueuedTimeUTC); //Verify the incoming payload with the security container. PayloadIncomingSecurity(payload); //Do we need to redirect the payload based on the redirect/rewrite rules. PayloadIncomingRedirectCheck(payload); //Create the tracker to process the incoming TaskTracker tracker = TaskManager.TrackerCreateFromPayload(payload, payload.Source); //Set the function that executes when the payload completes. tracker.ExecuteComplete = (tr, failed, ex) => { var contextPayload = tr.ToTransmissionPayload(); try { mClientCollection.ActiveDecrement(clientId, tr.TickCount); if (failed) { mClientCollection.ErrorIncrement(clientId); } contextPayload.Signal(!failed); contextPayload.TraceWrite(failed?"Failed":"Success", "CommunicationContainer/PayloadSubmit -> ExecuteComplete"); } catch (Exception exin) { Collector?.LogException($"Payload completion error-{payload} after {(tr.Context as TransmissionPayload)?.Message?.FabricDeliveryCount} delivery attempts", exin); contextPayload.TraceWrite($"Exception: {ex.Message}", "CommunicationContainer/PayloadSubmit -> ExecuteComplete"); } }; //Submit the tracker to the task manager. payload.TraceWrite("Outgoing", "CommunicationContainer/PayloadSubmit"); TaskSubmit(tracker); } catch (Exception ex) { Collector?.LogException($"ProcessClientPayload: unhandled error {payload.Source}/{payload.Message.CorrelationKey}-{payload} after {payload.Message?.FabricDeliveryCount} delivery attempts", ex); payload.TraceWrite($"Exception: {ex.Message}", "CommunicationContainer/PayloadSubmit"); payload.SignalFail(); } }
/// <summary> /// This method transmits the messages to the relevant senders. /// </summary> /// <param name="payload">The payload messages to externalOnly</param> public virtual async Task <bool> Send(TransmissionPayload payload) { payload.TraceConfigure(mPolicy.TransmissionPayloadTraceEnabled); payload.TraceWrite("Outgoing", "CommunicationContainer/Send"); try { //Set outgoing routing information to lower case. This is important as messaging protocols such as //Service Bus can be case sensitive when running subscription filters. if (mPolicy.ServiceMessageHeaderConvertToLowercase) { payload.Message.ConvertMessageHeadersToLowercase(); } Channel channel = PayloadOutgoingRedirectChecks(payload); PayloadOutgoingSecurity(payload); //No, we want to send the message externally. List <ISender> messageSenders = null; //Get the supported message handler if (channel != null && !mMessageSenderMap.TryGetValue(channel.Id, out messageSenders)) { messageSenders = MessageSenderResolve(payload); } //If there are no supported senders for the particular channelId then throw an exception if (messageSenders == null || messageSenders.Count == 0) { Collector?.LogMessage(LoggingLevel.Warning, string.Format("Unable to resolve sender for message {0}", payload != null ? payload.Message : null), "Communication"); payload.TraceWrite("Senders Unresolved", "CommunicationContainer/Send"); return(false); } //Set the outgoing originator if not set. if (string.IsNullOrEmpty(payload.Message.OriginatorServiceId)) { payload.Message.OriginatorServiceId = OriginatorId.ExternalServiceId; } //Send the message to the supported senders. await Task.WhenAll(messageSenders.Select(s => s.ProcessMessage(payload))); } catch (Exception ex) { Collector?.LogException(string.Format("Unable to send message {0}", payload != null ? payload.Message : null), ex); payload.TraceWrite($"Exception: {ex.Message}", "CommunicationContainer/Send"); return(false); } return(true); }