/// <summary> /// Initializes a new instance of the <see cref="InitializeorFailGroupMembersActivity"/> class. /// </summary> /// <param name="sentNotificationDataRepository">Sent notification data repository.</param> /// <param name="getUserDataEntitiesByIdActivity">get user data entities by id activity.</param> public InitializeorFailGroupMembersActivity( SentNotificationDataRepository sentNotificationDataRepository, GetUserDataEntitiesByIdsActivity getUserDataEntitiesByIdActivity) { this.sentNotificationDataRepository = sentNotificationDataRepository; this.getUserDataEntitiesByIdActivity = getUserDataEntitiesByIdActivity; }
/// <summary> /// Initializes a new instance of the <see cref="GetRecipientDataListForTeamsActivity"/> class. /// </summary> /// <param name="sentNotificationDataRepository">Sent notification data repository.</param> /// <param name="sendBatchesDataRepository">The send batches data repository.</param> public GetRecipientDataListForTeamsActivity( SentNotificationDataRepository sentNotificationDataRepository, SendBatchesDataRepository sendBatchesDataRepository) { this.sentNotificationDataRepository = sentNotificationDataRepository; this.sendBatchesDataRepository = sendBatchesDataRepository; }
/// <summary> /// Initializes a new instance of the <see cref="NotificationService"/> class. /// </summary> /// <param name="globalSendingNotificationDataRepository">The global sending notification data repository.</param> /// <param name="sentNotificationDataRepository">The sent notification data repository.</param> public NotificationService( GlobalSendingNotificationDataRepository globalSendingNotificationDataRepository, SentNotificationDataRepository sentNotificationDataRepository) { this.globalSendingNotificationDataRepository = globalSendingNotificationDataRepository ?? throw new ArgumentNullException(nameof(globalSendingNotificationDataRepository)); this.sentNotificationDataRepository = sentNotificationDataRepository ?? throw new ArgumentNullException(nameof(sentNotificationDataRepository)); }
/// <summary> /// Initializes a new instance of the <see cref="ProcessRecipientDataListActivity"/> class. /// </summary> /// <param name="sentNotificationDataRepository">The sent notification data repository.</param> /// <param name="sendBatchesDataRepository">The send batches data repository.</param> public ProcessRecipientDataListActivity( SentNotificationDataRepository sentNotificationDataRepository, SendBatchesDataRepository sendBatchesDataRepository) { this.sentNotificationDataRepository = sentNotificationDataRepository; this.sendBatchesDataRepository = sendBatchesDataRepository; }
/// <summary> /// Initializes a new instance of the <see cref="SentNotificationsController"/> class. /// </summary> /// <param name="notificationDataRepository">Notification data repository service that deals with the table storage in azure.</param> /// <param name="sentNotificationDataRepository">Sent notification data repository.</param> /// <param name="teamDataRepository">Team data repository instance.</param> /// <param name="prepareToSendQueue">The service bus queue for preparing to send notifications.</param> /// <param name="dataQueue">The service bus queue for the data queue.</param> /// <param name="dataQueueMessageOptions">The options for the data queue messages.</param> /// <param name="groupsService">The groups service.</param> /// <param name="exportDataRepository">The Export data repository instance.</param> /// <param name="appCatalogService">App catalog service.</param> /// <param name="appSettingsService">App settings service.</param> /// <param name="userAppOptions">User app options.</param> /// <param name="loggerFactory">The logger factory.</param> public SentNotificationsController( NotificationDataRepository notificationDataRepository, SentNotificationDataRepository sentNotificationDataRepository, TeamDataRepository teamDataRepository, PrepareToSendQueue prepareToSendQueue, DataQueue dataQueue, IOptions <DataQueueMessageOptions> dataQueueMessageOptions, IGroupsService groupsService, ExportDataRepository exportDataRepository, IAppCatalogService appCatalogService, IAppSettingsService appSettingsService, IOptions <UserAppOptions> userAppOptions, ILoggerFactory loggerFactory) { if (dataQueueMessageOptions is null) { throw new ArgumentNullException(nameof(dataQueueMessageOptions)); } this.notificationDataRepository = notificationDataRepository ?? throw new ArgumentNullException(nameof(notificationDataRepository)); this.sentNotificationDataRepository = sentNotificationDataRepository ?? throw new ArgumentNullException(nameof(sentNotificationDataRepository)); this.teamDataRepository = teamDataRepository ?? throw new ArgumentNullException(nameof(teamDataRepository)); this.prepareToSendQueue = prepareToSendQueue ?? throw new ArgumentNullException(nameof(prepareToSendQueue)); this.dataQueue = dataQueue ?? throw new ArgumentNullException(nameof(dataQueue)); this.forceCompleteMessageDelayInSeconds = dataQueueMessageOptions.Value.ForceCompleteMessageDelayInSeconds; this.groupsService = groupsService ?? throw new ArgumentNullException(nameof(groupsService)); this.exportDataRepository = exportDataRepository ?? throw new ArgumentNullException(nameof(exportDataRepository)); this.appCatalogService = appCatalogService ?? throw new ArgumentNullException(nameof(appCatalogService)); this.appSettingsService = appSettingsService ?? throw new ArgumentNullException(nameof(appSettingsService)); this.userAppOptions = userAppOptions?.Value ?? throw new ArgumentNullException(nameof(userAppOptions)); this.logger = loggerFactory?.CreateLogger <SentNotificationsController>() ?? throw new ArgumentNullException(nameof(loggerFactory)); }
/// <summary> /// Initializes a new instance of the <see cref="DataStreamFacade"/> class. /// </summary> /// <param name="sentNotificationDataRepository">the sent notification data repository.</param> /// <param name="teamDataRepository">the team data repository.</param> /// <param name="usersService">the users service.</param> public DataStreamFacade( SentNotificationDataRepository sentNotificationDataRepository, TeamDataRepository teamDataRepository, IUsersService usersService) { this.sentNotificationDataRepository = sentNotificationDataRepository; this.teamDataRepository = teamDataRepository; this.usersService = usersService; }
/// <summary> /// Initializes a new instance of the <see cref="PrecheckService"/> class. /// </summary> /// <param name="globalSendingNotificationDataRepository">The global sending notification data repository.</param> /// <param name="sentNotificationDataRepository">The sent notification data repository.</param> /// <param name="sendQueue">The send queue.</param> public PrecheckService( GlobalSendingNotificationDataRepository globalSendingNotificationDataRepository, SentNotificationDataRepository sentNotificationDataRepository, SendQueue sendQueue) { this.globalSendingNotificationDataRepository = globalSendingNotificationDataRepository; this.sentNotificationDataRepository = sentNotificationDataRepository; this.sendQueue = sendQueue; }
/// <summary> /// Initializes a new instance of the <see cref="TeamsDataCapture"/> class. /// </summary> /// <param name="teamDataRepository">Team data repository instance.</param> /// <param name="userDataRepository">User data repository instance.</param> /// <param name="sentNotificationDataRepository">sentNotificationDataRepository Data Repository instance.</param> public TeamsDataCapture( TeamDataRepository teamDataRepository, UserDataRepository userDataRepository, SentNotificationDataRepository sentNotificationDataRepository) { this.teamDataRepository = teamDataRepository; this.userDataRepository = userDataRepository; this.sentNotificationDataRepository = sentNotificationDataRepository; }
/// <summary> /// Initializes a new instance of the <see cref="ExportController"/> class. /// </summary> /// <param name="sentNotificationDataRepository">SentNotification data repository instance.</param> /// <param name="exportDataRepository">Export data repository instance.</param> /// <param name="userDataRepository">User data repository instance.</param> /// <param name="exportQueue">The service bus queue for the export queue.</param> public ExportController( SentNotificationDataRepository sentNotificationDataRepository, ExportDataRepository exportDataRepository, UserDataRepository userDataRepository, ExportQueue exportQueue) { this.sentNotificationDataRepository = sentNotificationDataRepository; this.exportDataRepository = exportDataRepository; this.userDataRepository = userDataRepository; this.exportQueue = exportQueue; }
/// <summary> /// Initializes a new instance of the <see cref="SyncTeamsActivity"/> class. /// </summary> /// <param name="teamDataRepository">Team Data repository.</param> /// <param name="sentNotificationDataRepository">Sent notification data repository.</param> /// <param name="localizer">Localization service.</param> /// <param name="notificationDataRepository">Notification data entity repository.</param> public SyncTeamsActivity( TeamDataRepository teamDataRepository, SentNotificationDataRepository sentNotificationDataRepository, IStringLocalizer <Strings> localizer, NotificationDataRepository notificationDataRepository) { this.teamDataRepository = teamDataRepository ?? throw new ArgumentNullException(nameof(teamDataRepository)); this.sentNotificationDataRepository = sentNotificationDataRepository ?? throw new ArgumentNullException(nameof(sentNotificationDataRepository)); this.localizer = localizer ?? throw new ArgumentNullException(nameof(localizer)); this.notificationDataRepository = notificationDataRepository ?? throw new ArgumentNullException(nameof(notificationDataRepository)); }
/// <summary> /// Initializes a new instance of the <see cref="DataStreamFacade"/> class. /// </summary> /// <param name="sentNotificationDataRepository">the sent notification data repository.</param> /// <param name="teamDataRepository">the team data repository.</param> /// <param name="usersService">the users service.</param> /// <param name="localizer">Localization service.</param> public DataStreamFacade( SentNotificationDataRepository sentNotificationDataRepository, TeamDataRepository teamDataRepository, IUsersService usersService, IStringLocalizer <Strings> localizer) { this.sentNotificationDataRepository = sentNotificationDataRepository; this.teamDataRepository = teamDataRepository; this.usersService = usersService; this.localizer = localizer ?? throw new ArgumentNullException(nameof(localizer)); }
/// <summary> /// Initializes a new instance of the <see cref="SentNotificationsController"/> class. /// </summary> /// <param name="notificationDataRepository">Notification data repository service that deals with the table storage in azure.</param> /// <param name="notificationDelivery">Notification delivery service instance.</param> /// <param name="teamDataRepository">Team data repository instance.</param> /// <param name="scheduleNotificationDataRepository">Schedule notification data repository.</param> /// <param name="sentNotificationDataRepository">Sent Notification Data Repository.</param> public SentNotificationsController( NotificationDataRepository notificationDataRepository, NotificationDelivery notificationDelivery, TeamDataRepository teamDataRepository, ScheduleNotificationDataRepository scheduleNotificationDataRepository, SentNotificationDataRepository sentNotificationDataRepository) { this.notificationDataRepository = notificationDataRepository; this.notificationDelivery = notificationDelivery; this.teamDataRepository = teamDataRepository; this.scheduleNotificationDataRepository = scheduleNotificationDataRepository; this.sentNotificationDataRepository = sentNotificationDataRepository; }
/// <summary> /// Initializes a new instance of the <see cref="SyncAllUsersActivity"/> class. /// </summary> /// <param name="userDataRepository">User Data repository.</param> /// <param name="sentNotificationDataRepository">Sent notification data repository.</param> /// <param name="usersService">Users service.</param> /// <param name="notificationDataRepository">Notification data entity repository.</param> /// <param name="localizer">Localization service.</param> public SyncAllUsersActivity( UserDataRepository userDataRepository, SentNotificationDataRepository sentNotificationDataRepository, IUsersService usersService, NotificationDataRepository notificationDataRepository, IStringLocalizer <Strings> localizer) { this.userDataRepository = userDataRepository ?? throw new ArgumentNullException(nameof(userDataRepository)); this.sentNotificationDataRepository = sentNotificationDataRepository ?? throw new ArgumentNullException(nameof(sentNotificationDataRepository)); this.usersService = usersService ?? throw new ArgumentNullException(nameof(usersService)); this.notificationDataRepository = notificationDataRepository ?? throw new ArgumentNullException(nameof(notificationDataRepository)); this.localizer = localizer ?? throw new ArgumentNullException(nameof(localizer)); }
/// <summary> /// Initializes a new instance of the <see cref="NotificationDelivery"/> class. /// </summary> /// <param name="configuration">The configuration.</param> /// <param name="notificationDataRepository">Notification repository service.</param> /// <param name="metadataProvider">Metadata Provider instance.</param> /// <param name="sendingNotificationCreator">SendingNotification creator.</param> /// <param name="sentNotificationDataRepository">Sent notification data repository.</param> public NotificationDelivery( IConfiguration configuration, NotificationDataRepository notificationDataRepository, MetadataProvider metadataProvider, SendingNotificationCreator sendingNotificationCreator, SentNotificationDataRepository sentNotificationDataRepository) { this.configuration = configuration; this.notificationDataRepository = notificationDataRepository; this.metadataProvider = metadataProvider; this.sendingNotificationCreator = sendingNotificationCreator; this.sentNotificationDataRepository = sentNotificationDataRepository; }
/// <summary> /// Initializes a new instance of the <see cref="SyncTeamMembersActivity"/> class. /// </summary> /// <param name="teamDataRepository">Team Data repository.</param> /// <param name="memberService">Teams member service.</param> /// <param name="notificationDataRepository">Notification data repository.</param> /// <param name="sentNotificationDataRepository">Sent notification data repository.</param> /// <param name="localizer">Localization service.</param> /// <param name="userDataRepository">User Data repository.</param> public SyncTeamMembersActivity( TeamDataRepository teamDataRepository, ITeamMembersService memberService, NotificationDataRepository notificationDataRepository, SentNotificationDataRepository sentNotificationDataRepository, IStringLocalizer <Strings> localizer, UserDataRepository userDataRepository) { this.teamDataRepository = teamDataRepository ?? throw new ArgumentNullException(nameof(teamDataRepository)); this.memberService = memberService ?? throw new ArgumentNullException(nameof(memberService)); this.notificationDataRepository = notificationDataRepository ?? throw new ArgumentNullException(nameof(notificationDataRepository)); this.sentNotificationDataRepository = sentNotificationDataRepository ?? throw new ArgumentNullException(nameof(sentNotificationDataRepository)); this.localizer = localizer ?? throw new ArgumentNullException(nameof(localizer)); this.userDataRepository = userDataRepository ?? throw new ArgumentNullException(nameof(userDataRepository)); }
/// <summary> /// Initializes a new instance of the <see cref="GetRecipientDataListForRosterActivity"/> class. /// </summary> /// <param name="botAdapter">The bot adapter.</param> /// <param name="botOptions">The bot options.</param> /// <param name="notificationDataRepository">Notification data repository.</param> /// <param name="sentNotificationDataRepository">Sent notification data repository.</param> /// <param name="localizer">Localization service.</param> /// <param name="handleWarningActivity">handle warning activity.</param> public GetRecipientDataListForRosterActivity( BotFrameworkHttpAdapter botAdapter, IOptions <BotOptions> botOptions, NotificationDataRepository notificationDataRepository, SentNotificationDataRepository sentNotificationDataRepository, IStringLocalizer <Strings> localizer, HandleWarningActivity handleWarningActivity) { this.botAdapter = botAdapter; this.microsoftAppId = botOptions.Value.MicrosoftAppId; this.notificationDataRepository = notificationDataRepository; this.sentNotificationDataRepository = sentNotificationDataRepository; this.localizer = localizer; this.handleWarningActivity = handleWarningActivity; }
/// <summary> /// Initializes a new instance of the <see cref="TeamsConversationActivity"/> class. /// </summary> /// <param name="conversationService">The create user conversation service.</param> /// <param name="sentNotificationDataRepository">The sent notification data repository.</param> /// <param name="userDataRepository">The user data repository.</param> /// <param name="notificationDataRepository">Notification data entity repository.</param> /// <param name="appManagerService">App manager service.</param> /// <param name="chatsService">Chats service.</param> /// <param name="appSettingsService">App Settings service.</param> /// <param name="options">Teams conversation options.</param> /// <param name="localizer">Localization service.</param> public TeamsConversationActivity( IConversationService conversationService, SentNotificationDataRepository sentNotificationDataRepository, UserDataRepository userDataRepository, NotificationDataRepository notificationDataRepository, IAppManagerService appManagerService, IChatsService chatsService, IAppSettingsService appSettingsService, IOptions <TeamsConversationOptions> options, IStringLocalizer <Strings> localizer) { this.conversationService = conversationService ?? throw new ArgumentNullException(nameof(conversationService)); this.sentNotificationDataRepository = sentNotificationDataRepository ?? throw new ArgumentNullException(nameof(sentNotificationDataRepository)); this.userDataRepository = userDataRepository ?? throw new ArgumentNullException(nameof(userDataRepository)); this.notificationDataRepository = notificationDataRepository ?? throw new ArgumentNullException(nameof(notificationDataRepository)); this.appManagerService = appManagerService ?? throw new ArgumentNullException(nameof(appManagerService)); this.chatsService = chatsService ?? throw new ArgumentNullException(nameof(chatsService)); this.appSettingsService = appSettingsService ?? throw new ArgumentNullException(nameof(appSettingsService)); this.options = options?.Value ?? throw new ArgumentNullException(nameof(options)); this.localizer = localizer ?? throw new ArgumentNullException(nameof(localizer)); }
/// <summary> /// Initializes a new instance of the <see cref="SentNotificationsController"/> class. /// </summary> /// <param name="notificationDataRepository">Notification data repository service that deals with the table storage in azure.</param> /// <param name="sentNotificationDataRepository">Sent notification data repository.</param> /// <param name="teamDataRepository">Team data repository instance.</param> /// <param name="prepareToSendQueue">The service bus queue for preparing to send notifications.</param> /// <param name="dataQueue">The service bus queue for the data queue.</param> /// <param name="dataQueueMessageOptions">The options for the data queue messages.</param> /// <param name="sendBatchesDataRepository">The send batches data repository.</param> /// <param name="groupsService">The groups service.</param> /// <param name="exportDataRepository">The Export data repository instance.</param> public SentNotificationsController( NotificationDataRepository notificationDataRepository, SentNotificationDataRepository sentNotificationDataRepository, TeamDataRepository teamDataRepository, PrepareToSendQueue prepareToSendQueue, DataQueue dataQueue, IOptions <DataQueueMessageOptions> dataQueueMessageOptions, SendBatchesDataRepository sendBatchesDataRepository, IGroupsService groupsService, ExportDataRepository exportDataRepository) { this.notificationDataRepository = notificationDataRepository; this.sentNotificationDataRepository = sentNotificationDataRepository; this.teamDataRepository = teamDataRepository; this.prepareToSendQueue = prepareToSendQueue; this.dataQueue = dataQueue; this.forceCompleteMessageDelayInSeconds = dataQueueMessageOptions.Value.ForceCompleteMessageDelayInSeconds; this.sendBatchesDataRepository = sendBatchesDataRepository; this.groupsService = groupsService; this.exportDataRepository = exportDataRepository; }
/// <summary> /// Initializes a new instance of the <see cref="GetRecipientsActivity"/> class. /// </summary> /// <param name="sentNotificationDataRepository">The sent notification data repository.</param> public GetRecipientsActivity(SentNotificationDataRepository sentNotificationDataRepository) { this.sentNotificationDataRepository = sentNotificationDataRepository ?? throw new ArgumentNullException(nameof(sentNotificationDataRepository)); }
/// <summary> /// Initializes a new instance of the <see cref="ManageResultDataService"/> class. /// </summary> /// <param name="sentNotificationDataRepository">The sent notification data repository.</param> public ManageResultDataService( SentNotificationDataRepository sentNotificationDataRepository) { this.sentNotificationDataRepository = sentNotificationDataRepository; }
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); }
/// <summary> /// Initializes a new instance of the <see cref="AggregateSentNotificationDataService"/> class. /// </summary> /// <param name="sentNotificationDataRepository">The sent notification data repository.</param> public AggregateSentNotificationDataService(SentNotificationDataRepository sentNotificationDataRepository) { this.sentNotificationDataRepository = sentNotificationDataRepository; }
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 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 <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"))); }