protected void CalculateComponentEventsStatus(Guid accountId, Guid eventsStatusId) { var processDate = DateTime.Now; var eventService = Context.EventService; var statusService = Context.BulbService; var request = new AccountCacheRequest() { AccountId = accountId, ObjectId = eventsStatusId }; // получаем объект для записи, чтобы заблокировать доступ, но ничего не пишем using (var data = AllCaches.StatusDatas.Write(request)) { if (data.Actual(processDate)) { // событий не было вообще if (data.LastEventId == null) { return; } // проверим, что событие актуально var lastEvent = eventService.GetEventCacheOrNullById(accountId, data.LastEventId.Value); if (lastEvent != null) { bool isActual = EventImportanceHelper.Get(data.Status) == lastEvent.Importance && lastEvent.ActualDate >= processDate; if (isActual) { // ничего не изменилось, статус актуален return; } } } // ищем событие, которое пересекается со статусом var nextEvent = eventService.GetDangerousEvent( accountId, data.ComponentId.Value, processDate); if (nextEvent != null) { var noSignalImportance = Api.EventImportance.Unknown; var signal = BulbSignal.Create(processDate, nextEvent, noSignalImportance, accountId); statusService.SetSignal(data.Id, signal); return; } // нет актуальных событий var unknownSignal = BulbSignal.CreateUnknown(accountId, processDate); statusService.SetSignal(eventsStatusId, unknownSignal); } }
public void ProcessEvent(Guid accountId, Guid componentId, IEventCacheReadObject eventObj) { var categories = new[] { Api.EventCategory.ApplicationError, Api.EventCategory.ComponentEvent }; if (categories.Contains(eventObj.Category) == false) { return; } var accountDbContext = Context.GetAccountDbContext(accountId); var component = accountDbContext.GetComponentRepository().GetById(componentId); // если выключен, то ничего не делаем if (component.CanProcess == false) { return; } // отфильтруем события, которые не могут влиять на статус // если событие НЕ длится if (eventObj.StartDate == eventObj.ActualDate) { // возможно такие события могут продлить EndDate до eventObj.StartDate // пока будем их игнорировать, чтобы сделать алгоритм проще return; } var statusId = component.EventsStatusId; var statusService = Context.BulbService; var noSignalImportance = Api.EventImportance.Unknown; // получаем или создаем статус (колбаску) var request = new AccountCacheRequest() { AccountId = accountId, ObjectId = statusId }; using (var data = AllCaches.StatusDatas.Write(request)) { DateTime processDate = DateTime.Now; // событие из будущего (завершается через 5 минут) if (eventObj.EndDate > processDate + TimeSpan.FromMinutes(5)) { // пусть будет, эту проблему должен решать отправитель //return UpdateStatusResult.Canceled(); } // события из прошлого игнорируем, иначе будет ерунда при обновлении родительской колбасы // т.е. будет несоответствие наложения дочерних колбасок на родительскую if (eventObj.ActualDate <= processDate) { return; } // если событие протухло if (eventObj.ActualDate <= data.EndDate) { return; } var status = MonitoringStatusHelper.Get(eventObj.Importance); var signal = BulbSignal.Create(processDate, eventObj, noSignalImportance); // 0. если это первый сигнал после пробела if (data.HasSignal == false) { statusService.SetSignal(data.Id, signal); return; } // 1. событие менее важное, чем текущий статус if (status < data.Status) { // событие поменяло важность, нодо расчитать занова! if (data.LastEventId == eventObj.Id) { CalculateComponentEventsStatus(accountId, component.EventsStatusId); return; } // текущий статус актуальней if (data.ActualDate >= eventObj.ActualDate) { return; } // на актуальный статус менее важные события не влияют if (data.Actual(processDate)) { return; } // статус протух, а событие актуальное // нужно расчитать, т.к. могут быть более важные актуальные события CalculateComponentEventsStatus(accountId, component.EventsStatusId); return; } // 2. событие такой же важности как статус if (status == data.Status) { // продлеваем statusService.SetSignal(data.Id, signal); return; } // 3. событие более важное, чем текущий статус statusService.SetSignal(data.Id, signal); } }
protected IBulbCacheReadObject SaveResultEvent( DateTime processDate, IUnitTestCacheReadObject unitTest, Event newEvent) { var request = new AccountCacheRequest() { AccountId = unitTest.AccountId, ObjectId = unitTest.StatusDataId }; using (var statusData = AllCaches.StatusDatas.Write(request)) { // сохраним результаты var eventService = Context.EventService; IEventCacheReadObject lastEvent = null; if (statusData.LastEventId.HasValue) { lastEvent = eventService.GetEventCacheOrNullById( unitTest.AccountId, statusData.LastEventId.Value); } // для системных проверок пробелы должны быть серыми, // чтобы из-за простоев агента зидиума не красить пользовательские проверки var noSignalImportance = unitTest.IsSystemType ? EventImportance.Unknown : EventImportance.Alarm; if (lastEvent == null) { // todo не понятно нужно ли в результаты проверок вставлять пробелы? // TryAddSpaceResultEvent(unitTest, newEvent, noSignalImportance); } else { // например, чтобы обрезать бесконечную актуальность у события "нет сигнала" if (lastEvent.ActualDate > newEvent.StartDate) { if (AllCaches.Events.ExistsInStorage(lastEvent)) { using (var wLastEvent = AllCaches.Events.Write(lastEvent)) { wLastEvent.ActualDate = newEvent.StartDate; wLastEvent.BeginSave(); } } } } // синхронная вставка // асинхронное создание объектов сильно усложняет код, поэтому будет создавать всё синхронно eventService.Add(unitTest.AccountId, newEvent); // асинхронная вставка //var newEventCache = EventCacheWriteObject.CreateForAdd(newEvent); //AllCaches.Events.AddNew(newEventCache); using (var wUnitTest = AllCaches.UnitTests.Write(unitTest)) { wUnitTest.LastExecutionDate = newEvent.EndDate; // расчитаем время следующего выполнения if (unitTest.PeriodSeconds > 0) { var nextTime = wUnitTest.NextDate ?? processDate; var period = TimeSpan.FromSeconds(wUnitTest.PeriodSeconds.Value); while (nextTime <= processDate) { nextTime = nextTime + period; } wUnitTest.NextDate = nextTime; } wUnitTest.BeginSave(); } // обновим статус var statusService = Context.BulbService; var signal = BulbSignal.Create(processDate, newEvent, noSignalImportance, unitTest.AccountId); var newStatus = statusService.SetSignal(unitTest.StatusDataId, signal); return(newStatus); } }