示例#1
0
        /// <summary>
        /// Remove a message from a Q after it has been processed, with success or failure
        /// message contains the owning Q to go to
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public bool RemoveFromQ(IFatpipeMessage message)
        {
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }

            bool result = true;

            try
            {
                this.fpmDal.RemoveMessageFromQueue(message);
            }
            catch (Exception exception)
            {
                LoggerFactory.Logger.Error("FatpipeManager.RemoveFromQueue", EventId.BizpipeRemoveFromQueue,
                                           "Failed to delete message (Id: {0}, PopReceipt: {1}) from queue {2}. Error: {3}",
                                           message.Header.QueueMessageId,
                                           message.Header.QueueMessagePopReceipt,
                                           message.Header.QueueName,
                                           exception.ToString());
                result = false;
            }

            return(result);
        }
        public bool SaveSuspendedMessage(IFatpipeMessage message)
        {
            string location = "FpmDal->SaveSuspendedMessage";
            bool   result   = true;
            SuspendedMessageEntity suspendedMessage = null;

            //TODO remove the return statement
            // don't want any message to be suspended
            return(true);

            try
            {
                Stopwatch watch = Stopwatch.StartNew();
                suspendedMessage           = new SuspendedMessageEntity(message.Header.TenantIdentifier, message.Header.Identifier);
                suspendedMessage.Timestamp = DateTime.UtcNow;
                suspendedMessage.SuspendedMessageBlobReference = message.Header.Identifier;
                if (message.Status != null)
                {
                    suspendedMessage.ErrorMessage = string.Format(CultureInfo.InvariantCulture,
                                                                  "{0}. Message suspended after {1} retries. Error: {2}",
                                                                  message.Status.ProcessingResult,
                                                                  message.Status.NumberOfRetryAttempts,
                                                                  message.Status.ErrorDescription);
                }
                IOutboundFatpipeMessage outboundMessage = message as IOutboundFatpipeMessage;
                if (outboundMessage != null)
                {
                    if (outboundMessage.RoutingInfo != null)
                    {
                        suspendedMessage.PartnerIdentifier = outboundMessage.RoutingInfo.PartnerId;
                    }
                }

                this.suspendedTableServiceContext.AddObject(MaargConfiguration.Instance[MaargConfiguration.SuspendedMessageTableName], suspendedMessage);

                //save to suspended table and blob
                DataServiceResponse response = this.suspendedTableServiceContext.SaveChangesWithRetries();
                // The entry in the Q is the message blob name
                using (Stream stream = BizpipeMesssageStreaming.WriteBizpipeMessageToStream(message))
                {
                    CloudBlob blob = this.suspendedContainer.GetBlobReference(suspendedMessage.SuspendedMessageBlobReference);
                    blob.UploadFromStream(stream);
                }

                watch.Stop();
                LoggerFactory.Logger.Debug(location,
                                           "Message {0} saved to suspended queue in {1} ms.",
                                           message.Header.Identifier,
                                           watch.ElapsedMilliseconds);
            }
            catch (Exception exception)
            {
                LoggerFactory.Logger.Error(location, EventId.BizpipeSaveSuspendMessage
                                           , "Exception encountered during suspended message operation: {0}."
                                           , exception.ToString());
                result = false;
            }

            return(result);
        }
        public IFatpipeMessage GetSuspendedMessage(string messageIdentifier)
        {
            string                 location         = "FpmDal->GetSuspendedMessage";
            IFatpipeMessage        result           = null;
            SuspendedMessageEntity suspendedMessage = null;

            try
            {
                Stopwatch watch = Stopwatch.StartNew();

                suspendedMessage =
                    (from e in this.suspendedTableServiceContext.CreateQuery <SuspendedMessageEntity>(MaargConfiguration.Instance[MaargConfiguration.SuspendedMessageTableName])
                     where e.RowKey == messageIdentifier
                     select e).FirstOrDefault();

                if (suspendedMessage != null)
                {
                    IFatpipeMessage message = null;
                    CloudBlob       blob    = this.suspendedContainer.GetBlobReference(suspendedMessage.SuspendedMessageBlobReference);
                    using (MemoryStream stream = new MemoryStream())
                    {
                        blob.DownloadToStream(stream);
                        stream.Position = 0;
                        message         = BizpipeMesssageStreaming.CreateBizpipeMessageFromStream(stream, this.fpm);
                    }

                    if (!string.IsNullOrEmpty(suspendedMessage.PartnerIdentifier))
                    {
                        IOutboundFatpipeMessage outboundMessage = this.fpm.CreateNewOutboundMessage();
                        outboundMessage.Header                    = message.Header;
                        outboundMessage.Body                      = message.Body;
                        outboundMessage.Status                    = message.Status;
                        outboundMessage.RoutingInfo               = new RoutingInfo();
                        outboundMessage.RoutingInfo.PartnerId     = suspendedMessage.PartnerIdentifier;
                        outboundMessage.RoutingInfo.TransportType = TransportType.Suspend;

                        result = outboundMessage;
                    }
                    else
                    {
                        result = message;
                    }
                }

                watch.Stop();
                LoggerFactory.Logger.Debug(location,
                                           "Message {0} retrieved from suspended queue in {1} ms.",
                                           messageIdentifier,
                                           watch.ElapsedMilliseconds);
            }
            catch (Exception exception)
            {
                LoggerFactory.Logger.Error(location, EventId.BizpipeGetSuspendMessage
                                           , "Error getting the suspended message {0}: {1}."
                                           , messageIdentifier
                                           , exception.ToString());
            }

            return(result);
        }
示例#4
0
        /// <summary>
        /// Used by OutboundTransportManager
        ///
        /// 1. DeQ bunch of messages from OutboundQueue
        /// 2. Transport each of them
        /// 3. RemoveFromQ each of them or suspend them as appropriate
        /// </summary>
        /// <param name="count">Number of messages to DeQ</param>
        /// <returns></returns>
        public List <IOutboundFatpipeMessage> DeQFromOutgoingQ(int count)
        {
            int             iter = 0;
            IFatpipeMessage msg  = null;
            List <IOutboundFatpipeMessage> msgList = new List <IOutboundFatpipeMessage>();

            while (iter < count)
            {
                msg = fpmDal.Dequeue(Constants.QueueType.OUTBOUND);
                if (msg == null)
                {
                    break;
                }

                IOutboundFatpipeMessage message = msg as IOutboundFatpipeMessage;
                string partnerId;
                bool   flag = msg.Header.Context.TryGetValue("PartnerId", out partnerId);
                if (flag)
                {
                    RoutingInfo routingInfo = new RoutingInfo(partnerId, TransportType.None);
                    flag = msg.Header.Context.TryGetValue("TransportType", out partnerId);
                    routingInfo.TransportType = (TransportType)Enum.Parse(typeof(TransportType), partnerId, true);
                    message.RoutingInfo       = routingInfo;
                }

                msgList.Add(message);
                iter++;
            }

            return(msgList);
        }
示例#5
0
        public IFatpipeMessage Clone(Stream bodyStream)
        {
            IFatpipeMessage msg = this.fpm.CreateNewMessage();

            msg.Body.Body = bodyStream;
            return(msg);
        }
        public IFatpipeMessage Dequeue(Constants.QueueType type)
        {
            string          location       = "FpmDal->Dequeue";
            IFatpipeMessage fatpipeMessage = null;

            bool               inbound   = (type == Constants.QueueType.INBOUND);
            CloudQueue         queue     = inbound ? this.incomingQ : this.outgoingQ;
            CloudBlobContainer container = inbound ? this.inContainer : this.outContainer;

            try
            {
                Stopwatch         watch = Stopwatch.StartNew();
                CloudQueueMessage entry = queue.GetMessage(this.visibilityTimeout);
                if (entry != null)
                {
                    watch.Stop();
                    LoggerFactory.Logger.Info(location + (inbound ? "->B2BEngineReadingFromIncomingQ" : "OutboundTransportReadingFromOutgoingQ"),
                                              "timeInMs={0}, entry={1}",
                                              watch.ElapsedMilliseconds, entry.AsString);

                    byte[]       buffer          = null;
                    bool         isInlineContent = inbound ? GetContent(entry, out buffer) : false;
                    MemoryStream blobStream      = null;
                    if (isInlineContent)
                    {
                        blobStream = new MemoryStream(buffer);
                    }
                    else
                    {
                        watch = Stopwatch.StartNew();
                        string             blobName = entry.AsString;
                        CloudBlob          blob     = container.GetBlobReference(blobName);
                        BlobRequestOptions options  = new BlobRequestOptions();
                        blobStream = new MemoryStream();
                        blob.DownloadToStream(blobStream);
                        watch.Stop();
                        LoggerFactory.Logger.Info(location + (inbound ? "->B2BEngineReadingFromIncomingBlob" : "OutboundTransportReadingFromOutgoingBlob"),
                                                  "timeInMs={0}, blob={1}",
                                                  watch.ElapsedMilliseconds, blobName);
                    }
                    blobStream.Position = 0;
                    //msg = DecodeBlobPayload(blobStream, this.fpm);
                    fatpipeMessage = BizpipeMesssageStreaming.CreateBizpipeMessageFromStream(blobStream, this.fpm);
                    // set the QueueName and the queue message identifiers
                    fatpipeMessage.Header.QueueName              = (inbound == true) ? incomingQ.Name : outgoingQ.Name;
                    fatpipeMessage.Header.QueueMessageId         = entry.Id;
                    fatpipeMessage.Header.QueueMessagePopReceipt = entry.PopReceipt;
                    fatpipeMessage.Status.NumberOfRetryAttempts  = entry.DequeueCount;
                }
            }
            catch (Exception ex)
            {
                LoggerFactory.Logger.Warning(location, EventId.BizpipeDequeueMessage
                                             , "Exception encountered during Dequeue operation: {0}", ex.ToString());
            }

            return(fatpipeMessage);
        }
示例#7
0
        public bool RetryOrSuspendMessage(IFatpipeMessage message)
        {
            if (message.Status.NumberOfRetryAttempts >= this.maximumNumberOfRetryAttempts)
            {
                return(this.SuspendMessage(message));
            }

            //Message will become visible again after the preset period of invisibility; no need to add another visibility setting.
            return(true);
        }
示例#8
0
        public bool Dequeue(ref IFatpipeMessage msg)
        {
            CloudQueueMessage entry = incomingQ.GetMessage();

            string blobName = entry.AsString;

            CloudBlob blob = container.GetBlobReference(blobName);

            //blob.DownloadToStream(

            return(true);
        }
        public void RemoveMessageFromQueue(IFatpipeMessage message)
        {
            string location = "FpmDal->RemoveMessageFromQueue";

            if (message == null)
            {
                throw new ArgumentNullException("message");
            }

            if (!string.IsNullOrEmpty(message.Header.QueueName))
            {
                CloudQueue queue = null;
                if (message.Header.QueueName == this.incomingQ.Name)
                {
                    queue = this.incomingQ;
                }

                if (message.Header.QueueName == this.outgoingQ.Name)
                {
                    queue = this.outgoingQ;
                }

                if (queue != null)
                {
                    try
                    {
                        queue.DeleteMessage(message.Header.QueueMessageId, message.Header.QueueMessagePopReceipt);
                    }
                    catch (Exception exception)
                    {
                        LoggerFactory.Logger.Error(location, EventId.BizpipeRemoveMessage
                                                   , "Error deleting message (Id = {0}, PopReceipt = {1}) from queue {2}: {3}.",
                                                   message.Header.QueueMessageId,
                                                   message.Header.QueueMessagePopReceipt,
                                                   queue.Name,
                                                   exception.ToString());
                        throw;
                    }
                }
                else
                {
                    LoggerFactory.Logger.Error(location, EventId.BizpipeStrayMessage
                                               , "Queue message is attached to queue {0} which is neither the inbound ({1}) nor the outbound ({2}) queue.",
                                               message.Header.QueueName,
                                               this.incomingQ.Name,
                                               this.outgoingQ.Name);
                }
            }
        }
示例#10
0
        public bool Enqueue(IFatpipeMessage msg)
        {
            // store the entire message in Blob
            string blobName = msg.Header.Identifier;

            CloudBlob blob = container.GetBlobReference(blobName);

            // Only the body is being uploaded for now..change it to upload the entire msg
            blob.UploadFromStream(msg.Body.Body);


            CloudQueueMessage entry = new CloudQueueMessage(blobName);

            incomingQ.AddMessage(entry);

            return(true);
        }
        public IEnumerable <IFatpipeMessage> ListSuspendedMessages(string tenantIdentifier)
        {
            string location = "FpmDal->ListSuspendedMessage";
            List <IFatpipeMessage> result = new List <IFatpipeMessage>();

            try
            {
                Stopwatch watch = Stopwatch.StartNew();

                string tableName         = MaargConfiguration.Instance[MaargConfiguration.SuspendedMessageTableName];
                var    suspendedMessages =
                    (
                        from e in this.suspendedTableServiceContext.CreateQuery <SuspendedMessageEntity>(tableName)
                        where e.PartitionKey == tenantIdentifier
                        select e
                    ).AsTableServiceQuery <SuspendedMessageEntity>();

                foreach (var suspendedMessage in suspendedMessages)
                {
                    IFatpipeMessage message = this.GetSuspendedMessage(suspendedMessage.RowKey);
                    if (message != null)
                    {
                        result.Add(message);
                    }
                }

                watch.Stop();
                LoggerFactory.Logger.Info(location,
                                          "Listed suspended messages for tenant {0} in {1} ms.",
                                          tenantIdentifier,
                                          watch.ElapsedMilliseconds);
            }
            catch (Exception exception)
            {
                LoggerFactory.Logger.Error(location, EventId.BizpipeListSuspendMessages
                                           , "Error listing suspended messages for tenant {0}: {1}."
                                           , tenantIdentifier
                                           , exception.ToString());
                throw;
            }

            return(result);
        }
示例#12
0
        /// <summary>
        /// Used by B2BProtocolEngine, it's a 3 step process.
        ///
        /// 1. First acquire lock (this method), so that other workers don't see the message for a period of time
        /// 2. Process message and write to OutboundQ or SuspendQ
        /// 3. Remove the message from Q
        ///
        /// </summary>
        /// <param name="count">Number of messages to DeQ</param>
        /// <returns></returns>
        public List <IFatpipeMessage> DeQFromIncomingQ(int count)
        {
            int                    iter    = 0;
            IFatpipeMessage        msg     = null;
            List <IFatpipeMessage> msgList = new List <IFatpipeMessage>();

            while (iter < count)
            {
                msg = fpmDal.Dequeue(Constants.QueueType.INBOUND);
                if (msg == null)
                {
                    break;
                }
                msgList.Add(msg);

                iter++;
            }

            return(msgList);
        }
        /// <summary>
        /// Has the logic to convert a FatpipeMessage into a Stream object that represents the storage logic
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static Stream WriteBizpipeMessageToStream(IFatpipeMessage message)
        {
            IList <KeyValuePair <string, string> > headerList = new List <KeyValuePair <string, string> >();

            headerList.Add(new KeyValuePair <string, string>(MsgId, message.Header.Identifier));
            headerList.Add(new KeyValuePair <string, string>(TenantId, message.Header.TenantIdentifier));
            headerList.Add(new KeyValuePair <string, string>(CorrelationId, message.Header.CorrelationId));

            if (message.Header.Context != null)
            {
                foreach (KeyValuePair <string, string> kvpair in message.Header.Context)
                {
                    headerList.Add(new KeyValuePair <string, string>(kvpair.Key, kvpair.Value));
                }
            }

            Stream headerStream = StreamHelper.SerializeHeadersToStream(headerList, true);
            Stream bodyStream   = message.Body.Body;

            return(new ConcatenatingStream(headerStream, bodyStream, null));
        }
        public static IFatpipeMessage CreateBizpipeMessageFromStream(Stream stream, IFatpipeManager manager)
        {
            IFatpipeMessage message = manager.CreateNewMessage();
            IList <KeyValuePair <string, string> > headerList;

            message.Body.Body = StreamHelper.DeserializeStreamToHeadersAndBody(stream, out headerList);
            MessageHeader header = new MessageHeader(string.Empty, string.Empty);

            message.Header = header;
            IDictionary <string, string> context = header.Context;

            foreach (KeyValuePair <string, string> keyValuePair in headerList)
            {
                string key = keyValuePair.Key;

                if (string.Compare(key, MsgId, StringComparison.OrdinalIgnoreCase) == 0)
                {
                    header.Identifier = keyValuePair.Value;
                }

                else if (string.Compare(key, TenantId, StringComparison.OrdinalIgnoreCase) == 0)
                {
                    header.TenantIdentifier = keyValuePair.Value;
                }

                else if (string.Compare(key, CorrelationId, StringComparison.OrdinalIgnoreCase) == 0)
                {
                    header.CorrelationId = keyValuePair.Value;
                }

                else
                {
                    context[keyValuePair.Key] = keyValuePair.Value;
                }
            }

            return(message);
        }
示例#15
0
        //Write message reference to permanent store, not Queue
        public bool SuspendMessage(IFatpipeMessage message)
        {
            bool   result   = true;
            string location = "FatpipeManager.SuspendMessage";

            try
            {
                //delete from queue
                this.fpmDal.RemoveMessageFromQueue(message);
                //save to suspended store
                result = this.fpmDal.SaveSuspendedMessage(message);
            }
            catch (Exception exception)
            {
                LoggerFactory.Logger.Error(location, EventId.BizpipeSuspendMessage,
                                           "Failed to suspend message {0}: {1}.",
                                           message.Header.Identifier,
                                           exception.ToString());
                result = false;
            }

            return(result);
        }
        public bool Enqueue(IFatpipeMessage msg, Constants.QueueType type)
        {
            string    location = "FpmDal->Enqueue";
            Stopwatch watch;

            try
            {
                // store the entire message in Blob
                string    blobName = msg.Header.Identifier;
                CloudBlob blob;
                bool      inbound = (type == Constants.QueueType.INBOUND);

                Stream blobStream = BizpipeMesssageStreaming.WriteBizpipeMessageToStream(msg);
                // The entry in the Q is the message blob name
                CloudQueueMessage entry = new CloudQueueMessage(blobName);
                //SetQueueBodyData(entry, blobStream);

                if (inbound)
                {
                    //Measure and write to blob storage
                    watch = Stopwatch.StartNew();
                    blob  = inContainer.GetBlobReference(blobName);
                    blob.UploadFromStream(blobStream);
                    watch.Stop();
                    LoggerFactory.Logger.Info(location + "->SaveToIncomingBlob", "timeInMs={0} blobName={1}",
                                              watch.ElapsedMilliseconds, blobName);

                    //Measure and write to incomingQ
                    watch = Stopwatch.StartNew();
                    incomingQ.AddMessage(entry);
                    watch.Stop();
                    LoggerFactory.Logger.Info(location + "->WriteToIncomingQ", "timeInMs={0} entry={1}",
                                              watch.ElapsedMilliseconds, blobName);
                }
                else
                {
                    //Measure and write to blob storage
                    watch = Stopwatch.StartNew();
                    blob  = outContainer.GetBlobReference(blobName);
                    blob.UploadFromStream(blobStream);
                    watch.Stop();
                    LoggerFactory.Logger.Info(location + "->B2BEngineWritingToOutgoingBlob", "timeInMs={0}, blob={1}",
                                              watch.ElapsedMilliseconds, blobName);

                    //Measure and write to incomingQ
                    watch = Stopwatch.StartNew();
                    outgoingQ.AddMessage(entry);
                    watch.Stop();
                    LoggerFactory.Logger.Info(location + "->B2BEngineWritingToOutgoingQ", "timeInMs={0}, entry={1}",
                                              watch.ElapsedMilliseconds, blobName);
                }

                // set the QueueName and the queue message identifiers
                msg.Header.QueueName              = (inbound == true) ? incomingQ.Name : outgoingQ.Name;
                msg.Header.QueueMessageId         = entry.Id;
                msg.Header.QueueMessagePopReceipt = entry.PopReceipt;
            }

            catch (Exception ex)
            {
                LoggerFactory.Logger.Warning(location, EventId.BizpipeEnqueueMessage
                                             , "Exception encountered during Enqueue operation: {0}", ex.ToString());
                return(false);
            }

            return(true);
        }
示例#17
0
 /// <summary>
 /// This is a very interesting method. It provides optics into what's going on in the system.
 /// Logic will be specific to agent.
 /// Refer to CorrelationId in message which stitches multiple messages together
 /// Eg. EDI Message M1, received, by AS2
 ///     M1 (correlationId), split into Ms1, Ms2, Ms3, Ms4, by B2BProtocolEngine
 ///     Ms1, sent, by HTTP
 ///     Ms2, sent, by AS2
 ///     Ms2, suspended, by AS2
 /// Common operations are
 /// messageM1, Received, 4/9/2012, By https://maarg.com, WebRole1, WebRoleId1234, ServerCloudMaarg1
 ///
 /// This is a very interesting subject and implementation can be very intelligent.
 /// We will start with a simple one though
 /// </summary>
 /// <param name="message"></param>
 /// <param name="agent"></param>
 /// <returns></returns>
 public bool WriteBusinessTransactionToStore(IFatpipeMessage message, IMessageHandlerAgent agent)
 {
     return(false);
 }