/// <summary>
 /// Initializes a new instance of the <see cref="StoreMessageActivity"/> class.
 /// </summary>
 /// <param name="notificationRepo">Sending notification data repository.</param>
 /// <param name="cardCreator">The adaptive card creator.</param>
 public StoreMessageActivity(
     SendingNotificationDataRepository notificationRepo,
     AdaptiveCardCreator cardCreator)
 {
     this.sendingNotificationDataRepository = notificationRepo ?? throw new ArgumentNullException(nameof(notificationRepo));
     this.adaptiveCardCreator = cardCreator ?? throw new ArgumentNullException(nameof(cardCreator));
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="CreateSendingNotificationActivity"/> class.
 /// </summary>
 /// <param name="sendingNotificationDataRepository">Sending notification data repository.</param>
 /// <param name="adaptiveCardCreator">The adaptive card creator.</param>
 public CreateSendingNotificationActivity(
     SendingNotificationDataRepository sendingNotificationDataRepository,
     AdaptiveCardCreator adaptiveCardCreator)
 {
     this.sendingNotificationDataRepository = sendingNotificationDataRepository;
     this.adaptiveCardCreator = adaptiveCardCreator;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="SendingNotificationCreator"/> class.
 /// </summary>
 /// <param name="configuration">The configuration.</param>
 /// <param name="notificationDataRepository">Notification Repository instance.</param>
 /// <param name="sendingNotificationDataRepository">Sending notification data repository.</param>
 /// <param name="adaptiveCardCreator">The adaptive card creator</param>
 public SendingNotificationCreator(
     IConfiguration configuration,
     NotificationDataRepository notificationDataRepository,
     SendingNotificationDataRepository sendingNotificationDataRepository,
     AdaptiveCardCreator adaptiveCardCreator)
 {
     this.microsoftAppId                    = configuration["MicrosoftAppId"];
     this.microsoftAppPassword              = configuration["MicrosoftAppPassword"];
     this.notificationDataRepository        = notificationDataRepository;
     this.sendingNotificationDataRepository = sendingNotificationDataRepository;
     this.adaptiveCardCreator               = adaptiveCardCreator;
 }
Пример #4
0
 /// <summary>
 /// Initializes a new instance of the <see cref="GetSendNotificationParamsService"/> class.
 /// </summary>
 /// <param name="companyCommunicatorSendFunctionOptions">The Company Communicator send function options.</param>
 /// <param name="sendingNotificationDataRepository">The sending notification data repository.</param>
 /// <param name="userDataRepository">The user data repository.</param>
 /// <param name="createUserConversationService">The create user conversation service.</param>
 /// <param name="delaySendingNotificationService">The delay sending notification service.</param>
 /// <param name="manageResultDataService">The manage result data service.</param>
 public GetSendNotificationParamsService(
     IOptions <CompanyCommunicatorSendFunctionOptions> companyCommunicatorSendFunctionOptions,
     SendingNotificationDataRepository sendingNotificationDataRepository,
     UserDataRepository userDataRepository,
     CreateUserConversationService createUserConversationService,
     DelaySendingNotificationService delaySendingNotificationService,
     ManageResultDataService manageResultDataService)
 {
     this.maxNumberOfAttempts               = companyCommunicatorSendFunctionOptions.Value.MaxNumberOfAttempts;
     this.sendRetryDelayNumberOfSeconds     = companyCommunicatorSendFunctionOptions.Value.SendRetryDelayNumberOfSeconds;
     this.sendingNotificationDataRepository = sendingNotificationDataRepository;
     this.userDataRepository              = userDataRepository;
     this.createUserConversationService   = createUserConversationService;
     this.delaySendingNotificationService = delaySendingNotificationService;
     this.manageResultDataService         = manageResultDataService;
 }
Пример #5
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SendFunction"/> class.
        /// </summary>
        /// <param name="options">Send function options.</param>
        /// <param name="notificationService">The service to precheck and determine if the queue message should be processed.</param>
        /// <param name="messageService">Message service.</param>
        /// <param name="notificationRepo">Notification repository.</param>
        /// <param name="sendQueue">The send queue.</param>
        /// <param name="localizer">Localization service.</param>
        public SendFunction(
            IOptions <SendFunctionOptions> options,
            INotificationService notificationService,
            IMessageService messageService,
            SendingNotificationDataRepository notificationRepo,
            SendQueue sendQueue,
            IStringLocalizer <Strings> localizer)
        {
            if (options is null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            this.maxNumberOfAttempts           = options.Value.MaxNumberOfAttempts;
            this.sendRetryDelayNumberOfSeconds = options.Value.SendRetryDelayNumberOfSeconds;

            this.notificationService = notificationService ?? throw new ArgumentNullException(nameof(notificationService));
            this.messageService      = messageService ?? throw new ArgumentNullException(nameof(messageService));
            this.notificationRepo    = notificationRepo ?? throw new ArgumentNullException(nameof(notificationRepo));
            this.sendQueue           = sendQueue ?? throw new ArgumentNullException(nameof(sendQueue));
            this.localizer           = localizer ?? throw new ArgumentNullException(nameof(localizer));
        }
Пример #6
0
        public async Task Run(
            [ServiceBusTrigger(CompanyCommunicatorSendFunction.SendQueueName, Connection = "ServiceBusConnection")]
            string myQueueItem,
            int deliveryCount,
            DateTime enqueuedTimeUtc,
            string messageId,
            ILogger log,
            ExecutionContext context)
        {
            log.LogInformation($"C# ServiceBus queue trigger function processed message: {myQueueItem}");

            IConfiguration configuration = new ConfigurationBuilder()
                                           .SetBasePath(context.FunctionAppDirectory)
                                           .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
                                           .AddEnvironmentVariables()
                                           .Build();

            var messageContent = JsonConvert.DeserializeObject <ServiceBusSendQueueMessageContent>(myQueueItem);

            var totalNumberOfThrottles = 0;

            try
            {
                // Simply initialize the variable for certain build environments and versions
                var maxNumberOfAttempts = 0;

                // If parsing fails, out variable is set to 0, so need to set the default
                if (!int.TryParse(configuration["MaxNumberOfAttempts"], out maxNumberOfAttempts))
                {
                    maxNumberOfAttempts = 1;
                }

                CompanyCommunicatorSendFunction.httpClient = CompanyCommunicatorSendFunction.httpClient
                                                             ?? new HttpClient();

                CompanyCommunicatorSendFunction.userDataRepository = CompanyCommunicatorSendFunction.userDataRepository
                                                                     ?? new UserDataRepository(configuration, isFromAzureFunction: true);

                CompanyCommunicatorSendFunction.sendingNotificationDataRepository = CompanyCommunicatorSendFunction.sendingNotificationDataRepository
                                                                                    ?? new SendingNotificationDataRepository(configuration, isFromAzureFunction: true);

                CompanyCommunicatorSendFunction.globalSendingNotificationDataRepository = CompanyCommunicatorSendFunction.globalSendingNotificationDataRepository
                                                                                          ?? new GlobalSendingNotificationDataRepository(configuration, isFromAzureFunction: true);

                CompanyCommunicatorSendFunction.sentNotificationDataRepository = CompanyCommunicatorSendFunction.sentNotificationDataRepository
                                                                                 ?? new SentNotificationDataRepository(configuration, isFromAzureFunction: true);

                if (CompanyCommunicatorSendFunction.botAccessToken == null ||
                    CompanyCommunicatorSendFunction.botAccessTokenExpiration == null ||
                    DateTime.UtcNow > CompanyCommunicatorSendFunction.botAccessTokenExpiration)
                {
                    await this.FetchTokenAsync(configuration, CompanyCommunicatorSendFunction.httpClient);
                }

                CompanyCommunicatorSendFunction.sendQueueServiceBusMessageSender = CompanyCommunicatorSendFunction.sendQueueServiceBusMessageSender
                                                                                   ?? new MessageSender(configuration["ServiceBusConnection"], CompanyCommunicatorSendFunction.SendQueueName);

                var getActiveNotificationEntityTask = CompanyCommunicatorSendFunction.sendingNotificationDataRepository.GetAsync(
                    PartitionKeyNames.NotificationDataTable.SendingNotificationsPartition,
                    messageContent.NotificationId);

                var getGlobalSendingNotificationDataEntityTask = CompanyCommunicatorSendFunction.globalSendingNotificationDataRepository
                                                                 .GetGlobalSendingNotificationDataEntity();

                var incomingUserDataEntity = messageContent.UserDataEntity;
                var incomingConversationId = incomingUserDataEntity.ConversationId;

                var getUserDataEntityTask = string.IsNullOrWhiteSpace(incomingConversationId)
                    ? CompanyCommunicatorSendFunction.userDataRepository.GetAsync(
                    PartitionKeyNames.UserDataTable.UserDataPartition,
                    incomingUserDataEntity.AadId)
                    : Task.FromResult <UserDataEntity>(null);

                await Task.WhenAll(getActiveNotificationEntityTask, getGlobalSendingNotificationDataEntityTask, getUserDataEntityTask);

                var activeNotificationEntity            = await getActiveNotificationEntityTask;
                var globalSendingNotificationDataEntity = await getGlobalSendingNotificationDataEntityTask;
                var userDataEntity = await getUserDataEntityTask;

                var conversationId = string.IsNullOrWhiteSpace(incomingConversationId)
                    ? userDataEntity?.ConversationId
                    : incomingConversationId;

                Task saveUserDataEntityTask              = Task.CompletedTask;
                Task saveSentNotificationDataTask        = Task.CompletedTask;
                Task setDelayTimeAndSendDelayedRetryTask = Task.CompletedTask;

                if (globalSendingNotificationDataEntity?.SendRetryDelayTime != null &&
                    DateTime.UtcNow < globalSendingNotificationDataEntity.SendRetryDelayTime)
                {
                    await this.SendDelayedRetryOfMessageToSendFunction(configuration, messageContent);

                    return;
                }

                if (!string.IsNullOrWhiteSpace(conversationId))
                {
                    incomingUserDataEntity.ConversationId = conversationId;

                    // Check if message is intended for a team
                    if (!conversationId.StartsWith("19:"))
                    {
                        incomingUserDataEntity.PartitionKey = PartitionKeyNames.UserDataTable.UserDataPartition;
                        incomingUserDataEntity.RowKey       = incomingUserDataEntity.AadId;

                        var operation = TableOperation.InsertOrMerge(incomingUserDataEntity);

                        saveUserDataEntityTask = CompanyCommunicatorSendFunction.userDataRepository.Table.ExecuteAsync(operation);
                    }
                }
                else
                {
                    var isCreateConversationThrottled = false;

                    for (int i = 0; i < maxNumberOfAttempts; i++)
                    {
                        var createConversationUrl = $"{incomingUserDataEntity.ServiceUrl}v3/conversations";
                        using (var requestMessage = new HttpRequestMessage(HttpMethod.Post, createConversationUrl))
                        {
                            requestMessage.Headers.Authorization = new AuthenticationHeaderValue(
                                "Bearer",
                                CompanyCommunicatorSendFunction.botAccessToken);

                            var payloadString = "{\"bot\": { \"id\": \"28:" + configuration["MicrosoftAppId"] + "\"},\"isGroup\": false, \"tenantId\": \"" + incomingUserDataEntity.TenantId + "\", \"members\": [{\"id\": \"" + incomingUserDataEntity.UserId + "\"}]}";
                            requestMessage.Content = new StringContent(payloadString, Encoding.UTF8, "application/json");

                            using (var sendResponse = await CompanyCommunicatorSendFunction.httpClient.SendAsync(requestMessage))
                            {
                                if (sendResponse.StatusCode == HttpStatusCode.Created)
                                {
                                    var jsonResponseString = await sendResponse.Content.ReadAsStringAsync();

                                    dynamic resp = JsonConvert.DeserializeObject(jsonResponseString);

                                    incomingUserDataEntity.PartitionKey   = PartitionKeyNames.UserDataTable.UserDataPartition;
                                    incomingUserDataEntity.RowKey         = incomingUserDataEntity.AadId;
                                    incomingUserDataEntity.ConversationId = resp.id;

                                    var operation = TableOperation.InsertOrMerge(incomingUserDataEntity);

                                    saveUserDataEntityTask = CompanyCommunicatorSendFunction.userDataRepository.Table.ExecuteAsync(operation);

                                    isCreateConversationThrottled = false;

                                    break;
                                }
                                else if (sendResponse.StatusCode == HttpStatusCode.TooManyRequests)
                                {
                                    isCreateConversationThrottled = true;

                                    totalNumberOfThrottles++;

                                    // Do not delay if already attempted the maximum number of attempts.
                                    if (i != maxNumberOfAttempts - 1)
                                    {
                                        var random = new Random();
                                        await Task.Delay(random.Next(500, 1500));
                                    }
                                }
                                else
                                {
                                    await this.SaveSentNotificationData(
                                        configuration,
                                        messageContent.NotificationId,
                                        incomingUserDataEntity.AadId,
                                        totalNumberOfThrottles,
                                        isStatusCodeFromCreateConversation : true,
                                        statusCode : sendResponse.StatusCode);

                                    return;
                                }
                            }
                        }
                    }

                    if (isCreateConversationThrottled)
                    {
                        await this.SetDelayTimeAndSendDelayedRetry(configuration, messageContent);

                        return;
                    }
                }

                var isSendMessageThrottled = false;

                for (int i = 0; i < maxNumberOfAttempts; i++)
                {
                    var conversationUrl = $"{incomingUserDataEntity.ServiceUrl}v3/conversations/{incomingUserDataEntity.ConversationId}/activities";
                    using (var requestMessage = new HttpRequestMessage(HttpMethod.Post, conversationUrl))
                    {
                        requestMessage.Headers.Authorization = new AuthenticationHeaderValue(
                            "Bearer",
                            CompanyCommunicatorSendFunction.botAccessToken);

                        var attachmentJsonString = JsonConvert.DeserializeObject(activeNotificationEntity.Content);
                        var messageString        = "{ \"type\": \"message\", \"attachments\": [ { \"contentType\": \"application/vnd.microsoft.card.adaptive\", \"content\": " + attachmentJsonString + " } ] }";
                        requestMessage.Content = new StringContent(messageString, Encoding.UTF8, "application/json");

                        using (var sendResponse = await CompanyCommunicatorSendFunction.httpClient.SendAsync(requestMessage))
                        {
                            if (sendResponse.StatusCode == HttpStatusCode.Created)
                            {
                                log.LogInformation("MESSAGE SENT SUCCESSFULLY");

                                saveSentNotificationDataTask = this.SaveSentNotificationData(
                                    configuration,
                                    messageContent.NotificationId,
                                    incomingUserDataEntity.AadId,
                                    totalNumberOfThrottles,
                                    isStatusCodeFromCreateConversation: false,
                                    statusCode: sendResponse.StatusCode);

                                isSendMessageThrottled = false;

                                break;
                            }
                            else if (sendResponse.StatusCode == HttpStatusCode.TooManyRequests)
                            {
                                log.LogError("MESSAGE THROTTLED");

                                isSendMessageThrottled = true;

                                totalNumberOfThrottles++;

                                // Do not delay if already attempted the maximum number of attempts.
                                if (i != maxNumberOfAttempts - 1)
                                {
                                    var random = new Random();
                                    await Task.Delay(random.Next(500, 1500));
                                }
                            }
                            else
                            {
                                log.LogError($"MESSAGE FAILED: {sendResponse.StatusCode}");

                                saveSentNotificationDataTask = this.SaveSentNotificationData(
                                    configuration,
                                    messageContent.NotificationId,
                                    incomingUserDataEntity.AadId,
                                    totalNumberOfThrottles,
                                    isStatusCodeFromCreateConversation: false,
                                    statusCode: sendResponse.StatusCode);

                                await Task.WhenAll(saveUserDataEntityTask, saveSentNotificationDataTask);

                                return;
                            }
                        }
                    }
                }

                if (isSendMessageThrottled)
                {
                    setDelayTimeAndSendDelayedRetryTask =
                        this.SetDelayTimeAndSendDelayedRetry(configuration, messageContent);
                }

                await Task.WhenAll(
                    saveUserDataEntityTask,
                    saveSentNotificationDataTask,
                    setDelayTimeAndSendDelayedRetryTask);
            }
            catch (Exception e)
            {
                log.LogError(e, $"ERROR: {e.Message}, {e.GetType()}");

                var statusCodeToStore = HttpStatusCode.Continue;
                if (deliveryCount >= CompanyCommunicatorSendFunction.MaxDeliveryCountForDeadLetter)
                {
                    statusCodeToStore = HttpStatusCode.InternalServerError;
                }

                await this.SaveSentNotificationData(
                    configuration,
                    messageContent.NotificationId,
                    messageContent.UserDataEntity.AadId,
                    totalNumberOfThrottles,
                    isStatusCodeFromCreateConversation : false,
                    statusCode : statusCodeToStore);

                throw e;
            }
        }
        public async Task Run(
            [ServiceBusTrigger("company-communicator-data", Connection = "ServiceBusConnection")]
            string myQueueItem,
            int deliveryCount,
            DateTime enqueuedTimeUtc,
            string messageId,
            ILogger log,
            ExecutionContext context)
        {
            CompanyCommunicatorDataFunction.configuration = CompanyCommunicatorDataFunction.configuration ??
                                                            new ConfigurationBuilder()
                                                            .AddEnvironmentVariables()
                                                            .Build();

            // Simply initialize the variable for certain build environments and versions
            var maxMinutesOfRetryingDataFunction = 0;

            // If parsing fails, out variable is set to 0, so need to set the default
            if (!int.TryParse(CompanyCommunicatorDataFunction.configuration["MaxMinutesOfRetryingDataFunction"], out maxMinutesOfRetryingDataFunction))
            {
                maxMinutesOfRetryingDataFunction = 1440;
            }

            var messageContent = JsonConvert.DeserializeObject <ServiceBusDataQueueMessageContent>(myQueueItem);

            CompanyCommunicatorDataFunction.sentNotificationDataRepository = CompanyCommunicatorDataFunction.sentNotificationDataRepository
                                                                             ?? new SentNotificationDataRepository(CompanyCommunicatorDataFunction.configuration, isFromAzureFunction: true);

            CompanyCommunicatorDataFunction.notificationDataRepository = CompanyCommunicatorDataFunction.notificationDataRepository
                                                                         ?? this.CreateNotificationRepository(CompanyCommunicatorDataFunction.configuration);

            CompanyCommunicatorDataFunction.sendingNotificationDataRepository = CompanyCommunicatorDataFunction.sendingNotificationDataRepository
                                                                                ?? new SendingNotificationDataRepository(CompanyCommunicatorDataFunction.configuration, isFromAzureFunction: true);

            var sentNotificationDataEntities = await CompanyCommunicatorDataFunction.sentNotificationDataRepository.GetAllAsync(
                messageContent.NotificationId);

            if (sentNotificationDataEntities == null)
            {
                if (DateTime.UtcNow >= messageContent.InitialSendDate + TimeSpan.FromMinutes(maxMinutesOfRetryingDataFunction))
                {
                    await this.SetEmptyNotificationDataEntity(messageContent.NotificationId);

                    return;
                }

                await this.SendTriggerToDataFunction(CompanyCommunicatorDataFunction.configuration, messageContent);

                return;
            }

            var succeededCount = 0;
            var failedCount    = 0;
            var throttledCount = 0;
            var unknownCount   = 0;

            DateTime lastSentDateTime = DateTime.MinValue;

            foreach (var sentNotificationDataEntity in sentNotificationDataEntities)
            {
                if (sentNotificationDataEntity.StatusCode == (int)HttpStatusCode.Created)
                {
                    succeededCount++;
                }
                else if (sentNotificationDataEntity.StatusCode == (int)HttpStatusCode.TooManyRequests)
                {
                    throttledCount++;
                }
                else if (sentNotificationDataEntity.StatusCode == 0)
                {
                    unknownCount++;
                }
                else
                {
                    failedCount++;
                }

                if (sentNotificationDataEntity.SentDate != null &&
                    sentNotificationDataEntity.SentDate > lastSentDateTime)
                {
                    lastSentDateTime = sentNotificationDataEntity.SentDate;
                }
            }

            var notificationDataEntityUpdate = new UpdateNotificationDataEntity
            {
                PartitionKey = PartitionKeyNames.NotificationDataTable.SentNotificationsPartition,
                RowKey       = messageContent.NotificationId,
                Succeeded    = succeededCount,
                Failed       = failedCount,
                Throttled    = throttledCount,
                Unknown      = unknownCount,
            };

            // Purposefully exclude the unknown count because those messages may be sent later
            var currentMessageCount = succeededCount
                                      + failedCount
                                      + throttledCount;

            if (currentMessageCount == messageContent.TotalMessageCount ||
                DateTime.UtcNow >= messageContent.InitialSendDate + TimeSpan.FromMinutes(maxMinutesOfRetryingDataFunction))
            {
                notificationDataEntityUpdate.IsCompleted = true;
                notificationDataEntityUpdate.SentDate    = lastSentDateTime != DateTime.MinValue
                    ? lastSentDateTime
                    : DateTime.UtcNow;
            }
            else
            {
                await this.SendTriggerToDataFunction(CompanyCommunicatorDataFunction.configuration, messageContent);
            }

            var operation = TableOperation.InsertOrMerge(notificationDataEntityUpdate);

            await CompanyCommunicatorDataFunction.notificationDataRepository.Table.ExecuteAsync(operation);
        }
        public async Task RunAsync(
            [TimerTrigger("0 */30 * * * *")]
            TimerInfo scheduleInitializationTimer,
            ILogger log)
        {
            scheduleInitializationTimer = scheduleInitializationTimer ?? throw new ArgumentNullException(nameof(scheduleInitializationTimer));

            log.LogInformation($"Schedule Initialization Timer executed at: {scheduleInitializationTimer.ToString()}.");

            CompanyCommunicatorScheduleFunction.configuration = CompanyCommunicatorScheduleFunction.configuration ??
                                                                new ConfigurationBuilder()
                                                                .AddEnvironmentVariables()
                                                                .Build();

            CompanyCommunicatorScheduleFunction.adaptiveCardCreator = CompanyCommunicatorScheduleFunction.adaptiveCardCreator
                                                                      ?? new AdaptiveCardCreator();

            CompanyCommunicatorScheduleFunction.tableRowKeyGenerator = CompanyCommunicatorScheduleFunction.tableRowKeyGenerator
                                                                       ?? new TableRowKeyGenerator();

            CompanyCommunicatorScheduleFunction.adGroupsDataRepository = CompanyCommunicatorScheduleFunction.adGroupsDataRepository
                                                                         ?? new ADGroupsDataRepository(CompanyCommunicatorScheduleFunction.configuration, true);

            CompanyCommunicatorScheduleFunction.notificationDataRepository = CompanyCommunicatorScheduleFunction.notificationDataRepository
                                                                             ?? new NotificationDataRepository(CompanyCommunicatorScheduleFunction.configuration, CompanyCommunicatorScheduleFunction.adGroupsDataRepository, tableRowKeyGenerator, true);

            CompanyCommunicatorScheduleFunction.userDataRepository = CompanyCommunicatorScheduleFunction.userDataRepository
                                                                     ?? new UserDataRepository(CompanyCommunicatorScheduleFunction.configuration, true);

            CompanyCommunicatorScheduleFunction.teamDataRepository = CompanyCommunicatorScheduleFunction.teamDataRepository
                                                                     ?? new TeamDataRepository(CompanyCommunicatorScheduleFunction.configuration, true);

            CompanyCommunicatorScheduleFunction.sendingNotificationDataRepository = CompanyCommunicatorScheduleFunction.sendingNotificationDataRepository
                                                                                    ?? new SendingNotificationDataRepository(CompanyCommunicatorScheduleFunction.configuration, true);

            CompanyCommunicatorScheduleFunction.globalSendingNotificationDataRepository = CompanyCommunicatorScheduleFunction.globalSendingNotificationDataRepository
                                                                                          ?? new GlobalSendingNotificationDataRepository(CompanyCommunicatorScheduleFunction.configuration, true);

            CompanyCommunicatorScheduleFunction.sentNotificationDataRepository = CompanyCommunicatorScheduleFunction.sentNotificationDataRepository
                                                                                 ?? new SentNotificationDataRepository(CompanyCommunicatorScheduleFunction.configuration, true);

            CompanyCommunicatorScheduleFunction.metadataProvider = CompanyCommunicatorScheduleFunction.metadataProvider
                                                                   ?? new MetadataProvider(CompanyCommunicatorScheduleFunction.configuration, userDataRepository, teamDataRepository, notificationDataRepository, adGroupsDataRepository);

            CompanyCommunicatorScheduleFunction.sendingNotificationCreator = CompanyCommunicatorScheduleFunction.sendingNotificationCreator
                                                                             ?? new SendingNotificationCreator(CompanyCommunicatorScheduleFunction.configuration, notificationDataRepository, sendingNotificationDataRepository, adaptiveCardCreator);

            CompanyCommunicatorScheduleFunction.scheduleNotificationDelivery = CompanyCommunicatorScheduleFunction.scheduleNotificationDelivery
                                                                               ?? new ScheduleNotificationDelivery(CompanyCommunicatorScheduleFunction.configuration, notificationDataRepository, metadataProvider, sendingNotificationCreator, scheduleNotificationDataRepository, teamDataRepository);

            CompanyCommunicatorScheduleFunction.scheduleNotificationDataRepository = CompanyCommunicatorScheduleFunction.scheduleNotificationDataRepository
                                                                                     ?? new ScheduleNotificationDataRepository(CompanyCommunicatorScheduleFunction.configuration, notificationDataRepository, metadataProvider, sendingNotificationCreator, scheduleNotificationDelivery, true);

            // Generate filter condition to get pending notifications.
            var rowKeyFilter = TableQuery.GenerateFilterConditionForDate(
                nameof(ScheduleNotificationDataEntity.NotificationDate),
                QueryComparisons.LessThanOrEqual,
                DateTime.UtcNow);

            // Get records which are pending to send notification.
            var pendingNotifications = await CompanyCommunicatorScheduleFunction.scheduleNotificationDataRepository.GetWithFilterAsync(
                rowKeyFilter);

            // Repeat all pending notifications.
            foreach (var pendingNotification in pendingNotifications)
            {
                try
                {
                    log.LogInformation($"Schedule notification triggered for " + pendingNotification.NotificationId);
                    string returnMessage = await CompanyCommunicatorScheduleFunction.scheduleNotificationDataRepository.SendNotificationandCreateScheduleAsync(pendingNotification);

                    if (string.IsNullOrEmpty(returnMessage))
                    {
                        log.LogInformation($"Schedule notification success for " + pendingNotification.NotificationId);
                    }
                    else
                    {
                        log.LogInformation($"Schedule notification failed for " + pendingNotification.NotificationId);
                    }
                }
                catch (Exception ex)
                {
                    log.LogError($"Error while sending schedule notification:" + pendingNotification.NotificationId, ex);
                }
            }
        }
        public async Task <IActionResult> RunAsync(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req,
            ILogger log)
        {
            //  scheduleInitializationTimer = scheduleInitializationTimer ?? throw new ArgumentNullException(nameof(scheduleInitializationTimer));

            //log.LogInformation($"Schedule Initialization Timer executed at: {scheduleInitializationTimer.ToString()}.");

            SchduleNotificationTestFunction.configuration = SchduleNotificationTestFunction.configuration ??
                                                            new ConfigurationBuilder()
                                                            .AddEnvironmentVariables()
                                                            .Build();

            SchduleNotificationTestFunction.adaptiveCardCreator = SchduleNotificationTestFunction.adaptiveCardCreator
                                                                  ?? new AdaptiveCardCreator();

            SchduleNotificationTestFunction.tableRowKeyGenerator = SchduleNotificationTestFunction.tableRowKeyGenerator
                                                                   ?? new TableRowKeyGenerator();

            SchduleNotificationTestFunction.adGroupsDataRepository = SchduleNotificationTestFunction.adGroupsDataRepository
                                                                     ?? new ADGroupsDataRepository(SchduleNotificationTestFunction.configuration, true);

            SchduleNotificationTestFunction.notificationDataRepository = SchduleNotificationTestFunction.notificationDataRepository
                                                                         ?? new NotificationDataRepository(SchduleNotificationTestFunction.configuration, SchduleNotificationTestFunction.adGroupsDataRepository, tableRowKeyGenerator, true);

            SchduleNotificationTestFunction.userDataRepository = SchduleNotificationTestFunction.userDataRepository
                                                                 ?? new UserDataRepository(SchduleNotificationTestFunction.configuration, true);

            SchduleNotificationTestFunction.teamDataRepository = SchduleNotificationTestFunction.teamDataRepository
                                                                 ?? new TeamDataRepository(SchduleNotificationTestFunction.configuration, true);

            SchduleNotificationTestFunction.sendingNotificationDataRepository = SchduleNotificationTestFunction.sendingNotificationDataRepository
                                                                                ?? new SendingNotificationDataRepository(SchduleNotificationTestFunction.configuration, true);

            SchduleNotificationTestFunction.globalSendingNotificationDataRepository = SchduleNotificationTestFunction.globalSendingNotificationDataRepository
                                                                                      ?? new GlobalSendingNotificationDataRepository(SchduleNotificationTestFunction.configuration, true);

            SchduleNotificationTestFunction.sentNotificationDataRepository = SchduleNotificationTestFunction.sentNotificationDataRepository
                                                                             ?? new SentNotificationDataRepository(SchduleNotificationTestFunction.configuration, true);

            SchduleNotificationTestFunction.metadataProvider = SchduleNotificationTestFunction.metadataProvider
                                                               ?? new MetadataProvider(SchduleNotificationTestFunction.configuration, userDataRepository, teamDataRepository, notificationDataRepository, adGroupsDataRepository);

            SchduleNotificationTestFunction.sendingNotificationCreator = SchduleNotificationTestFunction.sendingNotificationCreator
                                                                         ?? new SendingNotificationCreator(SchduleNotificationTestFunction.configuration, notificationDataRepository, sendingNotificationDataRepository, adaptiveCardCreator);

            SchduleNotificationTestFunction.scheduleNotificationDelivery = SchduleNotificationTestFunction.scheduleNotificationDelivery
                                                                           ?? new ScheduleNotificationDelivery(SchduleNotificationTestFunction.configuration, notificationDataRepository, metadataProvider, sendingNotificationCreator, scheduleNotificationDataRepository, teamDataRepository);

            SchduleNotificationTestFunction.scheduleNotificationDataRepository = SchduleNotificationTestFunction.scheduleNotificationDataRepository
                                                                                 ?? new ScheduleNotificationDataRepository(SchduleNotificationTestFunction.configuration, notificationDataRepository, metadataProvider, sendingNotificationCreator, scheduleNotificationDelivery, true);

            // Generate filter condition to get pending notifications.
            var rowKeyFilter = TableQuery.GenerateFilterConditionForDate(
                nameof(ScheduleNotificationDataEntity.NotificationDate),
                QueryComparisons.LessThanOrEqual,
                DateTime.UtcNow);

            // Get records which are pending to send notification.
            var pendingNotifications = await SchduleNotificationTestFunction.scheduleNotificationDataRepository.GetWithFilterAsync(
                rowKeyFilter);

            // Repeat all pending notifications.
            foreach (var pendingNotification in pendingNotifications)
            {
                try
                {
                    log.LogInformation($"Schedule notification triggered for " + pendingNotification.NotificationId);
                    string returnMessage = await SchduleNotificationTestFunction.scheduleNotificationDataRepository.SendNotificationandCreateScheduleAsync(pendingNotification);

                    if (string.IsNullOrEmpty(returnMessage))
                    {
                        log.LogInformation($"Schedule notification success for " + pendingNotification.NotificationId);
                    }
                    else
                    {
                        log.LogInformation($"Schedule notification failed for " + pendingNotification.NotificationId);
                    }
                }
                catch (Exception ex)
                {
                    log.LogError($"Error while sending schedule notification:" + pendingNotification.NotificationId, ex);
                }
            }

            return(await Task.FromResult((ActionResult) new OkObjectResult("OK")));
        }