Ejemplo n.º 1
0
        /// <summary>
        /// Fetches all of the current known results for the Sent Notification and calculates the various totals
        /// as results.
        /// </summary>
        /// <param name="notificationId">The notification ID.</param>
        /// <param name="log">The logger.</param>
        /// <returns>A <see cref="Task{TResult}"/> representing the result of the asynchronous operation.</returns>
        public async Task <AggregatedSentNotificationDataResults> AggregateSentNotificationDataResultsAsync(
            string notificationId,
            ILogger log)
        {
            var partitionKeyFilter = TableQuery.GenerateFilterCondition(
                nameof(TableEntity.PartitionKey),
                QueryComparisons.Equal,
                notificationId);

            // The SentNotificationDataEntity.DeliveryStatus property's default value is null.
            // After finished processing a recipient, the send function sets the property to one of the following values, which indicates the delivery status.
            //   Succeeded,
            //   Failed,
            //   RecipientNotFound,
            //   Throttled,
            //   etc.
            // The notNullStatusFilter finds out the delivery statuses for all the processed recipients.
            var notNullStatusFilter = TableQuery.GenerateFilterCondition(
                nameof(SentNotificationDataEntity.DeliveryStatus),
                QueryComparisons.NotEqual,
                "null");

            // Create the complete query where:
            // PartitionKey eq notificationId AND DeliveryStatus ne null
            var completeFilter = TableQuery.CombineFilters(partitionKeyFilter, TableOperators.And, notNullStatusFilter);
            var query          = new TableQuery <SentNotificationDataEntity>().Where(completeFilter);

            try
            {
                var aggregatedResults = new AggregatedSentNotificationDataResults();

                TableContinuationToken currentContinuationToken = null;

                do
                {
                    // Make the query to the data table and update the continuation token in order to continue to paginate the results.
                    TableQuerySegment <SentNotificationDataEntity> resultSegment = await this.sentNotificationDataRepository.Table
                                                                                   .ExecuteQuerySegmentedAsync <SentNotificationDataEntity>(query, currentContinuationToken);

                    currentContinuationToken = resultSegment.ContinuationToken;

                    // Aggregate the results.
                    foreach (var sentNotification in resultSegment)
                    {
                        aggregatedResults.UpdateAggregatedResults(sentNotification);
                    }
                }while (currentContinuationToken != null);

                return(aggregatedResults);
            }
            catch (Exception e)
            {
                var errorMessage = $"{e.GetType()}: {e.Message}";
                log.LogError(e, $"ERROR: {errorMessage}");
                throw;
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Updates the notification totals with the given information and results.
        /// </summary>
        /// <param name="notificationId">The notification ID.</param>
        /// <param name="shouldForceCompleteNotification">Flag to indicate if the notification should
        /// be forced to be marked as completed.</param>
        /// <param name="totalExpectedNotificationCount">The total expected count of notifications to be sent.</param>
        /// <param name="aggregatedSentNotificationDataResults">The current aggregated results for
        /// the sent notifications.</param>
        /// <param name="log">The logger.</param>
        /// <returns>A <see cref="Task{TResult}"/> representing the result of the asynchronous operation.</returns>
        public async Task <UpdateNotificationDataEntity> UpdateNotificationDataAsync(
            string notificationId,
            bool shouldForceCompleteNotification,
            int totalExpectedNotificationCount,
            AggregatedSentNotificationDataResults aggregatedSentNotificationDataResults,
            ILogger log)
        {
            try
            {
                var currentTotalNotificationCount = aggregatedSentNotificationDataResults.CurrentTotalNotificationCount;
                var succeededCount         = aggregatedSentNotificationDataResults.SucceededCount;
                var failedCount            = aggregatedSentNotificationDataResults.FailedCount;
                var throttledCount         = aggregatedSentNotificationDataResults.ThrottledCount;
                var recipientNotFoundCount = aggregatedSentNotificationDataResults.RecipientNotFoundCount;
                var lastSentDate           = aggregatedSentNotificationDataResults.LastSentDate;

                // Create the general update.
                var notificationDataEntityUpdate = new UpdateNotificationDataEntity
                {
                    PartitionKey      = NotificationDataTableNames.SentNotificationsPartition,
                    RowKey            = notificationId,
                    Succeeded         = succeededCount,
                    Failed            = failedCount,
                    RecipientNotFound = recipientNotFoundCount,
                    Throttled         = throttledCount,
                };

                // If it should be marked as complete, set the other values accordingly.
                if (currentTotalNotificationCount >= totalExpectedNotificationCount ||
                    shouldForceCompleteNotification)
                {
                    // Update the status to Sent.
                    notificationDataEntityUpdate.Status = NotificationStatus.Sent.ToString();

                    if (currentTotalNotificationCount >= totalExpectedNotificationCount)
                    {
                        // If the message is being completed because all messages have been accounted for,
                        // then make sure the unknown count is 0 and update the sent date with the date
                        // of the last sent message.
                        notificationDataEntityUpdate.Unknown  = 0;
                        notificationDataEntityUpdate.SentDate = lastSentDate ?? DateTime.UtcNow;
                    }
                    else if (shouldForceCompleteNotification)
                    {
                        // If the message is being completed, not because all messages have been accounted for,
                        // but because the trigger is coming from the delayed Service Bus message that ensures that the
                        // notification will eventually be marked as complete, then update the unknown count of messages
                        // not accounted for and update the sent date to the current time.
                        var countDifference = totalExpectedNotificationCount - currentTotalNotificationCount;

                        // This count must stay 0 or above.
                        var unknownCount = countDifference >= 0 ? countDifference : 0;

                        notificationDataEntityUpdate.Unknown  = unknownCount;
                        notificationDataEntityUpdate.SentDate = DateTime.UtcNow;
                    }
                }

                var operation = TableOperation.InsertOrMerge(notificationDataEntityUpdate);
                await this.notificationDataRepository.Table.ExecuteAsync(operation);

                return(notificationDataEntityUpdate);
            }
            catch (Exception e)
            {
                var errorMessage = $"{e.GetType()}: {e.Message}";
                log.LogError(e, $"ERROR: {errorMessage}");
                throw;
            }
        }