private async Task <TimeSpan> SendNotifications(ServiceStatusResult statusResult) { List <Task> tasks = new List <Task>(); List <TimeSpan> gracePeriods = new List <TimeSpan>(); // Send service up notifications List <SubscriptionResults> serviceUpMailRecepients = await GetSubscribers(statusResult.WentOnline); foreach (SubscriptionResults recepient in serviceUpMailRecepients) { // TODO: Read text from config file tasks.Add(mailingService.Send(recepient.User.Email, "Service Up", GetMessageBody(recepient.Subscriptions.Select(s => s.Service).ToList()))); } // Send service down notifications List <SubscriptionResults> serviceDownMailRecepients = await GetSubscribers(statusResult.WentOffline); foreach (SubscriptionResults recepient in serviceDownMailRecepients) { // TODO: Read text from config file tasks.Add(mailingService.Send(recepient.User.Email, "Service Down", GetMessageBody(recepient.Subscriptions.Select(s => s.Service).ToList()))); gracePeriods.AddRange(recepient.Subscriptions.Select(s => s.GracePeriod)); } await Task.WhenAll(tasks.ToArray()); // Find the minimum grace period out of all subscriptions (excluding zeros) // If no entries found return a big value, so it will be ignored and polling freaquency will be considered var minimumGracePeriod = gracePeriods.Count > 0 ? gracePeriods.Min() : new TimeSpan(24, 0, 0); return(minimumGracePeriod); }
public async Task <TimeSpan> UpdateServiceHelth() { // Read saved service providers from the DB List <ServiceProvider> serviceProviders = await serviceProviderRepository.GetAll(); // Check network connectivity status ServiceStatusResult updateResult = await networkService.CheckTcpConnection(serviceProviders); // write new status to the DB Task updateServiceProviderTask = serviceProviderRepository.Upsert(updateResult.ServiceProviders); // send mail notifications Task <TimeSpan> sendMailTask = SendNotifications(updateResult); // DB update, email notification and polling freaquency read can happen asynchronusly // Let the DB query run asynchronously while above two operations runs Task <TimeSpan> pollingFreaquencyTask = serviceProviderRepository.GetMaximumPollingFreaquency(); // wait for DB update and notifications to complete await updateServiceProviderTask; TimeSpan minimumGracePeriod = await sendMailTask; // wait for the query result. This should be already completed TimeSpan pollingFreaquency = await pollingFreaquencyTask; // Next update cycle will be initialized based on the minimum value between polling frequency and minimum grace period of failed services. // From the NetworkService class correct polling frequency will be checked and skipped unnecessary network checks TimeSpan nextUpdateFrequency = minimumGracePeriod < pollingFreaquency ? minimumGracePeriod : pollingFreaquency; return(nextUpdateFrequency); }
public void UpdateServiceHealth_Should_Return_grace_period() { var mockLogger = new Mock <ILogger <ServiceManager> >(); var mockServiceProviderRepo = new Mock <IServiceProviderRepository>(); var mockUserRepo = new Mock <IUserRepository>(); var mockNetworkService = new Mock <INetworkService>(); var mockMailingService = new Mock <IMailingService>(); // This means in one failed service provider grace period is less than the next polling time // in this case minimum grace period should return as the next polling time TimeSpan maximumPollingFreaquency = new TimeSpan(1, 0, 1); TimeSpan minimumGracePeriod = new TimeSpan(0, 0, 1); ServiceProvider serviceProvider = new ServiceProvider() { Host = "127.0.0.1", Port = 80, PollingFrequency = maximumPollingFreaquency }; List <ServiceProvider> serviceProviders = new List <ServiceProvider>(); serviceProviders.Add(serviceProvider); List <ServiceSubscription> serviceSubscriptions = new List <ServiceSubscription>(); serviceSubscriptions.Add(new ServiceSubscription() { Service = serviceProvider, GracePeriod = minimumGracePeriod, PollingFrequency = maximumPollingFreaquency }); List <User> users = new List <User>(); users.Add(new User() { Name = "abc", Email = "*****@*****.**", Subscriptions = serviceSubscriptions }); ServiceStatusResult updateResult = new ServiceStatusResult(); updateResult.WentOffline.Add(serviceProvider); mockNetworkService.Setup(n => n.CheckTcpConnection(serviceProviders)).ReturnsAsync(updateResult); mockUserRepo.Setup(u => u.GetAll()).ReturnsAsync(users); mockServiceProviderRepo.Setup(s => s.GetMaximumPollingFreaquency()).ReturnsAsync(maximumPollingFreaquency); ServiceManager serviceManager = new ServiceManager(mockLogger.Object, mockServiceProviderRepo.Object, mockUserRepo.Object, mockNetworkService.Object, mockMailingService.Object); // execute method TimeSpan pollingFreaquencyResult = serviceManager.UpdateServiceHelth().Result; // UpdateServiceHelth() should return the value we configured for minimum grace period as it's the lowest value Assert.AreEqual(pollingFreaquencyResult, minimumGracePeriod); }
public async Task <ServiceStatusResult> CheckTcpConnection(List <ServiceProvider> tcpServiceProviders) { // List<Task> tasks = new List<Task>(); serviceStatusResult = new ServiceStatusResult(); foreach (ServiceProvider tcpServiceProvider in tcpServiceProviders) { if (tcpServiceProvider.UpdatedDate.Add(tcpServiceProvider.PollingFrequency) <= DateTime.Now && // If polling is due and (tcpServiceProvider.OutageStart > DateTime.Now && tcpServiceProvider.OutageEnd >= DateTime.Now || // If outage starts and ends in a future date, check connectivity tcpServiceProvider.OutageStart < DateTime.Now && tcpServiceProvider.OutageEnd < DateTime.Now)) // If outage started and ended in a past date, check connectivity { await CheckTcpConnection(tcpServiceProvider); } } return(serviceStatusResult); }
public NetworkService(ILogger <NetworkService> logger) { this.logger = logger; serviceStatusResult = new ServiceStatusResult(); }