Пример #1
0
        public static bool CanJoinSimpleEvents(IEventCacheReadObject oldEvent, Event newEvent, TimeSpan joinInterval)
        {
            if (oldEvent == null)
            {
                return(false);
            }
            if (joinInterval == TimeSpan.Zero)
            {
                return(false);
            }
            // добавляем 1 секунду, т.к. при сохранении в БД мс теряются
            var maxJoinDate = oldEvent.EndDate.AddSeconds(1) + joinInterval;

            return(CanJoin(oldEvent, newEvent, maxJoinDate));
        }
Пример #2
0
 public static BulbSignal Create(DateTime processDate, IEventCacheReadObject eventObj, EventImportance noSignalImportance)
 {
     if (eventObj == null)
     {
         throw new ArgumentNullException("eventObj");
     }
     return(new BulbSignal()
     {
         AccountId = eventObj.AccountId,
         EventId = eventObj.Id,
         IsSpace = eventObj.IsSpace,
         ActualDate = eventObj.ActualDate,
         Message = eventObj.Message,
         Status = MonitoringStatusHelper.Get(eventObj.Importance),
         NoSignalImportance = noSignalImportance,
         ProcessDate = processDate,
         StartDate = eventObj.StartDate
     });
 }
Пример #3
0
        /// <summary>
        /// Проверяет можно ли склеивать события.
        /// Все события склеиваются одинаково (простые и непрерывные).
        /// </summary>
        /// <param name="oldEvent"></param>
        /// <param name="newEvent"></param>
        /// <param name="maxJoinDate"></param>
        /// <returns></returns>
        private static bool CanJoin(
            IEventCacheReadObject oldEvent,
            Event newEvent,
            DateTime maxJoinDate)
        {
            // склеивать события разных версий нельзя
            if (newEvent.VersionLong != null &&
                oldEvent.VersionLong != null && // если хотя бы у одного события версия неизвестна, то можно клеить
                newEvent.VersionLong != oldEvent.VersionLong)
            {
                return(false);
            }

            return(oldEvent.OwnerId == newEvent.OwnerId &&
                   oldEvent.Importance == newEvent.Importance &&
                   oldEvent.IsSpace == newEvent.IsSpace && // склеивать пробел с сигналом нельзя
                   oldEvent.EventTypeId == newEvent.EventTypeId &&
                   oldEvent.JoinKeyHash == newEvent.JoinKeyHash &&
                   maxJoinDate >= newEvent.StartDate);
        }
Пример #4
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);
            }
        }
Пример #5
0
        protected IEventCacheReadObject CreateOrJoinSimpleEvent(
            Guid componentId,
            Event eventObj,
            Guid?oldEventId,
            TimeSpan joinInterval,
            Guid accountId,
            out bool isEventNew)
        {
            IEventCacheReadObject rLastEvent = null;

            if (oldEventId.HasValue)
            {
                rLastEvent = AllCaches.Events.Find(new AccountCacheRequest()
                {
                    AccountId = accountId,
                    ObjectId  = oldEventId.Value
                });
            }
            else
            {
                var accountDbContext = Context.DbContext.GetAccountDbContext(accountId);
                var repository       = accountDbContext.GetEventRepository();
                var lastEvent        = repository.GetForJoin(eventObj);
                if (lastEvent != null)
                {
                    rLastEvent = AllCaches.Events.GetForRead(lastEvent, accountId);
                }
            }

            if (rLastEvent != null)
            {
                var request = new AccountCacheRequest()
                {
                    AccountId = accountId,
                    ObjectId  = rLastEvent.Id
                };
                if (AllCaches.Events.ExistsInStorage(request))
                {
                    using (var wLastEvent = AllCaches.Events.Write(request))
                    {
                        bool canJoin = EventHelper.CanJoinSimpleEvents(wLastEvent, eventObj, joinInterval);
                        if (canJoin)
                        {
                            // Можно склеивать
                            UpdateJoinedEvent(accountId, componentId, wLastEvent, eventObj);
                            isEventNew = false;
                            wLastEvent.BeginSave();
                            return(wLastEvent);
                        }
                    }
                }
            }


            // Создадим новое
            {
                var accountDbContext = Context.DbContext.GetAccountDbContext(accountId);
                var eventRepository  = accountDbContext.GetEventRepository();
                isEventNew = true;
                eventRepository.Add(eventObj);
                accountDbContext.SaveChanges();
                var wEvent = EventCacheWriteObject.CreateForUpdate(eventObj, accountId);
                AllCaches.Events.AddOrGet(wEvent);
                return(wEvent);
            }
        }
Пример #6
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);
            }
        }