Ejemplo n.º 1
0
        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);
            }
        }
Ejemplo n.º 2
0
        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);
            }
        }
Ejemplo n.º 3
0
        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);
            }
        }