public void ProcessQueuedEmailNotificationsTestInvalidInput()
        {
            MeetingInviteController meetingInviteController = new MeetingInviteController(this.emailServiceManager.Object, this.logger);
            QueueNotificationItem   queueNotificationItem   = new QueueNotificationItem {
                NotificationIds = new string[] { Guid.NewGuid().ToString() }
            };

            _ = Assert.ThrowsAsync <ArgumentException>(async() => await meetingInviteController.ProcessQueuedMeetingNotifications(null, queueNotificationItem));
            _ = Assert.ThrowsAsync <ArgumentNullException>(async() => await meetingInviteController.ProcessQueuedMeetingNotifications("TestApp", null));
        }
        public void ProcessQueuedEmailNotificationsTestValidInput()
        {
            MeetingInviteController      meetingInviteController = new MeetingInviteController(this.emailServiceManager.Object, this.logger);
            IList <NotificationResponse> responses = new List <NotificationResponse>();
            string applicationName = "TestApp";
            QueueNotificationItem queueNotificationItem = new QueueNotificationItem {
                NotificationIds = new string[] { Guid.NewGuid().ToString() }
            };

            _ = this.emailServiceManager
                .Setup(emailServiceManager => emailServiceManager.ProcessMeetingNotifications(It.IsAny <string>(), It.IsAny <QueueNotificationItem>()))
                .Returns(Task.FromResult(responses));

            Task <IList <NotificationResponse> > result = meetingInviteController.ProcessQueuedMeetingNotifications(applicationName, queueNotificationItem);

            Assert.AreEqual(result.Status.ToString(), "RanToCompletion");
            this.emailServiceManager.Verify(mgr => mgr.ProcessMeetingNotifications(It.IsAny <string>(), It.IsAny <QueueNotificationItem>()), Times.Once);
            Assert.Pass();
        }
コード例 #3
0
        /// <summary>
        /// Fetches the records for given notification ids and resends using MS Graph Provider.
        /// </summary>
        /// <param name="applicationName">Application associated with email notifications.</param>
        /// <param name="queueNotificationItem">Queue Notification Entity.</param>
        /// <returns>A <see cref="Task"/> representing the result of the asynchronous operation.</returns>
        private async Task <IList <MeetingNotificationItemEntity> > ProcessMeetingNotificationsUsingProvider(string applicationName, QueueNotificationItem queueNotificationItem)
        {
            var traceProps = new Dictionary <string, string>();

            traceProps[Constants.Application] = applicationName;
            IList <MeetingNotificationItemEntity> notSentEntities = new List <MeetingNotificationItemEntity>();

            this.logger.TraceInformation($"Started {nameof(this.ProcessMeetingNotificationsUsingProvider)} method of {nameof(EmailServiceManager)}.", traceProps);

            List <string> notificationIds = queueNotificationItem.NotificationIds.ToList();

            this.logger.TraceVerbose($"Started {nameof(this.emailNotificationRepository.GetMeetingNotificationItemEntities)} method in {nameof(EmailServiceManager)}.", traceProps);
            IList <MeetingNotificationItemEntity> notificationEntities = await this.emailNotificationRepository.GetMeetingNotificationItemEntities(notificationIds, applicationName).ConfigureAwait(false);

            this.logger.TraceVerbose($"Completed {nameof(this.emailNotificationRepository.GetMeetingNotificationItemEntities)} method in {nameof(EmailServiceManager)}.", traceProps);

            var notificationEntitiesToBeSkipped = new List <MeetingNotificationItemEntity>();

            if (notificationEntities?.Count == 0)
            {
                throw new ArgumentException("No records found for the input notification ids.", nameof(queueNotificationItem));
            }

            if (queueNotificationItem.IgnoreAlreadySent)
            {
                notificationEntitiesToBeSkipped = notificationEntities.Where(x => x.Status == NotificationItemStatus.Sent).ToList();
                notificationEntities            = notificationEntities.Where(x => x.Status != NotificationItemStatus.Sent).ToList();
            }

            if (notificationEntities?.Count == 0)
            {
                return(notificationEntitiesToBeSkipped);
            }

            this.logger.TraceVerbose($"Started {nameof(this.ProcessMeetingNotificationsUsingProvider)} method in {nameof(EmailServiceManager)}.", traceProps);
            var retEntities = await this.ProcessMeetingNotificationEntities(applicationName, notificationEntities).ConfigureAwait(false);

            this.logger.TraceVerbose($"Completed {nameof(this.ProcessMeetingNotificationsUsingProvider)} method in {nameof(EmailServiceManager)}.", traceProps);
            retEntities = retEntities.Concat(notificationEntitiesToBeSkipped).ToList();
            this.logger.TraceInformation($"Completed {nameof(this.ProcessNotificationsUsingProvider)} method of {nameof(EmailServiceManager)}.", traceProps);

            return(retEntities);
        }
コード例 #4
0
        /// <inheritdoc/>
        public async Task <IList <NotificationResponse> > ProcessMeetingNotifications(string applicationName, QueueNotificationItem queueNotificationItem)
        {
            var traceprops = new Dictionary <string, string>();

            traceprops[Constants.Application] = applicationName;
            traceprops[Constants.MeetingNotificationCount] = queueNotificationItem?.NotificationIds.Length.ToString(CultureInfo.InvariantCulture);
            var stopwatch = new Stopwatch();

            stopwatch.Start();
            bool result = false;

            this.logger.WriteCustomEvent("ProcessMeetingNotifications Started", traceprops);
            try
            {
                this.logger.TraceInformation($"Started {nameof(this.ProcessMeetingNotifications)} method of {nameof(EmailServiceManager)}.");
                if (string.IsNullOrWhiteSpace(applicationName))
                {
                    throw new ArgumentException("Application Name cannot be null or empty.", nameof(applicationName));
                }

                if (queueNotificationItem is null)
                {
                    throw new ArgumentNullException(nameof(queueNotificationItem));
                }

                IList <NotificationResponse>          notificationResponses    = new List <NotificationResponse>();
                IList <MeetingNotificationItemEntity> notificationItemEntities = await this.ProcessMeetingNotificationsUsingProvider(applicationName, queueNotificationItem).ConfigureAwait(false);

                var responses = this.emailManager.NotificationEntitiesToResponse(notificationResponses, notificationItemEntities);
                this.logger.TraceInformation($"Finished {nameof(this.ProcessEmailNotifications)} method of {nameof(EmailServiceManager)}.");
                result = true;
                return(responses);
            }
            catch (Exception ex)
            {
                result = true;
                this.logger.WriteException(ex, traceprops);
                throw;
            }
            finally
            {
                stopwatch.Stop();
                traceprops[Constants.Result] = result.ToString(CultureInfo.InvariantCulture);
                var metrics = new Dictionary <string, double>();
                metrics[Constants.Duration] = stopwatch.ElapsedMilliseconds;
                this.logger.WriteCustomEvent("ProcessEmailNotifications Completed", traceprops, metrics);
            }
        }
コード例 #5
0
        public async Task Run([QueueTrigger("notifications-queue", Connection = "AzureWebJobsStorage")] CloudQueueMessage inputQueueItem)
        {
            var stopwatch = new Stopwatch();

            stopwatch.Start();
            var notifQueueItem = inputQueueItem.AsString;
            var traceProps     = new Dictionary <string, string>();

            traceProps["DequeueCount"]   = inputQueueItem.DequeueCount.ToString();
            traceProps["QueueMessageId"] = inputQueueItem.Id;
            traceProps["InsertionTime"]  = inputQueueItem.InsertionTime.ToString();
            this.logger.TraceInformation($"ProcessNotificationQueueItem started processing: {notifQueueItem}");
            QueueNotificationItem queueNotificationItem = null;

            try
            {
                if (string.IsNullOrEmpty(notifQueueItem))
                {
                    throw new ArgumentException("message", nameof(notifQueueItem));
                }

                queueNotificationItem = JsonConvert.DeserializeObject <QueueNotificationItem>(notifQueueItem);

                traceProps[NotificationService.Common.Constants.Application]            = queueNotificationItem?.Application;
                traceProps[NotificationService.Common.Constants.CorrelationId]          = queueNotificationItem?.CorrelationId;
                traceProps[NotificationService.Common.Constants.NotificationIds]        = string.Join(',', queueNotificationItem?.NotificationIds);
                traceProps[NotificationService.Common.Constants.EmailNotificationCount] = string.Join(',', queueNotificationItem?.NotificationIds?.Length);
                traceProps[NotificationService.Common.Constants.NotificationType]       = queueNotificationItem?.NotificationType.ToString();
                this.logger.TraceInformation($"ProcessNotificationQueueItem. Notification Item: {notifQueueItem}", traceProps);
                this.logger.WriteCustomEvent("QueueEmailNotifications Started", traceProps);

                _ = traceProps.Remove(NotificationService.Common.Constants.NotificationIds);
                if (queueNotificationItem != null)
                {
                    var notifType = queueNotificationItem.NotificationType == NotificationType.Mail ? Constants.EmailNotificationType : Constants.MeetingNotificationType;

                    var    stringContent = new StringContent(JsonConvert.SerializeObject(queueNotificationItem), Encoding.UTF8, Constants.JsonMIMEType);
                    string notificationServiceEndpoint = this.configuration?[Constants.NotificationServiceEndpoint];
                    this.logger.TraceVerbose($"ProcessNotificationQueueItem fetching token to call notification service endpoint...", traceProps);

                    this.logger.TraceInformation($"ProcessNotificationQueueItem calling notification service endpoint...", traceProps);
                    var response = await this.httpClientHelper.PostAsync($"{notificationServiceEndpoint}/v1/{notifType}/process/{queueNotificationItem.Application}", stringContent);

                    this.logger.TraceInformation($"ProcessNotificationQueueItem received response from notification service endpoint.", traceProps);
                    if (!response.IsSuccessStatusCode)
                    {
                        var content = await response.Content.ReadAsStringAsync();

                        this.logger.WriteException(new Exception($"An error occurred while processing {notifQueueItem} in ProcessNotificationQueueItem. Details: {content}."), traceProps);
                    }
                }
                else
                {
                    this.logger.WriteException(new Exception("Invalid queue item received by the processor."), traceProps);
                }
            }
            catch (TaskCanceledException ex)
            {
                this.logger.WriteException(ex, traceProps);

                // Ignoring this exception as notification service would process items but http has been timedout here.
            }
            catch (Exception ex)
            {
                string maxDequeueCountVal = Startup.MaxDequeueCount.Value;

                int maxDeqCount;
                if (int.TryParse(maxDequeueCountVal, out maxDeqCount))
                {
                    if (inputQueueItem.DequeueCount < maxDeqCount)
                    {
                        this.logger.WriteException(ex, traceProps);
                        throw;
                    }
                }

                this.logger.WriteException(ex, traceProps);
                await this.UpdateStatusOfNotificationItemsAsync(queueNotificationItem.NotificationIds, NotificationItemStatus.Failed, ex.Message);
            }
            finally
            {
                this.logger.TraceInformation($"ProcessNotificationQueueItem finished processing: {notifQueueItem}", traceProps);
                stopwatch.Stop();

                var metrics = new Dictionary <string, double>();
                metrics[NotificationService.Common.Constants.Duration] = stopwatch.ElapsedMilliseconds;
                this.logger.WriteCustomEvent("QueueEmailNotifications Completed", traceProps, metrics);
            }
        }
コード例 #6
0
        public async Task <IList <NotificationResponse> > ProcessQueuedMeetingNotifications(string applicationName, [FromBody] QueueNotificationItem queueNotificationItem)
        {
            var traceprops = new Dictionary <string, string>();

            if (string.IsNullOrWhiteSpace(applicationName))
            {
                throw new System.ArgumentException("Application Name cannot be null or empty.", nameof(applicationName));
            }

            if (queueNotificationItem is null)
            {
                throw new System.ArgumentNullException(nameof(queueNotificationItem));
            }

            if (queueNotificationItem.NotificationIds.Length == 0)
            {
                throw new ArgumentException("Notification IDs list should not be empty.", nameof(queueNotificationItem));
            }

            traceprops[AIConstants.Application]              = applicationName;
            traceprops[AIConstants.NotificationIds]          = string.Join(',', queueNotificationItem.NotificationIds);
            traceprops[AIConstants.MeetingNotificationCount] = queueNotificationItem.NotificationIds.Length.ToString(CultureInfo.InvariantCulture);

            IList <NotificationResponse> notificationResponses;

            this.logger.TraceInformation($"Started {nameof(this.ProcessQueuedMeetingNotifications)} method of {nameof(EmailController)}.", traceprops);
            notificationResponses = await this.emailServiceManager.ProcessMeetingNotifications(applicationName, queueNotificationItem).ConfigureAwait(false);

            this.logger.TraceInformation($"Finished {nameof(this.ProcessQueuedMeetingNotifications)} method of {nameof(EmailController)}.", traceprops);
            return(notificationResponses);
        }
コード例 #7
0
        /// <summary>
        /// Fetches the records for given notification ids and resends using MS Graph Provider.
        /// </summary>
        /// <param name="applicationName">Application associated with email notifications.</param>
        /// <param name="queueNotificationItem">Queue Notification Entity.</param>
        /// <returns>A <see cref="Task"/> representing the result of the asynchronous operation.</returns>
        private async Task <IList <EmailNotificationItemEntity> > ProcessNotificationsUsingProvider(string applicationName, QueueNotificationItem queueNotificationItem)
        {
            var traceProps = new Dictionary <string, string>();

            traceProps[AIConstants.Application] = applicationName;
            IList <EmailNotificationItemEntity> notSentEntities = new List <EmailNotificationItemEntity>();

            List <string> notificationIds = queueNotificationItem.NotificationIds.ToList();

            traceProps[AIConstants.NotificationIds] = JsonConvert.SerializeObject(notificationIds);
            this.logger.TraceInformation($"Started {nameof(this.ProcessNotificationsUsingProvider)} method of {nameof(EmailServiceManager)}.", traceProps);
            IList <EmailNotificationItemEntity> notificationEntities = await this.emailNotificationRepository.GetEmailNotificationItemEntities(notificationIds, applicationName).ConfigureAwait(false);

            var notificationEntitiesToBeSkipped = new List <EmailNotificationItemEntity>();

            if (notificationEntities.Count == 0)
            {
#pragma warning disable CA2208 // Instantiate argument exceptions correctly
                throw new ArgumentException("No records found for the input notification ids.", nameof(notificationIds));
#pragma warning restore CA2208 // Instantiate argument exceptions correctly
            }

            if (queueNotificationItem.IgnoreAlreadySent)
            {
                notificationEntitiesToBeSkipped = notificationEntities.Where(x => x.Status == NotificationItemStatus.Sent).ToList();
                notificationEntities            = notificationEntities.Where(x => x.Status != NotificationItemStatus.Sent).ToList();
            }

            if (notificationEntities.Count == 0)
            {
                return(notificationEntitiesToBeSkipped);
            }

            var retEntities = await this.ProcessNotificationEntities(applicationName, notificationEntities).ConfigureAwait(false);

            retEntities = retEntities.Concat(notificationEntitiesToBeSkipped).ToList();
            this.logger.TraceInformation($"Completed {nameof(this.ProcessNotificationsUsingProvider)} method of {nameof(EmailServiceManager)}.", traceProps);

            return(retEntities);
        }