/// <summary>
        /// Processes the exception.
        /// </summary>
        /// <param name="ex">The exception raised.</param>
        /// <param name="rq">The incoming request.</param>
        /// <param name="responses">The responses.</param>
        protected virtual Task ProcessRequestException(Exception ex, TransmissionPayload rq, List <TransmissionPayload> responses)
        {
            if (mPolicy.OnProcessRequestExceptionLog)
            {
                Collector?.LogException($"{FriendlyName}/ProcessRequest unhandled exception: {rq.Message.ToKey()}", ex);
            }

            switch (mPolicy.OnProcessRequestException)
            {
            case ProcessRequestExceptionBehaviour.DoNothing:
                break;

            case ProcessRequestExceptionBehaviour.SignalSuccessAndSend500ErrorResponse:
                rq.SignalSuccess();
                var rs = rq.ToResponse();
                rs.Message.Status            = "500";
                rs.Message.StatusDescription = ex.Message;
                responses.Add(rs);
                break;

            case ProcessRequestExceptionBehaviour.SignalFailAndDoNothing:
                rq.SignalFail();
                break;

            default:
                throw ex;
            }

            return(Task.FromResult(0));
        }
        /// <summary>
        /// This method is called to process an incoming payload.
        /// </summary>
        /// <param name="rq">The message to process.</param>
        /// <param name="responses">The return path for the message.</param>
        public virtual async Task ProcessRequest(TransmissionPayload rq, List <TransmissionPayload> responses)
        {
            var header = rq.Message.ToServiceMessageHeader();
            H   handler;

            if (!SupportedResolve(header, out handler))
            {
                var ex = new CommandNotSupportedException(rq.Id, header, GetType());
                FireAndDecorateEventArgs(OnRequestUnresolved, () => new ProcessRequestEventArgs(rq, ex));
                throw ex;
            }

            FireAndDecorateEventArgs(OnRequest, () => new ProcessRequestEventArgs(rq));

            int start = StatisticsInternal.ActiveIncrement();

            try
            {
                //Call the registered command. This should not throw an exception if a hander has been registered.
                await handler.Execute(rq, responses);
            }
            catch (Exception ex)
            {
                StatisticsInternal.ErrorIncrement();
                FireAndDecorateEventArgs(OnRequestUnhandledException, () => new ProcessRequestEventArgs(rq, ex));
                //Handler has not caught the exception, so we default to the default policy behaviour.
                await ProcessRequestException(ex, rq, responses);
            }
            finally
            {
                StatisticsInternal.ActiveDecrement(start);
            }
        }
Exemple #3
0
        /// <summary>
        /// This method resolves the client and processes the message.
        /// </summary>
        /// <param name="payload">The payload to transmit.</param>
        public virtual async Task SenderTransmit(TransmissionPayload payload)
        {
            int?start  = null;
            H   client = null;

            try
            {
                client = ClientResolve(payload.Message.ChannelPriority);

                start = client.StatisticsInternal.ActiveIncrement();

                await client.Transmit(payload);

                payload.TraceWrite($"Sent: {client.Name}", "MessagingSenderBase/ProcessMessage");
            }
            catch (Exception ex)
            {
                LogExceptionLocation("ProcessMessage (Unhandled)", ex);
                //OK, not sure what happened here, so we need to throw the exception.
                payload.TraceWrite($"Exception: {ex.Message}", "MessagingSenderBase/ProcessMessage");
                if (client != null)
                {
                    client.StatisticsInternal.ErrorIncrement();
                }
                throw;
            }
            finally
            {
                if (client != null && start.HasValue)
                {
                    client.StatisticsInternal.ActiveDecrement(start.Value);
                }
            }
        }
Exemple #4
0
 private void Sender_TransmitBroadcast(TransmissionPayload e, long count)
 {
     for (int c = 0; c < mListeners.Count; c++)
     {
         mListeners[c].Inject(PayloadCopy(e));
     }
 }
Exemple #5
0
        /// <summary>
        /// This method is called to process an incoming payload.
        /// </summary>
        /// <param name="rq">The message to process.</param>
        /// <param name="responses">The return path for the message.</param>
        public virtual async Task ProcessRequest(TransmissionPayload rq, List <TransmissionPayload> responses)
        {
            int start = StatisticsInternal.ActiveIncrement();

            try
            {
                var header = rq.Message.ToServiceMessageHeader();

                H handler;
                if (!SupportedResolve(header, out handler))
                {
                    OnRequestUnresolved?.Invoke(this, rq);
                    throw new CommandNotSupportedException(rq.Id, header, GetType());
                }

                OnRequest?.Invoke(this, rq);
                //Call the registered command.
                await handler.Execute(rq, responses);
            }
            catch (Exception)
            {
                StatisticsInternal.ErrorIncrement();
                //throw any errors back out to the dispatcher.
                throw;
            }
            finally
            {
                StatisticsInternal.ActiveDecrement(start);
            }
        }
        /// <summary>
        /// This method packs the ServiceMessage in to the BrokeredMessage format
        /// for communication through the Azure Service Bus.
        /// </summary>
        /// <param name="payload">The payload to convert.</param>
        /// <returns>Returns a converted BrokeredMessage from transmission.</returns>
        public BrokeredMessage PackEventSource(TransmissionPayload payload)
        {
            var entry = payload.MessageObject as EventSourceEntryBase;

            byte[] blob;

            using (var stream = new MemoryStream())
                using (var streamWriter = new StreamWriter(stream))
                    using (var textWriter = new JsonTextWriter(streamWriter))
                    {
                        mJsonSerializer.Serialize(textWriter, payload.MessageObject);
                        streamWriter.Flush();
                        stream.Position = 0;
                        blob            = stream.ToArray();
                    }

            BrokeredMessage bMessage = new BrokeredMessage(blob);

            bMessage.Properties.Add("BatchId", entry.BatchId);
            bMessage.Properties.Add("CorrelationId", entry.CorrelationId);
            bMessage.Properties.Add("Key", entry.Key);
            bMessage.Properties.Add("EntityType", entry.EntityType);
            bMessage.Properties.Add("EntityVersion", entry.EntityVersion);
            bMessage.Properties.Add("UTCTimeStamp", entry.UTCTimeStamp);

            bMessage.Properties.Add("OriginatorId", OriginatorId);

            return(bMessage);
        }
 /// <summary>
 /// This is the default constructor.
 /// </summary>
 /// <param name="rq">The incoming request.</param>
 /// <param name="rsCol">The outgoing response collection.</param>
 /// <param name="serializer">The serialization container.</param>
 /// <param name="collector">The data collector.</param>
 /// <param name="sharedServices">The shared service context.</param>
 /// <param name="originatorId">This is the Microservice identifiers.</param>
 /// <param name="outgoingRequest">This is the outgoing request initiator.</param>
 public CommandMethodRequestContext(TransmissionPayload rq, List <TransmissionPayload> rsCol
                                    , IPayloadSerializationContainer serializer
                                    , IDataCollection collector
                                    , ISharedService sharedServices
                                    , MicroserviceId originatorId
                                    , ICommandOutgoing outgoingRequest) : base(rq, rsCol, serializer, collector, sharedServices, originatorId, outgoingRequest)
 {
 }
 public OutgoingRequestTracker(string id, TransmissionPayload payload, TimeSpan ttl, int?start = null)
 {
     Id      = id;
     Payload = payload;
     Tcs     = new TaskCompletionSource <TransmissionPayload>();
     Start   = start ?? Environment.TickCount;
     MaxTTL  = ttl;
 }
Exemple #9
0
        private void Sender_TransmitRoundRobin(TransmissionPayload e, long count)
        {
            var listeners = mActiveListeners;

            int position = (int)(count % listeners.Length);

            Sender_Transmit(listeners[position], e);
        }
        /// <summary>
        /// This extension method is used to set the response for an inline message.
        /// </summary>
        /// <param name="c">The incoming context.</param>
        /// <param name="status">The response status.</param>
        /// <param name="description">The optional response description</param>
        public static void ResponseSet(this CommandMethodInlineContext c, int status, string description = null)
        {
            TransmissionPayload ars = c.Request.ToResponse();

            ars.Message.StatusSet(status, description);

            c.Responses.Add(ars);
        }
Exemple #11
0
 /// <summary>
 /// This is the default constructor.
 /// </summary>
 /// <param name="rq">The incoming request.</param>
 /// <param name="rsCol">The outgoing response collection.</param>
 /// <param name="serializer">The serialization container.</param>
 /// <param name="collector">The data collector.</param>
 /// <param name="sharedServices">The shared service context.</param>
 /// <param name="originatorId">This is the Microservice identifiers.</param>
 public CommandMethodInlineContext(TransmissionPayload rq, List <TransmissionPayload> rsCol
                                   , IPayloadSerializationContainer serializer
                                   , IDataCollection collector
                                   , ISharedService sharedServices
                                   , MicroserviceId originatorId) : base(serializer, collector, sharedServices, originatorId)
 {
     Request   = rq;
     Responses = rsCol;
 }
        /// <summary>
        /// This method injects a service message in to the execution path and bypasses the listener infrastructure.
        /// </summary>
        /// <param name="message">The service message.</param>
        /// <param name="options">The process options.</param>
        /// <param name="release">The release action which is called when the payload has been executed.</param>
        /// <param name="isDeadLetterMessage">A flag indicating whether the message is a deadletter replay. These messages may be treated differently
        /// by the receiving commands.</param>
        public void Process(ServiceMessage message
                            , ProcessOptions options      = ProcessOptions.RouteExternal | ProcessOptions.RouteInternal
                            , Action <bool, Guid> release = null
                            , bool isDeadLetterMessage    = false)
        {
            var payload = new TransmissionPayload(message, release: release, options: options, isDeadLetterMessage: isDeadLetterMessage);

            Process(payload);
        }
Exemple #13
0
        /// <summary>
        /// This method seperates the payloads so that they are different objects.
        /// </summary>
        /// <param name="inPayload">The incoming payload.</param>
        /// <returns>Returns a new payload.</returns>
        private TransmissionPayload PayloadCopy(TransmissionPayload inPayload)
        {
            //First clone the service message.
            byte[] data = mSerializer.Serialize(inPayload.Message);

            ServiceMessage clone = mSerializer.Deserialize <ServiceMessage>(data);

            return(new TransmissionPayload(clone));
        }
Exemple #14
0
        protected virtual TimeSpan DefaultDelayBetweenRetries(TransmissionPayload transmissionPayload, int i)
        {
            if (transmissionPayload != null && transmissionPayload.Message != null && transmissionPayload.Message.ChannelPriority == 0)
            {
                return(TimeSpan.FromMilliseconds(i * 10));
            }

            return(TimeSpan.FromSeconds(i));
        }
        /// <summary>
        /// This method sends a message to the underlying dispatcher and tracks its progress.
        /// </summary>
        /// <typeparam name="K"></typeparam>
        /// <param name="payloadRq">The payload to process.</param>
        /// <param name="processResponse"></param>
        /// <param name="processAsync">Specifies whether the process in async in which case it is
        /// returned immediately without waiting for the payload to be processed.</param>
        /// <returns>The task with a payload of type K</returns>
        protected async Task <K> OutgoingRequestOut <K>(TransmissionPayload payloadRq,
                                                        Func <TaskStatus, TransmissionPayload, bool, K> processResponse,
                                                        bool processAsync = false)
        {
            ValidateServiceStarted();

            if (payloadRq == null)
            {
                throw new ArgumentNullException("payloadRequest has not been set.");
            }
            if (processResponse == null)
            {
                throw new ArgumentNullException("processPayload has not been set.");
            }

            //Create and register the request holder.
            var tracker = new OutgoingRequestTracker(payloadRq, payloadRq.MaxProcessingTime ?? Policy.OutgoingRequestMaxProcessingTimeDefault);

            //Add the outgoing holder to the collection
            if (!mOutgoingRequests.TryAdd(tracker.Id, tracker))
            {
                var errorStr = $"OutgoingRequestTransmit: Duplicate key {tracker.Id}";

                Collector?.LogMessage(LoggingLevel.Error, errorStr, "RqDuplicate");

                throw new OutgoingRequestTransmitException(errorStr);
            }

            //Raise the event.
            FireAndDecorateEventArgs(OnOutgoingRequest, () => new OutgoingRequestEventArgs(tracker));

            //Submit the payload for processing to the task manager
            TaskManager(this, tracker.Id, tracker.Payload);

            //OK, this is a sync process, let's wait until it responds or times out.
            TransmissionPayload payloadRs = null;

            //This has not been marked async so hold the current task until completion.
            if (!processAsync)
            {
                try
                {
                    if (UseASPNETThreadModel)
                    {
                        payloadRs = Task.Run(async() => await tracker.Tcs.Task).Result;
                    }
                    else
                    {
                        payloadRs = await tracker.Tcs.Task;
                    }
                }
                catch (Exception) { }
            }

            return(processResponse(tracker.Tcs.Task.Status, payloadRs, processAsync));
        }
Exemple #16
0
        /// <summary>
        /// This method separates the payloads so that they are different objects.
        /// </summary>
        /// <param name="inPayload">The incoming payload.</param>
        /// <param name="signal">The optional signal action.</param>
        /// <param name="traceEnabled">Specifies whether trace is enabled. If omitted or set to null, the value inherits from the incoming payload.</param>
        /// <returns>Returns a new cloned payload.</returns>
        public static TransmissionPayload Clone(this TransmissionPayload inPayload, Action <bool, Guid> signal, bool?traceEnabled = null)
        {
            traceEnabled = traceEnabled ?? inPayload.TraceEnabled;
            //First clone the service message.
            var cloned = new TransmissionPayload(inPayload.Message.Clone(), release: signal, traceEnabled: traceEnabled.Value);

            cloned.TraceWrite("Cloned", "ManualCommunicationBridgeAgent/PayloadCopy");

            return(cloned);
        }
Exemple #17
0
        /// <summary>
        /// Purges any remaining messages when the service shuts down.
        /// </summary>
        public void Purge()
        {
            TransmissionPayload payload = null;

            while (mPending?.TryDequeue(out payload) ?? false)
            {
                payload.TraceWrite("Purged", "ManualChannelClientHolder/Purge");
                payload.SignalFail();
            }
        }
        /// <summary>
        /// This method validates the payload with the security container.
        /// </summary>
        /// <param name="payload">The incoming payload.</param>
        protected virtual void PayloadOutgoingSecurity(TransmissionPayload payload)
        {
            //Try and resolve the channel.
            Channel channel = null;

            TryGet(payload.Message.ChannelId, ChannelDirection.Outgoing, out channel);

            //Secure the outgoing payload.
            Security.Secure(channel, payload);
        }
        /// <summary>
        /// This method validates the payload with the security container.
        /// </summary>
        /// <param name="payload">The incoming payload.</param>
        protected virtual void PayloadIncomingSecurity(TransmissionPayload payload)
        {
            //Try and resolve the channel.
            Channel channel = null;

            TryGet(payload.Message.ChannelId, ChannelDirection.Incoming, out channel);

            //Decrypt and verify the incoming message.
            Security.Verify(channel, payload);
        }
 /// <summary>
 /// This is the default constructor.
 /// </summary>
 /// <param name="rq">The incoming request.</param>
 /// <param name="rsCol">The outgoing response collection.</param>
 /// <param name="serviceHandlers">The service handlers container.</param>
 /// <param name="collector">The data collector.</param>
 /// <param name="sharedServices">The shared service context.</param>
 /// <param name="originatorId">This is the Microservice identifiers.</param>
 /// <param name="outgoingRequest">This is the outgoing request initiator.</param>
 public CommandRequestContextBase(TransmissionPayload rq, List <TransmissionPayload> rsCol
                                  , IServiceHandlers serviceHandlers
                                  , IDataCollection collector
                                  , ISharedService sharedServices
                                  , MicroserviceId originatorId
                                  , O outgoingRequest) : base(serviceHandlers, collector, sharedServices, originatorId, outgoingRequest)
 {
     Request   = rq;
     Responses = rsCol;
 }
Exemple #21
0
        protected virtual int DefaultMaximumRetries(TransmissionPayload transmissionPayload)
        {
            // Channel 0 async processing should keep retrying
            if (transmissionPayload != null && transmissionPayload.Message != null && transmissionPayload.Message.ChannelPriority == 0)
            {
                return(500);
            }

            return(5);
        }
Exemple #22
0
        /// <summary>
        /// This method marshalls the incoming requests from the Initiators.
        /// </summary>
        /// <param name="caller">The caller.</param>
        /// <param name="message">The message to process.</param>
        public virtual R ProcessMessage(IService caller, TransmissionPayload payload)
        {
            //Create and register the request holder.
            var holder = HolderCreate(caller, payload);

            Register(holder);

            ProcessMessageInternal(holder);

            return(holder);
        }
Exemple #23
0
 /// <summary>
 /// This method is called when a command throws an unhanlded exception when processing the request
 /// </summary>
 /// <param name="payload">The request payload.</param>
 /// <param name="pex">The unhandled exception.</param>
 internal virtual void OnProcessRequestError(TransmissionPayload payload, Exception pex)
 {
     try
     {
         ProcessRequestError?.Invoke(this, new ProcessRequestErrorEventArgs(payload, pex));
     }
     catch (Exception ex)
     {
         mDataCollection?.LogException("ProcessRequestError event / external exception thrown on event", ex);
     }
 }
        /// <summary>
        /// This method validates the payload with the security container.
        /// </summary>
        /// <param name="payload">The incoming payload.</param>
        protected virtual void PayloadPack(TransmissionPayload payload)
        {
            //Try and resolve the channel.
            Channel channel = null;

            TryGet(payload.Message.ChannelId, ChannelDirection.Outgoing, out channel);

            //Secure the outgoing payload.
            Secure(channel, payload);
            payload.TraceWrite("Secured", "CommunicationContainer/PayloadOutgoingSecurity");
        }
Exemple #25
0
        /// <summary>
        /// This method formats the key used to hold the priority processes.
        /// </summary>
        /// <param name="caller">The calling object.</param>
        /// <returns>Returns a formatted string containing both parts.</returns>
        protected virtual string Key(IService caller, TransmissionPayload payload)
        {
            if (mKeyMaker != null)
            {
                return(mKeyMaker(caller, payload));
            }

            string type = caller == null ? "" : caller.GetType().Name;

            return(string.Format("{0}|{1}", type, Guid.NewGuid().ToString("N")).ToLowerInvariant());
        }
        /// <summary>
        /// This method injects a service message in to the execution path and bypasses the listener infrastructure.
        /// </summary>
        /// <param name="dispatcher">The Microservice dispatcher.</param>
        /// <param name="message">The service message.</param>
        /// <param name="options">The process options.</param>
        /// <param name="release">The release action which is called when the payload has been executed by the receiving commands.</param>
        public static void Process(this IMicroserviceDispatch dispatcher
                                   , ServiceMessage message
                                   , ProcessOptions options      = ProcessOptions.RouteExternal | ProcessOptions.RouteInternal
                                   , Action <bool, Guid> release = null)
        {
            var payload = new TransmissionPayload(message
                                                  , release: release
                                                  , options: options);

            dispatcher.Process(payload);
        }
 private void ProcessInvoke(TransmissionPayload payload)
 {
     try
     {
         OnProcess?.Invoke(this, payload);
     }
     catch (Exception ex)
     {
         Collector?.LogException("ManualChannelSender/ProcessInvoke", ex);
     }
 }
        /// <summary>
        /// This method validates the payload with the security container.
        /// </summary>
        /// <param name="payload">The incoming payload.</param>
        protected virtual void PayloadUnpack(TransmissionPayload payload)
        {
            //Try and resolve the channel.
            Channel channel = null;

            TryGet(payload.Message.ChannelId, ChannelDirection.Incoming, out channel);

            //Decrypt and verify the incoming message.
            Verify(channel, payload);
            payload.TraceWrite("Verified", "CommunicationContainer/PayloadIncomingSecurity");
        }
        public PersistenceRequestHolder(Guid profileId, TransmissionPayload prq, List <TransmissionPayload> prs)
        {
            this.ProfileId = profileId;
            this.Prq       = prq;
            this.Prs       = prs;

            Start = Environment.TickCount;

            result = null;
            Rq     = null;
            Rs     = null;
        }
Exemple #30
0
        /// <summary>
        /// This message resolves the specific handler that can process the incoming message.
        /// </summary>
        /// <param name="payload">The incoming message payload.</param>
        /// <returns>Returns the supported handlers or null.</returns>
        protected virtual List <ISender> MessageSenderResolve(TransmissionPayload payload)
        {
            var message = payload.Message;

            string         channelId = message.ChannelId;
            List <ISender> newMap    = mSenders.Where(h => h.SupportsChannel(channelId)).ToList();

            //Make sure that the handler is queueAdded as a null value to stop further resolution attempts
            mMessageSenderMap.AddOrUpdate(channelId, newMap, (k, u) => newMap.Count == 0 ? null : newMap);

            return(newMap);
        }