コード例 #1
0
        /// <summary>
        /// Deletes a single message from a queue.
        /// </summary>
        /// <typeparam name="T">The type of the payload associated with the message.</typeparam>
        /// <param name="message">The message to be deleted from a queue.</param>
        /// <returns>A flag indicating whether or not the specified message has actually been deleted.</returns>
        public bool Delete <T>(T message)
        {
            Guard.ArgumentNotNull(message, "message");

            int deletedMsgCount = 0;

            InflightMessageInfo inflightMessage = null;

            if (this.inflightMessages.TryRemove(message, out inflightMessage))
            {
                try
                {
                    var queue = this.queueStorage.GetQueueReference(inflightMessage.QueueName);

                    foreach (var queueMsg in inflightMessage.QueueMessages)
                    {
                        if (Delete(queue, queueMsg))
                        {
                            deletedMsgCount++;
                        }
                    }

                    // Remove large message blob (if associated with the message being deleted).
                    if (inflightMessage.LargeMessageMetadata != null)
                    {
                        this.overflowStorage.Delete(inflightMessage.LargeMessageMetadata.ContainerName, inflightMessage.LargeMessageMetadata.BlobReference);
                    }
                }
                catch
                {
                    // In the event of a failure, return the removed in-flight message back to the collection.
                    if (!this.inflightMessages.TryAdd(message, inflightMessage))
                    {
                        this.inflightMessages.AddOrUpdate(message, inflightMessage, (key, oldValue) => { return(inflightMessage); });
                    }
                    throw;
                }
            }

            return(deletedMsgCount > 0);
        }
コード例 #2
0
        /// <summary>
        /// Gets a collection of messages from the specified queue and applies the specified visibility timeout.
        /// </summary>
        /// <typeparam name="T">The type of the payload associated with the message.</typeparam>
        /// <param name="queueName">The name of the source queue.</param>
        /// <param name="count">The number of messages to retrieve.</param>
        /// <param name="visibilityTimeout">The timeout during which retrieved messages will remain invisible on the queue.</param>
        /// <returns>The list of messages retrieved from the specified queue.</returns>
        public IEnumerable <T> Get <T>(string queueName, int count, TimeSpan visibilityTimeout)
        {
            Guard.ArgumentNotNullOrEmptyString(queueName, "queueName");
            Guard.ArgumentNotZeroOrNegativeValue(count, "count");

            try
            {
                var queue = this.queueStorage.GetQueueReference(CloudUtility.GetSafeContainerName(queueName));

                IEnumerable <CloudQueueMessage> queueMessages = this.retryPolicy.ExecuteAction <IEnumerable <CloudQueueMessage> >(() =>
                {
                    return(queue.GetMessages(Math.Min(count, CloudQueueMessage.MaxNumberOfMessagesToPeek), visibilityTimeout));
                });

                if (queueMessages != null)
                {
                    Type queueMsgType = typeof(T);
                    var  messages     = new List <T>(count);

                    foreach (var queueMsg in queueMessages)
                    {
                        object msgObject = DeserializeQueueMessage(queueMsg, queueMsgType);

                        // Construct an in-flight message object describing the queued message.
                        InflightMessageInfo inflightMessage = new InflightMessageInfo()
                        {
                            QueueName = queue.Name
                        };

                        // Register the queued message so that it can be located later on.
                        inflightMessage.QueueMessages.Add(queueMsg);

                        if (msgObject is LargeQueueMessageInfo)
                        {
                            // Looks like we are dealing a large message that needs to be fetched from blob storage.
                            inflightMessage.LargeMessageMetadata = msgObject as LargeQueueMessageInfo;

                            // Attempt to retrieve the actual message data from the blob storage.
                            T msgData = this.overflowStorage.Get <T>(inflightMessage.LargeMessageMetadata.ContainerName, inflightMessage.LargeMessageMetadata.BlobReference);

                            // If blob was found, add it to the list of messages being fetched and returned.
                            if (msgData != null)
                            {
                                messages.Add(msgData);
                                msgObject = msgData;
                            }
                            else
                            {
                                // We should skip the current message as it's data has not been located.
                                continue;
                            }
                        }
                        else
                        {
                            messages.Add((T)msgObject);
                        }

                        // Update the in-flight collection, add a new item if necessary, otherwise perform a thread-safe update.
                        this.inflightMessages.AddOrUpdate(msgObject, inflightMessage, (key, oldValue) =>
                        {
                            oldValue.QueueMessages.Clear();
                            return(inflightMessage);
                        });
                    }

                    return(messages);
                }
            }
            catch (Exception ex)
            {
                // We intend to never fail when fetching messages from a queue. We will still need to report on a exception and return an empty list.
                TraceManager.CloudStorageComponent.TraceError(ex);
            }

            // By default, return an empty collection of messages if the above code path didn't return a result.
            return(new T[0]);
        }