예제 #1
0
        public async Task <IReadOnlyList <MessageData> > GetMessagesAsync(CancellationToken cancellationToken)
        {
            using (var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(this.releaseCancellationToken, cancellationToken))
            {
                bool pendingOrchestratorMessageLimitReached = false;
                bool isWaitingForMoreMessages = false;

                while (!linkedCts.IsCancellationRequested)
                {
                    // Pause dequeuing if the total number of locked messages gets too high.
                    long pendingOrchestratorMessages = this.stats.PendingOrchestratorMessages.Count;
                    if (pendingOrchestratorMessages >= this.settings.ControlQueueBufferThreshold)
                    {
                        if (!pendingOrchestratorMessageLimitReached)
                        {
                            pendingOrchestratorMessageLimitReached = true;
                            this.settings.Logger.PendingOrchestratorMessageLimitReached(
                                this.storageAccountName,
                                this.settings.TaskHubName,
                                this.Name,
                                pendingOrchestratorMessages);
                        }

                        await Task.Delay(TimeSpan.FromSeconds(1));

                        continue;
                    }

                    pendingOrchestratorMessageLimitReached = false;

                    try
                    {
                        OperationContext context = new OperationContext {
                            ClientRequestID = Guid.NewGuid().ToString()
                        };
                        IEnumerable <CloudQueueMessage> batch = await TimeoutHandler.ExecuteWithTimeout(
                            "GetMessages",
                            context.ClientRequestID,
                            this.storageAccountName,
                            this.settings,
                            () =>
                        {
                            return(this.storageQueue.GetMessagesAsync(
                                       this.settings.ControlQueueBatchSize,
                                       this.settings.ControlQueueVisibilityTimeout,
                                       this.settings.ControlQueueRequestOptions,
                                       context,
                                       linkedCts.Token));
                        });

                        this.stats.StorageRequests.Increment();

                        if (!batch.Any())
                        {
                            if (!isWaitingForMoreMessages)
                            {
                                isWaitingForMoreMessages = true;
                                this.settings.Logger.WaitingForMoreMessages(
                                    this.storageAccountName,
                                    this.settings.TaskHubName,
                                    this.storageQueue.Name);
                            }

                            await this.backoffHelper.WaitAsync(linkedCts.Token);

                            continue;
                        }

                        isWaitingForMoreMessages = false;

                        var batchMessages = new ConcurrentBag <MessageData>();
                        await batch.ParallelForEachAsync(async delegate(CloudQueueMessage queueMessage)
                        {
                            this.stats.MessagesRead.Increment();

                            MessageData messageData = await this.messageManager.DeserializeQueueMessageAsync(
                                queueMessage,
                                this.storageQueue.Name);

                            // Check to see whether we've already dequeued this message.
                            if (!this.stats.PendingOrchestratorMessages.TryAdd(queueMessage.Id, 1))
                            {
                                // This message is already loaded in memory and is therefore a duplicate.
                                // We will continue to process it because we need the updated pop receipt.
                                this.settings.Logger.DuplicateMessageDetected(
                                    this.storageAccountName,
                                    this.settings.TaskHubName,
                                    messageData.TaskMessage.Event.EventType.ToString(),
                                    Utils.GetTaskEventId(messageData.TaskMessage.Event),
                                    queueMessage.Id,
                                    messageData.TaskMessage.OrchestrationInstance.InstanceId,
                                    messageData.TaskMessage.OrchestrationInstance.ExecutionId,
                                    this.Name,
                                    queueMessage.DequeueCount);
                            }

                            batchMessages.Add(messageData);
                        });

                        this.backoffHelper.Reset();

                        // Try to preserve insertion order when processing
                        IReadOnlyList <MessageData> sortedMessages = batchMessages.OrderBy(m => m, MessageOrderingComparer.Default).ToList();
                        foreach (MessageData message in sortedMessages)
                        {
                            AzureStorageOrchestrationService.TraceMessageReceived(
                                this.settings,
                                message,
                                this.storageAccountName);
                        }

                        return(sortedMessages);
                    }
                    catch (Exception e)
                    {
                        if (!linkedCts.IsCancellationRequested)
                        {
                            this.settings.Logger.MessageFailure(
                                this.storageAccountName,
                                this.settings.TaskHubName,
                                string.Empty /* MessageId */,
                                string.Empty /* InstanceId */,
                                string.Empty /* ExecutionId */,
                                this.storageQueue.Name,
                                string.Empty /* EventType */,
                                0 /* TaskEventId */,
                                e.ToString());

                            await this.backoffHelper.WaitAsync(linkedCts.Token);
                        }
                    }
                }

                this.IsReleased = true;
                return(EmptyMessageList);
            }
        }
예제 #2
0
        public async Task <IReadOnlyList <MessageData> > GetMessagesAsync(CancellationToken cancellationToken)
        {
            using (var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(this.releaseCancellationToken, cancellationToken))
            {
                bool pendingOrchestratorMessageLimitReached = false;
                bool isWaitingForMoreMessages = false;

                while (!linkedCts.IsCancellationRequested)
                {
                    // Pause dequeuing if the total number of locked messages gets too high.
                    long pendingOrchestratorMessages = this.stats.PendingOrchestratorMessages.Value;
                    if (pendingOrchestratorMessages >= this.settings.ControlQueueBufferThreshold)
                    {
                        if (!pendingOrchestratorMessageLimitReached)
                        {
                            pendingOrchestratorMessageLimitReached = true;
                            AnalyticsEventSource.Log.PendingOrchestratorMessageLimitReached(
                                this.storageAccountName,
                                this.settings.TaskHubName,
                                pendingOrchestratorMessages,
                                Utils.ExtensionVersion);
                        }

                        await Task.Delay(TimeSpan.FromSeconds(1));

                        continue;
                    }

                    pendingOrchestratorMessageLimitReached = false;

                    try
                    {
                        IEnumerable <CloudQueueMessage> batch = await this.storageQueue.GetMessagesAsync(
                            this.settings.ControlQueueBatchSize,
                            this.settings.ControlQueueVisibilityTimeout,
                            this.settings.ControlQueueRequestOptions,
                            null /* operationContext */,
                            linkedCts.Token);

                        this.stats.StorageRequests.Increment();

                        if (!batch.Any())
                        {
                            if (!isWaitingForMoreMessages)
                            {
                                isWaitingForMoreMessages = true;
                                AnalyticsEventSource.Log.WaitingForMoreMessages(
                                    this.storageAccountName,
                                    this.settings.TaskHubName,
                                    this.storageQueue.Name,
                                    Utils.ExtensionVersion);
                            }

                            await this.backoffHelper.WaitAsync(linkedCts.Token);

                            continue;
                        }

                        isWaitingForMoreMessages = false;

                        var batchMessages = new ConcurrentBag <MessageData>();
                        await batch.ParallelForEachAsync(async delegate(CloudQueueMessage queueMessage)
                        {
                            this.stats.MessagesRead.Increment();

                            MessageData messageData = await this.messageManager.DeserializeQueueMessageAsync(
                                queueMessage,
                                this.storageQueue.Name);

                            batchMessages.Add(messageData);
                        });

                        this.backoffHelper.Reset();

                        // Try to preserve insertion order when processing
                        IReadOnlyList <MessageData> sortedMessages = batchMessages.OrderBy(m => m, MessageOrderingComparer.Default).ToList();
                        foreach (MessageData message in sortedMessages)
                        {
                            AzureStorageOrchestrationService.TraceMessageReceived(
                                message,
                                this.storageAccountName,
                                this.settings.TaskHubName);
                        }

                        return(sortedMessages);
                    }
                    catch (Exception e)
                    {
                        if (!linkedCts.IsCancellationRequested)
                        {
                            AnalyticsEventSource.Log.MessageFailure(
                                this.storageAccountName,
                                this.settings.TaskHubName,
                                string.Empty,
                                string.Empty,
                                this.storageQueue.Name,
                                string.Empty,
                                e.ToString(),
                                Utils.ExtensionVersion);

                            await this.backoffHelper.WaitAsync(linkedCts.Token);
                        }
                    }
                }

                this.IsReleased = true;
                return(EmptyMessageList);
            }
        }