using Bit.Core.Settings; using Bit.Core.Utilities; using Microsoft.Azure.NotificationHubs; using Microsoft.Extensions.Logging; namespace Bit.Core.NotificationHub; #nullable enable public class NotificationHubPool : INotificationHubPool { private List _connections { get; } private readonly IEnumerable _clients; private readonly ILogger _logger; public NotificationHubPool(ILogger logger, GlobalSettings globalSettings) { _logger = logger; _connections = FilterInvalidHubs(globalSettings.NotificationHubPool.NotificationHubs); _clients = _connections.GroupBy(c => c.ConnectionString).Select(g => g.First().HubClient); } private List FilterInvalidHubs(IEnumerable hubs) { List result = new(); _logger.LogDebug("Filtering {HubCount} notification hubs", hubs.Count()); foreach (var hub in hubs) { var connection = NotificationHubConnection.From(hub); if (!connection.IsValid) { _logger.LogWarning("Invalid notification hub settings: {HubName}", hub.HubName ?? "hub name missing"); continue; } _logger.LogDebug("Adding notification hub: {ConnectionLogString}", connection.LogString); result.Add(connection); } return result; } /// /// Gets the NotificationHubClient for the given comb ID. /// /// /// /// Thrown when no notification hub is found for a given comb. public INotificationHubClient ClientFor(Guid comb) { var resolvedConnection = ConnectionFor(comb); return resolvedConnection.HubClient; } /// /// Gets the NotificationHubConnection for the given comb ID. /// /// /// /// Thrown when no notification hub is found for a given comb. public NotificationHubConnection ConnectionFor(Guid comb) { var possibleConnections = _connections.Where(c => c.RegistrationEnabled(comb)).ToArray(); if (possibleConnections.Length == 0) { throw new InvalidOperationException($"No valid notification hubs are available for the given comb ({comb}).\n" + $"The comb's datetime is {CoreHelpers.DateFromComb(comb)}." + $"Hub start and end times are configured as follows:\n" + string.Join("\n", _connections.Select(c => $"Hub {c.HubName} - Start: {c.RegistrationStartDate}, End: {c.RegistrationEndDate}"))); } var resolvedConnection = possibleConnections[CoreHelpers.BinForComb(comb, possibleConnections.Length)]; _logger.LogTrace("Resolved notification hub for comb {Comb} out of {HubCount} hubs.\n{ConnectionInfo}", comb, possibleConnections.Length, resolvedConnection.LogString); return resolvedConnection; } public INotificationHubProxy AllClients { get { return new NotificationHubClientProxy(_clients); } } }