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); } }
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); } }