コード例 #1
0
        protected void Send(TransmissionState state, Result result, TResponse baseResponse = null)
        {
            result = result ?? Result.Success;

            try
            {
                string data;
                var    serialize = Result.Success;
                SocketResponsePackage <TResponse, TResponseTypes> response;
                // TODO: Consider other options.
                if (result.Any(i => i.Level >= ResultIssueLevels.Fatal))
                {
                    ErrorOut(result);
                }

                if (IsFailed ||
                    (response = PackResponse(result, baseResponse)) == null ||
                    !(serialize += PayloadSerializer.Serialize(response, out data)) ||
                    !state.Send(data))
                {
                    Send(state, result + serialize);
                }
            }
            catch (Exception e)
            {
                ErrorOut(result + Result.Error(e));
            }
        }
コード例 #2
0
        /// <summary>
        /// This method marshals the RepositoryHolder and transmits it to the remote Microservice.
        /// </summary>
        /// <typeparam Name="KT">The key type.</typeparam>
        /// <typeparam Name="ET">The entity type.</typeparam>
        /// <param name="actionType">The action type.</param>
        /// <param name="rq">The repository holder request.</param>
        /// <param name="routing"></param>
        /// <returns>Returns an async task that will be signalled when the request completes or times out.</returns>
        protected override async Task <RepositoryHolder <KT, ET> > TransmitInternal <KT, ET>(string actionType, RepositoryHolder <KT, ET> rq, ProcessOptions?routing = null)
        {
            StatisticsInternal.ActiveIncrement();

            var payloadRq = TransmissionPayload.Create();

            bool processAsync = rq.Settings?.ProcessAsync ?? false;

            payloadRq.Options = ProcessOptions.RouteInternal;
            var message = payloadRq.Message;

            payloadRq.MaxProcessingTime = rq.Settings?.WaitTime ?? mDefaultRequestTimespan;
            payloadRq.MessageObject     = rq;
            message.ChannelId           = ChannelId;
            message.ChannelPriority     = processAsync ? 0:-1;
            message.MessageType         = mMessageType;
            message.ActionType          = actionType;

            message.ResponseChannelId       = mResponseChannel;
            message.ResponseChannelPriority = -1; //Always internal

            message.Blob = PayloadSerializer.PayloadSerialize(rq);

            return(await TransmitAsync(payloadRq, ProcessResponse <KT, ET>, processAsync : processAsync));
        }
コード例 #3
0
        /// <summary>
        /// This method marshals the RepositoryHolder and transmits it to the remote Microservice.
        /// </summary>
        /// <typeparam Name="KT">The key type.</typeparam>
        /// <typeparam Name="ET">The entity type.</typeparam>
        /// <param name="actionType">The action type.</param>
        /// <param name="rq">The repository holder request.</param>
        /// <param name="routing"></param>
        /// <returns>Returns an async task that will be signalled when the request completes or times out.</returns>
        protected override async Task <RepositoryHolder <KT, ET> > TransmitInternal <KT, ET>(string actionType, RepositoryHolder <KT, ET> rq, ProcessOptions?routing = null, IPrincipal principal = null)
        {
            StatisticsInternal.ActiveIncrement();

            var payloadRq = TransmissionPayload.Create(mPolicy.TransmissionPayloadTraceEnabled);

            // Set the originator key to the correlation id if passed through the rq settings
            if (!string.IsNullOrEmpty(rq.Settings?.CorrelationId))
            {
                payloadRq.Message.ProcessCorrelationKey = rq.Settings.CorrelationId;
            }

            bool processAsync = rq.Settings?.ProcessAsync ?? false;

            payloadRq.Options = ProcessOptions.RouteInternal;
            var message = payloadRq.Message;

            payloadRq.MaxProcessingTime = rq.Settings?.WaitTime ?? mDefaultRequestTimespan;
            payloadRq.MessageObject     = rq;
            message.ChannelId           = ChannelId;
            message.ChannelPriority     = processAsync ? 0:-1;
            message.MessageType         = mMessageType;
            message.ActionType          = actionType;

            message.ResponseChannelId       = mResponseChannel;
            message.ResponseChannelPriority = -1; //Always internal

            message.Blob = PayloadSerializer.PayloadSerialize(rq);

            return(await OutgoingRequestOut(payloadRq, ProcessResponse <KT, ET>, processAsync : processAsync));
        }
コード例 #4
0
        /// <summary>
        /// This method is the default method used to process the returning message response.
        /// </summary>
        /// <typeparam name="RS">The response type.</typeparam>
        /// <param name="rType"></param>
        /// <param name="payloadRs">The incoming response payload.</param>
        /// <param name="processAsync"></param>
        /// <returns>Returns the response wrapper generic object.</returns>
        protected virtual ResponseWrapper <RS> ProcessOutgoingResponse <RS>(TaskStatus rType, TransmissionPayload payloadRs, bool processAsync)
        {
            StatisticsInternal.ActiveDecrement(payloadRs?.Extent ?? TimeSpan.Zero);

            if (processAsync)
            {
                return(new ResponseWrapper <RS>(responseCode: 202, responseMessage: "Accepted"));
            }

            try
            {
                payloadRs?.CompleteSet();

                switch (rType)
                {
                case TaskStatus.RanToCompletion:
                    try
                    {
                        //payload.Message.
                        var response = new ResponseWrapper <RS>(payloadRs);

                        if (payloadRs.Message.Blob.HasObject)
                        {
                            response.Response = (RS)payloadRs.Message.Blob.Object;
                        }
                        else if (payloadRs.Message.Blob != null)
                        {
                            response.Response = PayloadSerializer.PayloadDeserialize <RS>(payloadRs);
                        }

                        return(response);
                    }
                    catch (Exception ex)
                    {
                        StatisticsInternal.ErrorIncrement();
                        return(new ResponseWrapper <RS>(500, ex.Message));
                    }

                case TaskStatus.Canceled:
                    StatisticsInternal.ErrorIncrement();
                    return(new ResponseWrapper <RS>(408, "Time out"));

                case TaskStatus.Faulted:
                    StatisticsInternal.ErrorIncrement();
                    return(new ResponseWrapper <RS>((int)PersistenceResponse.GatewayTimeout504, "Response timeout."));

                default:
                    StatisticsInternal.ErrorIncrement();
                    return(new ResponseWrapper <RS>(500, rType.ToString()));
                }
            }
            catch (Exception ex)
            {
                Collector?.LogException("Error processing response for task status " + rType, ex);
                throw;
            }
        }
コード例 #5
0
        /// <summary>
        /// This method is used to process the returning message response.
        /// </summary>
        /// <typeparam name="KT"></typeparam>
        /// <typeparam name="ET"></typeparam>
        /// <param name="rType"></param>
        /// <param name="payload"></param>
        /// <param name="processAsync"></param>
        /// <returns></returns>
        protected virtual RepositoryHolder <KT, ET> ProcessResponse <KT, ET>(TaskStatus rType, TransmissionPayload payload, bool processAsync)
        {
            StatisticsInternal.ActiveDecrement(payload != null ? payload.Extent : TimeSpan.Zero);

            if (processAsync)
            {
                return(new RepositoryHolder <KT, ET>(responseCode: 202, responseMessage: "Accepted"));
            }

            try
            {
                switch (rType)
                {
                case TaskStatus.RanToCompletion:
                    if (payload.MessageObject != null)
                    {
                        return(payload.MessageObject as RepositoryHolder <KT, ET>);
                    }

                    if (payload.Message.Blob == null)
                    {
                        return(new RepositoryHolder <KT, ET>(responseCode: 500, responseMessage: "Unexpected response (no payload)"));
                    }

                    try
                    {
                        var response = PayloadSerializer.PayloadDeserialize <RepositoryHolder <KT, ET> >(payload);
                        return(response);
                    }
                    catch (Exception ex)
                    {
                        StatisticsInternal.ErrorIncrement();
                        return(new RepositoryHolder <KT, ET>(responseCode: 500, responseMessage: ex.Message));
                    }

                case TaskStatus.Canceled:
                    StatisticsInternal.ErrorIncrement();
                    return(new RepositoryHolder <KT, ET>(responseCode: 408, responseMessage: "Time out"));

                case TaskStatus.Faulted:
                    StatisticsInternal.ErrorIncrement();
                    return(new RepositoryHolder <KT, ET>()
                    {
                        ResponseCode = (int)PersistenceResponse.GatewayTimeout504, ResponseMessage = "Response timeout."
                    });

                default:
                    StatisticsInternal.ErrorIncrement();
                    return(new RepositoryHolder <KT, ET>(responseCode: 500, responseMessage: rType.ToString()));
                }
            }
            catch (Exception ex)
            {
                Logger.LogException("Error processing response for task status " + rType, ex);
                throw;
            }
        }
コード例 #6
0
        private void ActionSync(TransmissionPayload incoming, List <TransmissionPayload> outgoing)
        {
            var blahIn = PayloadSerializer.PayloadDeserialize <Blah>(incoming);
            var rs     = incoming.ToResponse();

            rs.Message.Blob              = PayloadSerializer.PayloadSerialize(blahIn.Message);
            rs.Message.Status            = "204";
            rs.Message.StatusDescription = "Hello";
            outgoing.Add(rs);
        }
コード例 #7
0
 public async Task HandlePublishEvent(RedisChannel channel,
                                      RedisValue value)
 {
     try
     {
         await HandlePublishedMetricsAsync(PayloadSerializer.GetObject(value));
     }
     catch (Exception e)
     {
     }
 }
コード例 #8
0
        public string GetMessageText(Message message)
        {
            StringBuilder sb = new StringBuilder();

            using (TextWriter writer = new StringWriter(sb))
            {
                PayloadSerializer.Serialize(writer, message);
                writer.Flush();;
            }
            return(sb.ToString());
        }
コード例 #9
0
        private async Task ActionAsync(TransmissionPayload incoming, List <TransmissionPayload> outgoing)
        {
            var blahIn = PayloadSerializer.PayloadDeserialize <Blah>(incoming);
            var rs     = incoming.ToResponse();

            rs.Message.Blob.SetObject("Freaky");
            rs.Message.Status            = "204";
            rs.Message.StatusDescription = "Hello";
            outgoing.Add(rs);

            //return Task.FromResult(0);
        }
コード例 #10
0
        /// <summary>
        /// Initializes the service relationships.
        /// </summary>
        protected virtual void Initialise()
        {
            PayloadSerializer.Start();
            ResourceTracker.Start();

            Scheduler.Collector = Collector;
            Scheduler.Start();

            ResourceTracker.Collector      = Collector;
            ResourceTracker.SharedServices = SharedService;
            ResourceTracker.Start();
        }
コード例 #11
0
        /// <summary>
        /// This is the default client create logic.
        /// </summary>
        /// <param name="partition"></param>
        /// <returns>
        /// Returns the client.
        /// </returns>
        protected override UdpClientHolder ClientCreate(SenderPartitionConfig partition)
        {
            var client = base.ClientCreate(partition);

            client.ContentType     = ContentType;
            client.ContentEncoding = ContentEncoding;

            client.Start = () =>
            {
                client.Client = client.ClientCreate();

                client.IsActive = true;
            };

            client.ClientCreate = () =>
            {
                var c = new UdpHelper(Config, UdpHelperMode.Sender);
                c.Start();
                return(c);
            };

            client.ClientClose = () => client.Client.Stop();

            client.MessagePack = (p) =>
            {
                var holder = p.Message.Blob;

                if (holder.ContentType == null)
                {
                    holder.ContentType = ContentType;
                }

                if (holder.ContentEncoding == null)
                {
                    holder.ContentEncoding = ContentEncoding;
                }

                if (!PayloadSerializer.TryPayloadSerialize(holder))
                {
                    throw new ArgumentException("Cannot serialize.");
                }

                if (holder.Blob.Length > UdpMessageMaximumPayloadSize)
                {
                    //throw new
                }

                return(holder);
            };

            return(client);
        }
コード例 #12
0
 /// <summary>
 /// This method is called when an entity of the cache type is updated or deleted.
 /// </summary>
 /// <param name="rq">The request.</param>
 /// <param name="rs">The response.</param>
 /// <returns></returns>
 protected virtual async Task EntityChangeNotification(TransmissionPayload rq, List <TransmissionPayload> rs)
 {
     try
     {
         EntityChangeReference <K> entityChangeReference = PayloadSerializer.PayloadDeserialize <EntityChangeReference <K> >(rq);
         var key = entityChangeReference.Key;
         Remove(key);
     }
     catch (Exception ex)
     {
         Collector?.LogException("Unable to retrieve the entity change reference", ex);
     }
 }
コード例 #13
0
        private async Task ActionAsync(TransmissionPayload incoming, List <TransmissionPayload> outgoing)
        {
            var blahIn = PayloadSerializer.PayloadDeserialize <Blah>(incoming);
            var rs     = incoming.ToResponse();

            rs.Message.Blob = PayloadSerializer.PayloadSerialize(new Blah {
                ContentId = blahIn.ContentId, Message = "Howdy"
            });
            rs.MessageObject             = "Freaky";
            rs.Message.Status            = "204";
            rs.Message.StatusDescription = "Hello";
            outgoing.Add(rs);
        }
コード例 #14
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="CM"></typeparam>
        /// <typeparam name="PM"></typeparam>
        /// <param name="action"></param>
        /// <param name="exceptionAction"></param>
        protected void CommandRegister <CM, PM>(
            Func <PM, TransmissionPayload, List <TransmissionPayload>, Task> action,
            Func <Exception, TransmissionPayload, List <TransmissionPayload>, Task> exceptionAction = null)
            where CM : IMessageContract
        {
            Func <TransmissionPayload, List <TransmissionPayload>, Task> actionReduced = async(m, l) =>
            {
                PM payload = PayloadSerializer.PayloadDeserialize <PM>(m);
                await action(payload, m, l);
            };

            CommandRegister <CM>(actionReduced, exceptionAction);
        }
コード例 #15
0
        /// <summary>
        /// This method marshals the RepositoryHolder and transmits it to the remote Microservice.
        /// </summary>
        /// <typeparam Name="KT">The key type.</typeparam>
        /// <typeparam Name="ET">The entity type.</typeparam>
        /// <param Name="actionType">The action type.</param>
        /// <param Name="rq">The repository holder request.</param>
        /// <returns>Returns an async task that will be signalled when the request completes or times out.</returns>
        protected override async Task <RepositoryHolder <KT, ET> > TransmitInternal <KT, ET>(
            string actionType, RepositoryHolder <KT, ET> rq, ProcessOptions?routing = null, IPrincipal principal = null)
        {
            try
            {
                StatisticsInternal.ActiveIncrement();

                var payload = TransmissionPayload.Create(Policy.TransmissionPayloadTraceEnabled);

                payload.SecurityPrincipal = TransmissionPayload.ConvertToClaimsPrincipal(principal ?? Thread.CurrentPrincipal);

                // Set the process correlation key to the correlation id if passed through the rq settings
                if (!string.IsNullOrEmpty(rq.Settings?.CorrelationId))
                {
                    payload.Message.ProcessCorrelationKey = rq.Settings.CorrelationId;
                }

                bool processAsync = rq.Settings?.ProcessAsync ?? false;

                payload.Message.ChannelPriority = processAsync ? 0 : 1;

                payload.Options = routing ?? RoutingDefault ?? ProcessOptions.RouteExternal;

                payload.Message.Blob = PayloadSerializer.PayloadSerialize(rq);

                payload.Message.ResponseChannelId = ResponseChannelId;

                payload.Message.ResponseChannelId   = ResponseId.Header.ChannelId;
                payload.Message.ResponseMessageType = ResponseId.Header.MessageType;
                payload.Message.ResponseActionType  = ResponseId.Header.ActionType;

                payload.Message.ResponseChannelPriority = payload.Message.ChannelPriority;

                payload.Message.ChannelId   = ChannelId;
                payload.Message.MessageType = EntityType;
                payload.Message.ActionType  = actionType;

                payload.MaxProcessingTime = rq.Settings?.WaitTime ?? mDefaultRequestTimespan;

                return(await OutgoingRequestOut(payload, ProcessResponse <KT, ET>, processAsync));
            }
            catch (Exception ex)
            {
                string key = rq != null && rq.Key != null?rq.Key.ToString() : string.Empty;

                Collector?.LogException($"Error transmitting {actionType}-{key} internally", ex);
                throw;
            }
        }
コード例 #16
0
        /// <summary>
        /// This method marshals the RepositoryHolder and transmits it to the remote Microservice.
        /// </summary>
        /// <typeparam Name="KT">The key type.</typeparam>
        /// <typeparam Name="ET">The entity type.</typeparam>
        /// <param Name="actionType">The action type.</param>
        /// <param Name="rq">The repository holder request.</param>
        /// <returns>Returns an async task that will be signalled when the request completes or times out.</returns>
        protected override async Task <RepositoryHolder <KT, ET> > TransmitInternal <KT, ET>(string actionType, RepositoryHolder <KT, ET> rq, ProcessOptions?routing = null)
        {
            try
            {
                StatisticsInternal.ActiveIncrement();

                var payload = TransmissionPayload.Create();

                // Set the originator key to the correlation id if passed through the rq settings
                if (rq.Settings != null && !string.IsNullOrEmpty(rq.Settings.CorrelationId))
                {
                    payload.Message.OriginatorKey = rq.Settings.CorrelationId;
                }

                bool processAsync = rq.Settings == null ? false : rq.Settings.ProcessAsync;

                payload.Message.ChannelPriority = processAsync ? 0 : 1;

                payload.Options = routing ?? RoutingDefault ?? ProcessOptions.RouteExternal;

                payload.Message.Blob = PayloadSerializer.PayloadSerialize(rq);

                payload.Message.ResponseChannelId       = ResponseChannelId;
                payload.Message.ResponseChannelPriority = payload.Message.ChannelPriority;

                payload.Message.ChannelId   = ChannelId;
                payload.Message.MessageType = EntityType;
                payload.Message.ActionType  = actionType;

                payload.MaxProcessingTime = rq.Settings?.WaitTime ?? mDefaultRequestTimespan;

                return(await TransmitAsync(payload, ProcessResponse <KT, ET>, processAsync));
            }
            catch (Exception ex)
            {
                string key = rq != null && rq.Key != null?rq.Key.ToString() : string.Empty;

                Logger.LogException(string.Format("Error transmitting {0}-{1} internally", actionType, key), ex);
                throw;
            }
        }
コード例 #17
0
        /// <summary>
        /// This override sets the default processing time to the client for incoming messages.
        /// </summary>
        /// <param name="partition">The current partition.</param>
        /// <returns>
        /// Returns the new client.
        /// </returns>
        protected override UdpClientHolder ClientCreate(ListenerPartitionConfig partition)
        {
            var client = base.ClientCreate(partition);

            client.ContentType     = ContentType;
            client.ContentEncoding = ContentEncoding;

            client.ClientCreate = () =>
            {
                var c = new UdpHelper(Config, UdpHelperMode.Listener);
                c.Start();
                return(c);
            };

            client.ClientClose = () => client.Client.Stop();

            client.MessageUnpack = (holder) =>
            {
                if (!PayloadSerializer.TryPayloadDeserialize(holder))
                {
                    holder.SetObject(new UdpHelper.Message {
                        Buffer = holder.Blob, RemoteEndPoint = (IPEndPoint)holder.Metadata
                    });
                }

                var sMessage = new ServiceMessage((client.MappingChannelId ?? client.ChannelId, RequestAddress), ResponseAddress);

                if (ResponseAddress != null)
                {
                    sMessage.ResponseChannelPriority = ResponseAddressPriority;
                }

                sMessage.ChannelPriority = RequestAddressPriority ?? client.Priority;
                sMessage.Blob            = holder;

                return(sMessage);
            };

            return(client);
        }
コード例 #18
0
 public void Init()
 {
     _sut = new PayloadSerializer();
 }
コード例 #19
0
        /// <summary>
        /// This method is used to send requests to the remote command.
        /// </summary>
        /// <typeparam name="RQ">The request type.</typeparam>
        /// <typeparam name="RS">The response type.</typeparam>
        /// <param name="channelId">The header routing information.</param>
        /// <param name="messageType">The header routing information.</param>
        /// <param name="actionType">The header routing information.</param>
        /// <param name="rq">The request object.</param>
        /// <param name="rqSettings">The request settings. Use this to specifically set the timeout parameters.</param>
        /// <param name="routingOptions">The routing options by default this will try internal and then external.</param>
        /// <param name="processResponse"></param>
        /// <param name="fallbackMaxProcessingTime">This is the fallback max processing time used if the timeout
        /// is not set in the request settings.
        /// If this is also null, the max time out will fall back to the policy settings.</param>
        /// <param name="principal">This is the principal that you wish the command to be executed under.
        /// By default this is taken from the calling thread if not passed.</param>
        /// <returns>Returns the async response wrapper.</returns>
        protected internal virtual async Task <ResponseWrapper <RS> > ProcessOutgoing <RQ, RS>(
            string channelId, string messageType, string actionType
            , RQ rq
            , RequestSettings rqSettings    = null
            , ProcessOptions?routingOptions = null
            , Func <TaskStatus, TransmissionPayload, bool, ResponseWrapper <RS> > processResponse = null
            , TimeSpan?fallbackMaxProcessingTime = null
            , IPrincipal principal = null
            )
        {
            if (!Policy.OutgoingRequestsEnabled)
            {
                throw new OutgoingRequestsNotEnabledException();
            }

            TransmissionPayload payload = null;

            try
            {
                StatisticsInternal.ActiveIncrement();

                payload = TransmissionPayload.Create(Policy.TransmissionPayloadTraceEnabled);
                payload.SecurityPrincipal = TransmissionPayload.ConvertToClaimsPrincipal(principal ?? Thread.CurrentPrincipal);

                // Set the process correlation key to the correlation id, if passed through the rq settings
                if (!string.IsNullOrEmpty(rqSettings?.CorrelationId))
                {
                    payload.Message.ProcessCorrelationKey = rqSettings.CorrelationId;
                }

                bool processAsync = rqSettings?.ProcessAsync ?? false;

                payload.Options = routingOptions ?? ProcessOptions.RouteExternal | ProcessOptions.RouteInternal;

                //Set the destination message
                payload.Message.ChannelId       = channelId ?? ChannelId;
                payload.Message.MessageType     = messageType;
                payload.Message.ActionType      = actionType;
                payload.Message.ChannelPriority = processAsync ? 0 : 1;

                //Set the response path
                payload.Message.ResponseChannelId       = ResponseId.Header.ChannelId;
                payload.Message.ResponseMessageType     = ResponseId.Header.MessageType;
                payload.Message.ResponseActionType      = ResponseId.Header.ActionType;
                payload.Message.ResponseChannelPriority = payload.Message.ChannelPriority;

                //Set the payload
                payload.Message.Blob = PayloadSerializer.PayloadSerialize(rq);

                //Set the processing time
                payload.MaxProcessingTime = rqSettings?.WaitTime ?? fallbackMaxProcessingTime ?? Policy.OutgoingRequestMaxProcessingTimeDefault;

                //Transmit
                return(await OutgoingRequestOut(payload, processResponse ?? ProcessOutgoingResponse <RS>, processAsync));
            }
            catch (Exception ex)
            {
                string key = payload?.Id.ToString() ?? string.Empty;
                Collector?.LogException(string.Format("Error transmitting {0}-{1} internally", actionType, key), ex);
                throw;
            }
        }
コード例 #20
0
        /// <summary>
        /// This method registers the specific persistence handler.
        /// </summary>
        /// <typeparam Name="KT">The key type.</typeparam>
        /// <typeparam Name="ET">The entity type.</typeparam>
        /// <param name="actionType">The action type identifier</param>
        /// <param name="action">The action to process the command.</param>
        /// <param name="logEventOnSuccess"></param>
        /// <param name="preaction"></param>
        /// <param name="postaction"></param>
        /// <param name="timeoutcorrect"></param>
        /// <param name="retryOnTimeout"></param>
        /// <param name="channelId"></param>
        /// <param name="entityType"></param>
        protected virtual void PersistenceCommandRegister <KT, ET>(string actionType
                                                                   , Func <PersistenceRequestHolder <KT, ET>, Task> action
                                                                   , bool logEventOnSuccess = false
                                                                   , Func <PersistenceRequestHolder <KT, ET>, Task <bool> > preaction      = null
                                                                   , Func <PersistenceRequestHolder <KT, ET>, Task> postaction             = null
                                                                   , Func <PersistenceRequestHolder <KT, ET>, Task <bool> > timeoutcorrect = null
                                                                   , int?retryOnTimeout = null
                                                                   , string channelId   = null
                                                                   , string entityType  = null
                                                                   )
        {
            Func <TransmissionPayload, List <TransmissionPayload>, Task> actionPayload = async(incoming, outgoing) =>
            {
                var profileHolder = ProfileStart <KT, ET>(incoming, outgoing);

                try
                {
                    var rsMessage = incoming.Message.ToResponse();

                    rsMessage.ChannelId       = incoming.Message.ResponseChannelId;
                    rsMessage.ChannelPriority = incoming.Message.ResponseChannelPriority;
                    rsMessage.MessageType     = incoming.Message.MessageType;
                    rsMessage.ActionType      = "";

                    var rsPayload = new TransmissionPayload(rsMessage);

                    bool hasTimedOut = false;

                    try
                    {
                        RepositoryHolder <KT, ET> rqTemp = incoming.MessageObject as RepositoryHolder <KT, ET>;

                        //Deserialize the incoming payloadRq request
                        if (rqTemp == null)
                        {
                            rqTemp = PayloadSerializer.PayloadDeserialize <RepositoryHolder <KT, ET> >(incoming);
                        }

                        profileHolder.Rq = new PersistenceRepositoryHolder <KT, ET>(rqTemp);

                        if (profileHolder.Rq.Timeout == null)
                        {
                            profileHolder.Rq.Timeout = TimeSpan.FromSeconds(10);
                        }

                        bool preactionFailed = false;

                        try
                        {
                            bool retryExceeded = false;

                            do
                            {
                                int attempt = Environment.TickCount;

                                //Create the payloadRs holder, and discard any previous version.
                                profileHolder.Rs = new PersistenceRepositoryHolder <KT, ET>();

                                if (preaction != null && !(await preaction(profileHolder)))
                                {
                                    preactionFailed = true;
                                    break;
                                }

                                //Call the specific command to process the action, i.e Create, Read, Update, Delete ... etc.
                                await action(profileHolder);

                                //Flag if the request times out at any point.
                                //This may be required later when checking whether the action was actually successful.
                                hasTimedOut |= profileHolder.Rs.IsTimeout;

                                //OK, if this is not a time out then it is successful
                                if (!profileHolder.Rs.IsTimeout && !profileHolder.Rs.ShouldRetry)
                                {
                                    break;
                                }

                                ProfileRetry(profileHolder, attempt);

                                if (profileHolder.Rs.IsTimeout)
                                {
                                    Logger.LogMessage(LoggingLevel.Warning, $"Timeout occured for {EntityType} {actionType} for request:{profileHolder.Rq} with response:{profileHolder.Rs}", "DBTimeout");
                                }

                                profileHolder.Rq.IsRetry = true;
                                //These should not be counted against the limit.
                                if (!profileHolder.Rs.ShouldRetry)
                                {
                                    profileHolder.Rq.Retry++;
                                }

                                profileHolder.Rq.IsTimeout = false;

                                retryExceeded = incoming.Cancel.IsCancellationRequested ||
                                                profileHolder.Rq.Retry > mPolicy.PersistenceRetryPolicy.GetMaximumRetries(incoming);
                            }while (!retryExceeded);

                            //Signal to the underlying comms channel that the message has been processed successfully.
                            incoming.Signal(!retryExceeded);

                            // If we have exceeded the retry limit then Log error
                            if (retryExceeded)
                            {
                                Log(actionType
                                    , profileHolder
                                    , LoggingLevel.Error
                                    , $"Retry limit has been exceeded (cancelled ({incoming.Cancel.IsCancellationRequested})) for {EntityType} {actionType} for {profileHolder.Rq} after {incoming.Message?.FabricDeliveryCount} delivery attempts"
                                    , "DBRetry");

                                profileHolder.result = ResourceRequestResult.RetryExceeded;
                            }
                        }
                        catch (Exception ex)
                        {
                            LogException(actionType, profileHolder, ex);
                            incoming.SignalFail();
                            profileHolder.result = ResourceRequestResult.Exception;
                        }

                        bool logEventSource = !preactionFailed && logEventOnSuccess && profileHolder.Rs.IsSuccess;

                        if (!profileHolder.Rs.IsSuccess && hasTimedOut && timeoutcorrect != null && profileHolder.result != ResourceRequestResult.Exception)
                        {
                            if (await timeoutcorrect(profileHolder))
                            {
                                logEventSource = true;
                                Logger.LogMessage(LoggingLevel.Info
                                                  , string.Format("Recovered timeout sucessfully for {0}-{1} for request:{2} - response:{3}", EntityType, actionType, profileHolder.Rq, profileHolder.Rs)
                                                  , "DBTimeout");
                            }
                            else
                            {
                                Logger.LogMessage(LoggingLevel.Error
                                                  , string.Format("Not recovered timeout for {0}-{1} for request:{2} - response:{3}", EntityType, actionType, profileHolder.Rq, profileHolder.Rs)
                                                  , "DBTimeout");
                            }
                        }

                        if (logEventSource && profileHolder.Rs.ShouldLogEventSource)
                        {
                            await LogEventSource(actionType, profileHolder);
                        }

                        if (!preactionFailed && postaction != null)
                        {
                            await postaction(profileHolder);
                        }

                        //Serialize the payloadRs
                        var reposHolder = profileHolder.Rs.ToRepositoryHolder();

                        rsPayload.MessageObject = reposHolder;
                        rsPayload.Message.Blob  = PayloadSerializer.PayloadSerialize(reposHolder);

                        rsPayload.Message.Status = "200";

                        if (!profileHolder.result.HasValue)
                        {
                            profileHolder.result = ResourceRequestResult.Success;
                        }
                    }
                    catch (Exception ex)
                    {
                        incoming.SignalFail();
                        rsPayload.Message.Status            = "500";
                        rsPayload.Message.StatusDescription = ex.Message;
                        Logger.LogException($"Error processing message (was cancelled({incoming.Cancel.IsCancellationRequested}))-{EntityType}-{actionType}-{profileHolder.Rq}", ex);
                        profileHolder.result = ResourceRequestResult.Exception;
                    }

                    // check whether we need to send a response message. If this is async and AsyncResponse is not set to true,
                    // then by default we do not send a response message to cut down on unnecessary traffic.
                    if (profileHolder.Rq == null || profileHolder.Rq.Settings == null || !profileHolder.Rq.Settings.ProcessAsync)
                    {
                        outgoing.Add(rsPayload);
                    }
                }
                finally
                {
                    ProfileEnd(profileHolder);
                }
            };

            if (channelId == null)
            {
                channelId = ChannelId ?? string.Empty;
            }

            if (entityType == null)
            {
                entityType = EntityType;
            }

            CommandRegister(
                channelId.ToLowerInvariant()
                , entityType.ToLowerInvariant()
                , actionType.ToLowerInvariant()
                , actionPayload);
        }
コード例 #21
0
 protected virtual Result BuildRequest(string message, out TRequest request)
 {
     return(PayloadSerializer.Deserialize(message, out request));
 }