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; } } } } }
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("Новых уведомлений нет"); } }