protected void AddNotification( LastComponentNotification lastComponentNotification, StatusInfo statusInfo, Subscription subscription, AccountDbContext accountDbContext, NotificationReason reason) { var realEvent = accountDbContext.Events.Find(statusInfo.EventId); if (realEvent == null) { return; } Interlocked.Increment(ref CreatedNotificationsCount); var newNotification = new Notification() { Id = Guid.NewGuid(), Address = lastComponentNotification.Address, CreationDate = Now(), EventId = statusInfo.EventId, Status = NotificationStatus.InQueue, SubscriptionId = subscription.Id, Type = lastComponentNotification.Type, UserId = subscription.UserId, Reason = reason }; if (newNotification.Type == NotificationType.Http) { newNotification.NotificationHttp = new NotificationHttp() { Notification = newNotification //Json = GetNotificationJson(lastComponentNotification.Component, eventObj) }; } var notificationRepository = accountDbContext.GetNotificationRepository(); notificationRepository.Add(newNotification); lastComponentNotification.Update(newNotification, statusInfo.Importance); accountDbContext.SaveChanges(); }
protected void ProcessAccountInternal( Guid accountId, User[] users, Dictionary <Guid, Subscription[]> userToSubscriptions, List <StatusInfo> statuses, AccountDbContext accountDbContext, ILogger logger) { var cancellationToken = DbProcessor.CancellationToken; // Обработаем каждый статус foreach (var status in statuses) { logger.Debug("Обрабатываем событие: " + status.EventId); cancellationToken.ThrowIfCancellationRequested(); // Получим компонент var component = status.Component; if (component == null) { logger.Trace("component == null"); continue; } // статус о выключенном компоненте мы должны получить, поэтому фильтр ниже закоментирован //if (component.Enable == false) //{ // if (isTraceEnabled) // { // log.Trace("component.Enable == false"); // } // continue; //} // Пропускаем удалённые if (component.IsDeleted) { logger.Trace("component.IsDeleted"); continue; } // Пропускаем удалённые if (component.IsRoot) { logger.Trace("component.IsRoot"); continue; } // цикл по пользователям foreach (var user in users) { var channels = new[] { SubscriptionChannel.Email, SubscriptionChannel.Sms, SubscriptionChannel.Http }; if (userToSubscriptions.TryGetValue(user.Id, out var subscriptions)) { foreach (var channel in channels) { var channelSubscriptions = subscriptions .Where(x => x.Channel == channel) .ToArray(); // ищем подписку на компонент var subscription = channelSubscriptions.FirstOrDefault(x => x.ComponentId == status.ComponentId); if (subscription == null) { // ищем подписку на тип события subscription = channelSubscriptions.FirstOrDefault(x => x.ComponentTypeId == status.Component.ComponentTypeId); if (subscription == null) { // ищем дефолтную подписку subscription = channelSubscriptions.FirstOrDefault(x => x.Object == SubscriptionObject.Default); // если дефолтной для email канала нет, то создаем её if (subscription == null && channel == SubscriptionChannel.Email) { var dispatcherClient = AgentHelper.GetDispatcherClient(); var response = dispatcherClient.CreateUserDefaultSubscription( accountId, new CreateUserDefaultSubscriptionRequestData() { Channel = channel, UserId = user.Id }); var repository = accountDbContext.GetSubscriptionRepository(); subscription = repository.GetById(response.Data.Id); } } } // проверим подписку if (subscription != null) { logger.Trace("Проверяем подписку " + subscription.Id + ", событие " + status.EventId + " и компонент " + component.Id); // если отправка запрещена if (subscription.IsEnabled == false) { logger.Trace("False by IsEnabled"); continue; } // подписка шлет уведомления только по событиям, которые создались после создания подписки if (status.CreateDate < subscription.LastUpdated) { logger.Trace("False by LastUpdated"); continue; } if (status.Category != EventCategory.ComponentExternalStatus) { logger.Trace("False by Category"); continue; } // минимальную длительность проверяем только у важных событий (цвет важности указывается пользователем в подписке) if (subscription.DurationMinimumInSeconds.HasValue && status.Importance >= subscription.Importance) { var eventDuration = (int)status.Duration.TotalSeconds; if (eventDuration < subscription.DurationMinimumInSeconds.Value) { logger.Trace("False by DurationMinimumInSeconds"); continue; } } logger.Debug("Создаем уведомления для подписки: " + subscription.Id); cancellationToken.ThrowIfCancellationRequested(); List <UserContact> contacts; if (subscription.Channel == SubscriptionChannel.Email) { contacts = GetUserEMailContacts(subscription.User); } else if (subscription.Channel == SubscriptionChannel.Sms) { contacts = GetUserMobileContacts(subscription.User); } else if (subscription.Channel == SubscriptionChannel.Http) { contacts = GetUserHttpContacts(subscription.User); } else { contacts = new List <UserContact>(); } logger.Debug("Адресов для уведомлений " + contacts.Count); foreach (var contact in contacts) { // Уведомления создаются только по контактам, добавленным до наступления события if (contact.CreateDate > status.CreateDate) { continue; } var address = contact.Value; logger.Debug("Создаём уведомление на адрес: " + address); NotificationType notificationType; if (contact.Type == UserContactType.Email) { notificationType = NotificationType.Email; } else if (contact.Type == UserContactType.MobilePhone) { notificationType = NotificationType.Sms; } else if (contact.Type == UserContactType.Http) { notificationType = NotificationType.Http; } else { logger.Debug("Неизвестный тип контакта: " + contact.Type); continue; } var lastComponentNotification = component.LastNotifications.FirstOrDefault( x => x.Address == address && x.Type == notificationType); var isImportanceColor = status.Importance >= subscription.Importance; // важный статус if (isImportanceColor) { // первое уведомление о важном статусе if (lastComponentNotification == null) { logger.Info("Первое уведомление на адрес " + address + " для компонента " + component.Id); lastComponentNotification = new LastComponentNotification() { Id = Guid.NewGuid(), Address = address, Component = component, ComponentId = component.Id, CreateDate = Now(), EventId = status.EventId, EventImportance = status.Importance, Type = notificationType, NotificationId = Guid.Empty }; component.LastNotifications.Add(lastComponentNotification); AddNotification( lastComponentNotification, status, subscription, accountDbContext, NotificationReason.NewImportanceStatus); continue; } // тот же важный статус if (lastComponentNotification.EventId == status.EventId) { if (subscription.ResendTimeInSeconds > 0) { // Проверим, нужно ли отправлять повторное уведомление var notifyDuration = (int)(Now() - lastComponentNotification.CreateDate).TotalSeconds; if (notifyDuration >= subscription.ResendTimeInSeconds) { logger.Info("Напоминание о статусе " + status.EventId + " на адрес " + address); AddNotification( lastComponentNotification, status, subscription, accountDbContext, NotificationReason.Reminder); continue; } } logger.Debug("Уже есть уведомление о событии " + status.EventId + " на адрес " + address); } else // новый важный статус { logger.Info("Новый важный статус " + status.EventId + " на адрес " + address); AddNotification( lastComponentNotification, status, subscription, accountDbContext, NotificationReason.NewImportanceStatus); } } else // НЕ важное событие { if (lastComponentNotification != null && subscription.NotifyBetterStatus && lastComponentNotification.EventImportance >= subscription.Importance) { logger.Info("Уведомление о том, что стало лучше " + status.EventId + " на адрес " + address); AddNotification( lastComponentNotification, status, subscription, accountDbContext, NotificationReason.BetterStatus); } else { //log.Debug("Не отправляем уведомление об улучшении "+ status.EventId + " на адрес " + address); } } } } } } else { // у пользователя нет ни одной подписки var dispatcherClient = AgentHelper.GetDispatcherClient(); var response = dispatcherClient.CreateUserDefaultSubscription(accountId, new CreateUserDefaultSubscriptionRequestData() { Channel = SubscriptionChannel.Email, UserId = user.Id }); response.Check(); } } } }