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;
            }            
        }
Example #2
0
        private void ProcessQueueMessage(CloudQueueMessage msg)
        {
            // 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);
                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
                    {
                    }
                    sendEmailQueue.DeleteMessage(msg);
                    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());
                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());
        }
Example #3
0
        private void ProcessSubscribeQueueMessage(CloudQueueMessage msg)
        {
            if (msg.DequeueCount > 5)
            {
                Trace.TraceError(
                    "Deleting poison subscribe message: message {0} WorkerC.",
                    msg.ToString()
                    );
                subscribeQueue.DeleteMessage(msg);
            }

            string[] subscriberParts = msg.AsString.Split(new char[] { ',' });
            string partitionKey = subscriberParts[0];
            string rowKey = subscriberParts[1];

            var retrieveOperation = TableOperation.Retrieve<Subscription>(partitionKey, rowKey);
            var retrievedResult = subscribersTable.Execute(retrieveOperation);
            var subscriber = retrievedResult.Result as Subscription;

            if (subscriber.Verified == true)
            {
                Trace.TraceWarning(
                    "Deleting message where subscriber App {0} with Log {1} is already verified.",
                    partitionKey,
                    rowKey
                    );
                subscribeQueue.DeleteMessage(msg);
                return;
            }
            else if (subscriber.VerificationsSent >= 3)
            {
                Trace.TraceWarning(
                    "Deleting message where subscriber App {0} with Log {1} has had {2} verification emails sent.",
                    partitionKey,
                    rowKey,
                    subscriber.VerificationsSent
                    );
                subscribeQueue.DeleteMessage(msg);
                return;
            }

            // Send email
            SendEmail(subscriber);

            // Increment count
            subscriber.VerificationsSent++;
            var replaceOperation = TableOperation.Replace(subscriber);
            subscribersTable.Execute(replaceOperation);

            subscribeQueue.DeleteMessage(msg);
        }