public void ProcessAccount(ForEachAccountData data)
        {
            var dispatcher = AgentHelper.GetDispatcherClient();

            while (true)
            {
                data.CancellationToken.ThrowIfCancellationRequested();

                const int maxCount = 100;
                var       response = dispatcher.RecalcUnitTestsResults(data.Account.Id, maxCount);
                if (response.Success)
                {
                    var updateCount = response.Data.UpdateCount;
                    Interlocked.Add(ref Count, updateCount);
                    if (updateCount == 0)
                    {
                        data.Logger.Trace("Обновлено статусов проверок: " + updateCount);
                        return;
                    }
                    data.Logger.Debug("Обновлено статусов проверок: " + updateCount);
                    if (updateCount < maxCount)
                    {
                        return;
                    }
                }
                else
                {
                    data.Logger.Error("Ошибка: " + response.ErrorMessage);
                    return;
                }
            }
        }
        protected void ProcessAccount(ForEachAccountData data, Guid?smsId = null)
        {
            var account = data.Account;

            var repository = data.AccountDbContext.GetSendSmsCommandRepository();
            var smss       = repository.GetForSend(SendMaxCount);

            if (smsId.HasValue)
            {
                smss = smss.Where(t => t.Id == smsId.Value).ToList();
            }

            var count = smss.Count;

            if (count > 0)
            {
                data.Logger.Debug("Всего sms для отправки: " + count);
            }
            else
            {
                data.Logger.Trace("Нет sms для отправки");
            }

            foreach (var sms in smss)
            {
                data.CancellationToken.ThrowIfCancellationRequested();

                data.Logger.Debug("Отправка sms на номер {0}", sms.Phone);
                try
                {
                    // отправим сообщение
                    var externalId = SendSms(sms.Phone, sms.Body);

                    // отправим событие = чтобы знать, сколько sms в день отправлено

                    /*
                     * DbProcesor.ComponentControl
                     *  .CreateComponentEvent("Отправка sms")
                     *  .SetJoinInterval(TimeSpan.FromDays(1))
                     *  .SetImportance(EventImportance.Unknown)
                     *  .SetJoinKey(DateTime.Now.ToString("yyyy.MM.dd"))
                     *  .Add();
                     */
                    // TODO Тут нужно писать метрику

                    // обновим статус  и статистику
                    repository.MarkAsSendSuccessed(sms.Id, externalId);
                    Interlocked.Increment(ref SuccessSendCount);

                    data.Logger.Info("Отправлено sms на номер {0}", sms.Phone);
                }
                catch (OperationCanceledException)
                {
                    throw;
                }
                catch (InvalidPhoneException exception)
                {
                    // О неправильном номере телефона запишем в лог
                    // Это не ошибка отправщика

                    data.Logger.Info(exception.Message, new { SmsId = sms.Id.ToString() });

                    repository.MarkAsSendFail(sms.Id, exception.Message);
                }
                catch (Exception exception)
                {
                    DbProcessor.SetException(exception);

                    exception.Data.Add("SmsId", sms.Id);
                    data.Logger.Error(exception);

                    repository.MarkAsSendFail(sms.Id, exception.Message);
                }
            }
        }
        protected void ProcessAccount(ForEachAccountData data, Guid?emailId = null)
        {
            var account = data.Account;

            using (var smtpClient = GetSmtpClient())
            {
                var repository = data.AccountDbContext.GetSendEmailCommandRepository();

                // важно отсортировать письма в порядке их создания
                var emails = repository
                             .GetForSend(SendMaxCount)
                             .OrderBy(x => x.CreateDate)
                             .ToArray();

                if (emailId.HasValue)
                {
                    emails = emails.Where(t => t.Id == emailId.Value).ToArray();
                }

                var count = emails.Length;
                if (count > 0)
                {
                    data.Logger.Debug("Всего писем для отправки: " + count);
                }
                else
                {
                    data.Logger.Trace("Нет писем для отправки");
                }

                var lastSendTime = DateTime.MinValue;

                foreach (var email in emails)
                {
                    data.CancellationToken.ThrowIfCancellationRequested();
                    data.Logger.Debug("Отправляем: {0} Тема: {1}", email.To, email.Subject);
                    try
                    {
                        // todo в почтовом клиенте thunderbird письма иногда не верно сортируются по дате
                        // есть предположение, что это из-за того, что дата создания округляется до секунд
                        // поэтому искуственно сделаем так, чтобы дата отправки писем отличалась как минимум на 1 секунду
                        DateTimeHelper.WaitForTime(lastSendTime.AddMilliseconds(1100));

                        // отправим сообщение
                        SendEmail(smtpClient, email.To, email.Subject, email.Body, email.IsHtml);

                        // отправим событие = чтобы знать, сколько писем в день отправлено

                        /*
                         * DbProcesor.ComponentControl
                         *  .CreateComponentEvent("Отправка почты")
                         *  .SetJoinInterval(TimeSpan.FromDays(1))
                         *  .SetImportance(EventImportance.Unknown)
                         *  .SetJoinKey(DateTime.Now.ToString("yyyy.MM.dd"))
                         *  .Add();
                         */
                        // TODO Тут надо писать метрику

                        // обновим статус  и статистику
                        repository.MarkAsSendSuccessed(email.Id);
                        Interlocked.Increment(ref SuccessSendCount);

                        data.Logger.Info("Отправлено письмо на адрес '{0}' с темой '{1}'", email.To, email.Subject);
                    }
                    catch (OperationCanceledException)
                    {
                        throw;
                    }
                    catch (Exception exception)
                    {
                        if (!IsRatelimitException(exception))
                        {
                            DbProcessor.SetException(exception);

                            exception.Data.Add("EMailId", email.Id);
                            data.Logger.Error(exception);

                            repository.MarkAsSendFail(email.Id, exception.Message);
                        }
                        else
                        {
                            // Особый случай - превышение лимита нашего ящика
                            // За ошибку не считаем, в следующий раз отправится

                            data.Logger.Error(exception, "Превышен лимит отправки ящика Zidium");

                            // Отправлять дальше нет смысла
                            break;
                        }
                    }
                }
            }
        }
Example #4
0
        public void ProcessAccount(ForEachAccountData data)
        {
            var categories = GetCategories();

            var accountTariffRepository = data.AccountDbContext.GetAccountTariffRepository();
            var tariffLimit             = accountTariffRepository.GetHardTariffLimit();
            var date = DateTimeHelper.TrimMs(DateTime.Now.AddDays(-GetMaxDaysFromTariffLimit(tariffLimit)));

            var eventRepository = data.AccountDbContext.GetEventRepository();
            var remaining       = eventRepository.GetEventsCountForDeletion(categories, date);

            Int64 count     = 0;
            var   stopwatch = Stopwatch.StartNew();

            while (true)
            {
                DbProcessor.CancellationToken.ThrowIfCancellationRequested();
                data.Logger.Trace("Аккаунт: {0}, Максимальная дата актуальности: {1}", data.Account.SystemName, date);

                var innerStopWatch = new Stopwatch();
                innerStopWatch.Start();

                if (remaining > 0)
                {
                    data.Logger.Debug("Осталось удалить событий: " + remaining);
                }

                DeleteParameters(
                    data.Logger,
                    eventRepository,
                    data.Account.Id,
                    categories,
                    date,
                    MaxDeleteCount);

                DeleteEventStatuses(
                    data.Logger,
                    eventRepository,
                    data.Account.Id,
                    categories,
                    date,
                    MaxDeleteCount);

                UpdateMetricsHistory(
                    data.Logger,
                    eventRepository,
                    data.Account.Id,
                    categories,
                    date,
                    MaxDeleteCount);

                DeleteNotifications(
                    data.Logger,
                    eventRepository,
                    data.Account.Id,
                    categories,
                    date,
                    MaxDeleteCount);

                DeleteArchivedStatuses(
                    data.Logger,
                    eventRepository,
                    data.Account.Id,
                    categories,
                    date,
                    MaxDeleteCount);

                var result = DeleteEvents(
                    data.Logger,
                    eventRepository,
                    data.Account.Id,
                    categories,
                    date,
                    MaxDeleteCount);

                count     += result;
                remaining -= result;

                innerStopWatch.Stop();
                if (result > 0)
                {
                    data.Logger.Debug("Удален пакет из {0} событий за {1} мс", result, innerStopWatch.ElapsedMilliseconds);
                }

                if (result == 0)
                {
                    break;
                }

                // чтобы не сильно нагружать SQL
                Thread.Sleep(1000);
            }

            stopwatch.Stop();

            if (count > 0)
            {
                data.Logger.Debug("Удалено событий: " + count + " за " + stopwatch.ElapsedMilliseconds + " мс");
                AddToReport(string.Format("Удалено {0} событий в аккаунте {1} за {2} мс", count, data.Account.SystemName, stopwatch.ElapsedMilliseconds));
            }
        }
        /// <summary>
        /// Отправка уведомлений из указанной StorageDb
        /// </summary>
        protected void ProcessAccount(ForEachAccountData data, Guid?componentId = null)
        {
            var notificationRepository = data.AccountDbContext.GetNotificationRepository();

            var notificationsQuery = notificationRepository.GetForSend(NotificationType);

            if (componentId.HasValue)
            {
                notificationsQuery = notificationsQuery.Where(t => t.Event.OwnerId == componentId.Value);
            }

            var notifications = notificationsQuery.OrderBy(t => t.CreationDate).Take(MaxNotificationCount).ToList();

            if (notifications.Count > 0)
            {
                data.Logger.Debug("Найдено уведомлений: " + notifications.Count);
                foreach (var notification in notifications)
                {
                    data.CancellationToken.ThrowIfCancellationRequested();

                    try
                    {
                        data.Logger.Debug("Обработка уведомления " + notification.Id);

                        Send(data.Logger,
                             notification,
                             data.AccountDbContext,
                             data.Account.SystemName, data.Account.Id);

                        notification.Status   = NotificationStatus.Sended;
                        notification.SendDate = DateTime.Now;
                        data.AccountDbContext.SaveChanges();

                        data.Logger.Info("Уведомление " + notification.Id + " отправлено на " + notification.Address);
                        Interlocked.Increment(ref CreatedNotificationsCount);
                    }
                    catch (NotificationNonImportantException exception)
                    {
                        // ошибка при отправке, которая не считается важной
                        data.Logger.Info(exception);

                        // обновим статус
                        notification.SendError = (exception.InnerException ?? exception).ToString();
                        notification.Status    = NotificationStatus.Error;
                        notification.SendDate  = DateTime.Now;
                        data.AccountDbContext.SaveChanges();

                        // TODO отправить ошибку в компонент аккаунта, чтобы её увидел админ аккаунта (а не админ Зидиума)
                    }
                    catch (Exception exception)
                    {
                        // залогируем ошибку
                        DbProcessor.SetException(exception);
                        data.Logger.Error(exception);

                        // обновим статус
                        notification.SendError = exception.ToString();
                        notification.Status    = NotificationStatus.Error;
                        notification.SendDate  = DateTime.Now;
                        data.AccountDbContext.SaveChanges();
                    }
                }
            }
            else
            {
                data.Logger.Trace("Новых уведомлений нет");
            }
        }