private void SetSentStatusWithUnknownCount(ref UpdateNotificationDataEntity notificationDataEntityUpdate, int unknownCount)
        {
            notificationDataEntityUpdate.Status = NotificationStatus.Sent.ToString();

            // This count must stay 0 or above.
            unknownCount = unknownCount >= 0 ? unknownCount : 0;
            notificationDataEntityUpdate.Unknown  = unknownCount;
            notificationDataEntityUpdate.SentDate = DateTime.UtcNow;
        }
        private void SetCanceledStatus(ref UpdateNotificationDataEntity notificationDataEntityUpdate, int canceledCount)
        {
            notificationDataEntityUpdate.Status = NotificationStatus.Canceled.ToString();

            // This count must stay 0 or above.
            canceledCount = canceledCount >= 0 ? canceledCount : 0;
            notificationDataEntityUpdate.Canceled = canceledCount;
            notificationDataEntityUpdate.SentDate = DateTime.UtcNow;
        }
        private void SetSentStatus(ref UpdateNotificationDataEntity notificationDataEntityUpdate, DateTime?lastSentDate)
        {
            // Update the status to Sent.
            notificationDataEntityUpdate.Status = NotificationStatus.Sent.ToString();

            // 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;
        }
        /// <summary>
        /// Updates the notification totals with the given information and results.
        /// </summary>
        /// <param name="notificationId">The notification ID.</param>
        /// <param name="orchestrationStatus">The orchestration status of the notification.</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,
            string orchestrationStatus,
            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 (orchestrationStatus.Equals(nameof(OrchestrationStatus.Terminated), StringComparison.InvariantCultureIgnoreCase) ||
                    orchestrationStatus.Equals(nameof(OrchestrationStatus.Completed), StringComparison.InvariantCultureIgnoreCase))
                {
                    if (currentTotalNotificationCount >= totalExpectedNotificationCount)
                    {
                        this.SetSentStatus(ref notificationDataEntityUpdate, lastSentDate);
                    }
                    else
                    {
                        var countDifference = totalExpectedNotificationCount - currentTotalNotificationCount;
                        this.SetCanceledStatus(ref notificationDataEntityUpdate, countDifference);
                    }
                }
                else

                // If it should be marked as complete, set the other values accordingly.
                if (currentTotalNotificationCount >= totalExpectedNotificationCount ||
                    shouldForceCompleteNotification)
                {
                    if (currentTotalNotificationCount >= totalExpectedNotificationCount)
                    {
                        this.SetSentStatus(ref notificationDataEntityUpdate, lastSentDate);
                    }
                    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.SetSentStatusWithUnknownCount(ref notificationDataEntityUpdate, countDifference);
                    }
                }

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