public void OnMessage(IRestrictionAttributesAcceptedV1 message) { var requestTelemetry = RequestTelemetryHelper.Start("Restriction Attributes Accepted Processing Rate", DateTime.UtcNow); CallContext.LogicalSetData(CORRELATION_SLOT, requestTelemetry.Id); Stopwatch requestTimer = Stopwatch.StartNew(); if (message == null) { throw new ArgumentNullException(); } var skuVariant = _skuVariantCacheManager.GetItemByKey(message.Sku); if (skuVariant == null) { throw new Exception($"Sku Variant Not Found For Restriction Attribute Accepted with Sku: {message.Sku}"); } var regionStock = _regionStockAggregateStore.GetRegionStockByVariantId(skuVariant.VariantId); if (regionStock != null) { IRegionStockAggregate regionStockAggregate = new RegionStockAggregate(regionStock.VariantId, regionStock.WarehouseAvailableStocks.ToList(), regionStock.RegionStocks.ToList(), null, regionStock.Version); regionStockAggregate.ApplyRestrictionAttributes(message.Attributes); _regionStockAggregateStore.UpdateRegionStock(RegionStockDocument.CreateFrom(regionStockAggregate)); } else { throw new RegionStockAggregateNotFoundException($"Failed retrieving Region Stock Aggregate for Sku {message.Sku}"); } RequestTelemetryHelper.Dispatch(_telemetryClient, requestTelemetry, requestTimer.Elapsed, true); }
private void ProcessSubscribeQueueMessage(CloudQueueMessage msg) { Stopwatch requestTimer = Stopwatch.StartNew(); var request = RequestTelemetryHelper.StartNewRequest("ProcessSubscribeQueueMessage", DateTimeOffset.UtcNow); CallContext.LogicalSetData(CORRELATION_SLOT, request.Id); //Thread.SetData(Thread.GetNamedDataSlot(CORRELATION_SLOT), request.Id); try { // Log and delete if this is a "poison" queue message (repeatedly processed // and always causes an error that prevents processing from completing). // Production applications should move the "poison" message to a "dead message" // queue for analysis rather than deleting the message. if (msg.DequeueCount > 5) { Trace.TraceError("Deleting poison subscribe message: message {0}.", msg.AsString, GetRoleInstance()); subscribeQueue.DeleteMessage(msg); request.Properties.Add(new KeyValuePair <string, string>("FailureCode", "PoisonMessage")); request.Properties.Add(new KeyValuePair <string, string>("DequeueCount", msg.DequeueCount.ToString())); if (msg.InsertionTime != null) { request.Metrics.Add(new KeyValuePair <string, double>("SubscribeProcessingTimeMs", ((TimeSpan)(DateTimeOffset.Now - msg.InsertionTime)).Milliseconds)); } RequestTelemetryHelper.DispatchRequest(request, requestTimer.Elapsed, false); return; } // Parse message retrieved from queue. Message consists of // subscriber GUID and list name. // Example: 57ab4c4b-d564-40e3-9a3f-81835b3e102e,contoso1 var messageParts = msg.AsString.Split(new char[] { ',' }); var subscriberGUID = messageParts[0]; var listName = messageParts[1]; Trace.TraceInformation("ProcessSubscribeQueueMessage start: subscriber GUID {0} listName {1} Role Instance {2}.", subscriberGUID, listName, GetRoleInstance()); // Get subscriber info. string filter = TableQuery.CombineFilters( TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, listName), TableOperators.And, TableQuery.GenerateFilterCondition("SubscriberGUID", QueryComparisons.Equal, subscriberGUID)); var query = new TableQuery <Subscriber>().Where(filter); var subscriber = mailingListTable.ExecuteQuery(query).ToList().Single(); // Get mailing list info. var retrieveOperation = TableOperation.Retrieve <MailingList>(subscriber.ListName, "mailinglist"); var retrievedResult = mailingListTable.Execute(retrieveOperation); var mailingList = retrievedResult.Result as MailingList; SendSubscribeEmail(subscriberGUID, subscriber, mailingList); subscribeQueue.DeleteMessage(msg); Trace.TraceInformation("ProcessSubscribeQueueMessage complete: subscriber GUID {0} Role Instance {1}.", subscriberGUID, GetRoleInstance()); if (msg.InsertionTime != null) { request.Metrics.Add(new KeyValuePair <string, double>("SubscribeProcessingTimeMs", ((TimeSpan)(DateTimeOffset.Now - msg.InsertionTime)).Milliseconds)); } RequestTelemetryHelper.DispatchRequest(request, requestTimer.Elapsed, true); } catch (Exception ex) { request.Properties.Add(new KeyValuePair <string, string>("FailureCode", "Exception")); if (msg.InsertionTime != null) { request.Metrics.Add(new KeyValuePair <string, double>("FailedSubscribeProcessingTimeMs", ((TimeSpan)(DateTimeOffset.Now - msg.InsertionTime)).Milliseconds)); } RequestTelemetryHelper.DispatchRequest(request, requestTimer.Elapsed, false); throw ex; } }
public override void Run() { Trace.TraceInformation("WorkerRoleA entering Run()"); while (true) { Stopwatch requestTimer = Stopwatch.StartNew(); var request = RequestTelemetryHelper.StartNewRequest("ProcessMessageWorkflow", DateTimeOffset.UtcNow); CallContext.LogicalSetData(CORRELATION_SLOT, request.Id); //Thread.SetData(Thread.GetNamedDataSlot(CORRELATION_SLOT), request.Id); try { var tomorrow = DateTime.Today.AddDays(1.0).ToString("yyyy-MM-dd"); // If OnStop has been called, return to do a graceful shutdown. if (onStopCalled == true) { Trace.TraceInformation("onStopCalled WorkerRoleB"); returnedFromRunMethod = true; return; } // Retrieve all messages that are scheduled for tomorrow or earlier // and are in Pending or Queuing status. string typeAndDateFilter = TableQuery.CombineFilters( TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.GreaterThan, "message"), TableOperators.And, TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.LessThan, tomorrow)); var query = (new TableQuery <Message>().Where(typeAndDateFilter)); var messagesToProcess = messageTable.ExecuteQuery(query).ToList(); TableOperation replaceOperation; request.Metrics.Add(new KeyValuePair <string, double>("NumberOfMessages", messagesToProcess.Count)); // Process each message (queue emails to be sent). foreach (Message messageToProcess in messagesToProcess) { string restartFlag = "0"; // If the message is already in Queuing status, // set flag to indicate this is a restart. if (messageToProcess.Status == "Queuing") { restartFlag = "1"; } // If the message is in Pending status, change // it to Queuing. if (messageToProcess.Status == "Pending") { messageToProcess.Status = "Queuing"; replaceOperation = TableOperation.Replace(messageToProcess); messageTable.Execute(replaceOperation); } // If the message is in Queuing status, // process it and change it to Processing status; // otherwise it's already in processing status, and // in that case check if processing is complete. if (messageToProcess.Status == "Queuing") { ProcessMessage(messageToProcess, restartFlag); messageToProcess.Status = "Processing"; replaceOperation = TableOperation.Replace(messageToProcess); messageTable.Execute(replaceOperation); } else { CheckAndArchiveIfComplete(messageToProcess); } } RequestTelemetryHelper.DispatchRequest(request, requestTimer.Elapsed, true); // Sleep to minimize query costs. System.Threading.Thread.Sleep(1000 * 30); } catch (Exception ex) { string err = ex.Message; if (ex.InnerException != null) { err += " Inner Exception: " + ex.InnerException.Message; } Trace.TraceError(err, ex); RequestTelemetryHelper.DispatchRequest(request, requestTimer.Elapsed, false); // Don't fill up Trace storage if we have a bug in queue process loop. System.Threading.Thread.Sleep(1000 * 60); } } }
private void ProcessQueueMessage(CloudQueueMessage msg) { Stopwatch requestTimer = Stopwatch.StartNew(); var request = RequestTelemetryHelper.StartNewRequest("ProcessEmailQueueMessage", DateTimeOffset.UtcNow); CallContext.LogicalSetData(CORRELATION_SLOT, request.Id); //Thread.SetData(Thread.GetNamedDataSlot(CORRELATION_SLOT), request.Id); try { // Log and delete if this is a "poison" queue message (repeatedly processed // and always causes an error that prevents processing from completing). // Production applications should move the "poison" message to a "dead message" // queue for analysis rather than deleting the message. if (msg.DequeueCount > 5) { Trace.TraceError("Deleting poison message: message {0} Role Instance {1}.", msg.ToString(), GetRoleInstance()); sendEmailQueue.DeleteMessage(msg); request.Properties.Add(new KeyValuePair <string, string>("FailureCode", "PoisonMessage")); request.Properties.Add(new KeyValuePair <string, string>("DequeueCount", msg.DequeueCount.ToString())); if (msg.InsertionTime != null) { request.Metrics.Add(new KeyValuePair <string, double>("EmailProcessingTimeMs", ((TimeSpan)(DateTimeOffset.Now - msg.InsertionTime)).Milliseconds)); } RequestTelemetryHelper.DispatchRequest(request, requestTimer.Elapsed, false); return; } // Parse message retrieved from queue. // Example: 2012-01-01,[email protected],0 var messageParts = msg.AsString.Split(new char[] { ',' }); var partitionKey = messageParts[0]; var rowKey = messageParts[1]; var restartFlag = messageParts[2]; Trace.TraceInformation("ProcessQueueMessage start: partitionKey {0} rowKey {1} Role Instance {2}.", partitionKey, rowKey, GetRoleInstance()); // If this is a restart, verify that the email hasn't already been sent. if (restartFlag == "1") { var retrieveOperationForRestart = TableOperation.Retrieve <SendEmail>(partitionKey, rowKey); var retrievedResultForRestart = messagearchiveTable.Execute(retrieveOperationForRestart); var messagearchiveRow = retrievedResultForRestart.Result as SendEmail; if (messagearchiveRow != null) { // SendEmail row is in archive, so email is already sent. // If there's a SendEmail Row in message table, delete it, // and delete the queue message. Trace.TraceInformation("Email already sent: partitionKey=" + partitionKey + " rowKey= " + rowKey); var deleteOperation = TableOperation.Delete(new SendEmail { PartitionKey = partitionKey, RowKey = rowKey, ETag = "*" }); try { messageTable.Execute(deleteOperation); } catch (Exception ex) { aiClient.TrackException(ex); } sendEmailQueue.DeleteMessage(msg); request.Properties.Add(new KeyValuePair <string, string>("SuccessCode", "NoOp-MessageAlreadySent")); if (msg.InsertionTime != null) { request.Metrics.Add(new KeyValuePair <string, double>("EmailProcessingTimeMs", ((TimeSpan)(DateTimeOffset.Now - msg.InsertionTime)).Milliseconds)); } RequestTelemetryHelper.DispatchRequest(request, requestTimer.Elapsed, true); return; } } // Get the row in the Message table that has data we need to send the email. var retrieveOperation = TableOperation.Retrieve <SendEmail>(partitionKey, rowKey); var retrievedResult = messageTable.Execute(retrieveOperation); var emailRowInMessageTable = retrievedResult.Result as SendEmail; if (emailRowInMessageTable == null) { Trace.TraceError("SendEmail row not found: partitionKey {0} rowKey {1} Role Instance {2}.", partitionKey, rowKey, GetRoleInstance()); request.Properties.Add(new KeyValuePair <string, string>("FailureCode", "SendEmailRowNotFound")); if (msg.InsertionTime != null) { request.Metrics.Add(new KeyValuePair <string, double>("EmailProcessingTimeMs", ((TimeSpan)(DateTimeOffset.Now - msg.InsertionTime)).Milliseconds)); } RequestTelemetryHelper.DispatchRequest(request, requestTimer.Elapsed, false); return; } // Derive blob names from the MessageRef. var htmlMessageBodyRef = emailRowInMessageTable.MessageRef + ".htm"; var textMessageBodyRef = emailRowInMessageTable.MessageRef + ".txt"; // If the email hasn't already been sent, send email and archive the table row. if (emailRowInMessageTable.EmailSent != true) { SendEmailToList(emailRowInMessageTable, htmlMessageBodyRef, textMessageBodyRef); var emailRowToDelete = new SendEmail { PartitionKey = partitionKey, RowKey = rowKey, ETag = "*" }; emailRowInMessageTable.EmailSent = true; var upsertOperation = TableOperation.InsertOrReplace(emailRowInMessageTable); messagearchiveTable.Execute(upsertOperation); var deleteOperation = TableOperation.Delete(emailRowToDelete); messageTable.Execute(deleteOperation); } // Delete the queue message. sendEmailQueue.DeleteMessage(msg); Trace.TraceInformation("ProcessQueueMessage complete: partitionKey {0} rowKey {1} Role Instance {2}.", partitionKey, rowKey, GetRoleInstance()); request.Properties.Add(new KeyValuePair <string, string>("SuccessCode", "EmailSent")); if (msg.InsertionTime != null) { request.Metrics.Add(new KeyValuePair <string, double>("EmailProcessingTimeMs", ((TimeSpan)(DateTimeOffset.Now - msg.InsertionTime)).Milliseconds)); } RequestTelemetryHelper.DispatchRequest(request, requestTimer.Elapsed, true); } catch (Exception ex) { request.Properties.Add(new KeyValuePair <string, string>("FailureCode", "Exception")); if (msg.InsertionTime != null) { request.Metrics.Add(new KeyValuePair <string, double>("FailedEmailProcessingTimeMs", ((TimeSpan)(DateTimeOffset.Now - msg.InsertionTime)).Milliseconds)); } RequestTelemetryHelper.DispatchRequest(request, requestTimer.Elapsed, false); throw ex; } }