Beispiel #1
0
        public IEventCacheReadObject JoinEvent(Guid accountId, Guid componentId, JoinEventData joinEventData)
        {
            // Проверим, что компонент вообще есть
            var componentRequest = new AccountCacheRequest()
            {
                AccountId = accountId,
                ObjectId  = componentId
            };
            var component = AllCaches.Components.Find(componentRequest);

            if (component == null)
            {
                throw new UnknownComponentIdException(componentId, accountId);
            }
            if (component.CanProcess == false)
            {
                throw new ResponseCodeException(Zidium.Api.ResponseCode.ObjectDisabled, "Компонент выключен");
            }

            // проверка лимитов
            var accountDbContext = Context.GetAccountDbContext(accountId);
            var limitChecker     = AccountLimitsCheckerManager.GetCheckerForAccount(accountId);

            limitChecker.CheckEventsRequestsPerDay(accountDbContext);

            // Проверим лимит размера хранилища
            var size = joinEventData.Message != null ? joinEventData.Message.Length * 2 : 0;

            limitChecker.CheckStorageSize(accountDbContext, size);

            var eventType = Context.EventTypeService.GetOneById(joinEventData.TypeId ?? Guid.Empty, accountId);

            // расчитаем важность
            joinEventData.Importance = GetEventImportance(joinEventData.Importance, eventType.Category);

            var localEvent = CreateEvent(
                accountId,
                joinEventData.StartDate,
                joinEventData.StartDate,
                joinEventData.Count,
                joinEventData.Version,
                joinEventData.Importance,
                TimeSpan.FromSeconds(joinEventData.JoinInterval ?? 0),
                joinEventData.Message,
                null,
                eventType,
                componentId,
                joinEventData.JoinKey ?? 0);

            var joinInterval = (joinEventData.JoinInterval.HasValue)
                ? TimeSpan.FromSeconds(joinEventData.JoinInterval.Value)
                : (eventType.JoinInterval ?? TimeSpan.Zero);

            var dbEvent = ProcessSimpleEvent(componentId, localEvent, joinEventData.EventId, joinInterval, accountId);

            limitChecker.AddEventsSizePerDay(accountDbContext, size);

            return(dbEvent);
        }
        public IBulbCacheReadObject GetComponentInternalState(Guid accountId, Guid componentId, bool recalc = false)
        {
            // перед отправкой актуализируем все статусы
            if (recalc)
            {
                CalculateAllStatuses(accountId, componentId);
            }

            var component = GetComponentById(accountId, componentId);
            var request   = new AccountCacheRequest()
            {
                AccountId = accountId,
                ObjectId  = component.InternalStatusId
            };

            return(AllCaches.StatusDatas.Find(request));
        }
        public IUnitTestTypeCacheReadObject UpdateUnitTestType(Guid accountId, UpdateUnitTestTypeRequestData data)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
            if (data.UnitTestTypeId == null)
            {
                throw new ParameterRequiredException("UnitTestTypeId");
            }

            var lockObject = LockObject.ForUnitTestType(data.UnitTestTypeId.Value);

            lock (lockObject)
            {
                var request = new AccountCacheRequest()
                {
                    AccountId = accountId,
                    ObjectId  = data.UnitTestTypeId.Value
                };

                var unitTestType = AllCaches.UnitTestTypes.Read(request);

                // Если поменялось системное имя, то проверим, что нет другого типа проверки с таким системным именем
                if (!string.Equals(unitTestType.SystemName, data.SystemName, StringComparison.OrdinalIgnoreCase))
                {
                    var anotherUnitTestType = AllCaches.UnitTestTypes.FindByName(accountId, data.SystemName);
                    if (anotherUnitTestType != null && anotherUnitTestType.Id != unitTestType.Id)
                    {
                        throw new ArgumentException("Тип проверки с таким системным именем уже существует");
                    }
                }

                using (var unitTestTypeWrite = AllCaches.UnitTestTypes.Write(request))
                {
                    unitTestTypeWrite.SystemName     = data.SystemName;
                    unitTestTypeWrite.DisplayName    = data.DisplayName;
                    unitTestTypeWrite.ActualTimeSecs = data.ActualTimeSecs;
                    unitTestTypeWrite.NoSignalColor  = data.NoSignalColor;
                    unitTestTypeWrite.BeginSave();
                    unitTestTypeWrite.WaitSaveChanges();
                }

                return(AllCaches.UnitTestTypes.Read(request));
            }
        }
Beispiel #4
0
        public IMetricTypeCacheReadObject GetOrCreateType(Guid accountId, string name)
        {
            if (name == null)
            {
                throw new ArgumentNullException("name");
            }
            if (accountId == Guid.Empty)
            {
                throw new ArgumentException("accountId == Guid.Empty");
            }
            var metricTypeId = AllCaches.MetricTypes.GetOrCreateTypeId(accountId, name);
            var request      = new AccountCacheRequest()
            {
                AccountId = accountId,
                ObjectId  = metricTypeId
            };

            return(AllCaches.MetricTypes.Find(request));
        }
        public void DeleteUnitTestType(Guid accountId, Guid unitTestTypeId)
        {
            var request = new AccountCacheRequest()
            {
                AccountId = accountId,
                ObjectId  = unitTestTypeId
            };

            using (var unitTest = AllCaches.UnitTestTypes.Write(request))
            {
                unitTest.IsDeleted = true;
                unitTest.BeginSave();
                unitTest.WaitSaveChanges();
            }

            var checker = AccountLimitsCheckerManager.GetCheckerForAccount(accountId);

            checker.RefreshUnitTestTypesCount();
        }
Beispiel #6
0
        protected IMetricCacheReadObject FindMetric(Guid accountId, Guid componentId, Guid metricTypeId)
        {
            // получим компонент
            var componentRequest = new AccountCacheRequest()
            {
                AccountId = accountId,
                ObjectId  = componentId
            };
            var component = AllCaches.Components.Find(componentRequest);

            if (component == null)
            {
                throw new UnknownComponentIdException(componentId, accountId);
            }

            // получим ссылку на метрику
            var metricReference = component.Metrics.FindByMetricTypeId(metricTypeId);

            if (metricReference == null)
            {
                return(null);
            }

            // получим метрику по ссылке
            var metricRequest = new AccountCacheRequest()
            {
                AccountId = accountId,
                ObjectId  = metricReference.Id
            };
            var metric = AllCaches.Metrics.Find(metricRequest);

            if (metric == null)
            {
                // такого быть НЕ должно, т.к. у компонента есть ссылка на метрику
                throw new Exception("metric == null");
            }
            return(metric);
        }
        protected Component Add(Component component, Guid accountId)
        {
            if (component == null)
            {
                throw new ArgumentNullException("component");
            }
            component.CreatedDate = DateTime.Now;
            if (component.Parent != null)
            {
                if (component.ComponentTypeId == SystemComponentTypes.Root.Id)
                {
                    throw new ResponseCodeException(
                              ResponseCode.UnknownComponentTypeId,
                              "Нельзя создавать экземпляры компонентов с типом Root");
                }
                component.ParentId     = component.Parent.Id;
                component.ParentEnable = component.Parent.CanProcess;
                var parentRequest = new AccountCacheRequest()
                {
                    AccountId = accountId,
                    ObjectId  = component.Parent.Id
                };
                var parent = AllCaches.Components.Find(parentRequest);
                if (parent == null)
                {
                    throw new Exception("parent == null");
                }
                var child = parent.Childs.FindByName(component.SystemName);
                if (child != null)
                {
                    throw new Exception("У родителя уже есть компонент с таким SystemName");
                }
            }

            component.ExternalStatus        = CreateStatusData(component, Api.EventCategory.ComponentExternalStatus, accountId);
            component.InternalStatus        = CreateStatusData(component, Api.EventCategory.ComponentInternalStatus, accountId);
            component.EventsStatus          = CreateStatusData(component, Api.EventCategory.ComponentEventsStatus, accountId);
            component.UnitTestsStatus       = CreateStatusData(component, Api.EventCategory.ComponentUnitTestsStatus, accountId);
            component.MetricsStatus         = CreateStatusData(component, Api.EventCategory.ComponentMetricsStatus, accountId);
            component.ChildComponentsStatus = CreateStatusData(component, Api.EventCategory.ComponentChildsStatus, accountId);

            // обновим ссылку на компонент
            var statuses = component.GetAllStatuses();

            foreach (var statusData in statuses)
            {
                statusData.ComponentId = component.Id;
                statusData.Component   = component;
            }

            component.LogConfig = new LogConfig()
            {
                ComponentId      = component.Id,
                Component        = component,
                Enabled          = true,
                IsFatalEnabled   = true,
                IsErrorEnabled   = true,
                IsWarningEnabled = true,
                IsInfoEnabled    = true,
                IsDebugEnabled   = true,
                IsTraceEnabled   = true,
                LastUpdateDate   = component.CreatedDate
            };
            var accountDbContext = Context.GetAccountDbContext(accountId);

            accountDbContext.Components.Add(component);
            accountDbContext.SaveChanges();

            // обновим в кэше ссылки на дочерние компоненты у родителя
            if (component.Parent != null)
            {
                var parentRequest = new AccountCacheRequest()
                {
                    AccountId = accountId,
                    ObjectId  = component.Parent.Id
                };
                using (var parent = AllCaches.Components.Write(parentRequest))
                {
                    var componentRef = new CacheObjectReference(component.Id, component.SystemName);
                    parent.WriteChilds.Add(componentRef);
                    parent.BeginSave();
                }
            }

            return(component);
        }
        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);
            }
        }
Beispiel #9
0
        public Guid CreateMetric(Guid accountId, Guid componentId, Guid metricTypeId)
        {
            // получаем компонент
            var componentRequest = new AccountCacheRequest()
            {
                AccountId = accountId,
                ObjectId  = componentId
            };

            using (var component = AllCaches.Components.Write(componentRequest))
            {
                var child = component.Metrics.FindByMetricTypeId(metricTypeId);
                if (child != null)
                {
                    throw new UserFriendlyException("У компонента уже есть метрика данного типа");
                }

                // сохраняем метрику в БД
                using (var accountDbContext = AccountDbContext.CreateFromAccountIdLocalCache(accountId))
                {
                    // Проверим лимиты
                    var limitChecker = AccountLimitsCheckerManager.GetCheckerForAccount(accountId);
                    limitChecker.CheckMaxMetrics(accountDbContext);

                    var processDate = DateTime.Now;
                    var metricId    = Guid.NewGuid();

                    var statusData = Context.BulbService.CreateBulb(
                        accountId,
                        processDate,
                        EventCategory.MetricStatus,
                        metricId);

                    // загрузим в новый контекст
                    statusData = accountDbContext.Bulbs.Find(statusData.Id);

                    var metric = new Metric()
                    {
                        Id           = metricId,
                        BeginDate    = processDate,
                        ActualDate   = processDate.AddDays(1),
                        ComponentId  = component.Id,
                        Enable       = true,
                        IsDeleted    = false,
                        MetricTypeId = metricTypeId,
                        ParentEnable = component.CanProcess,
                        StatusDataId = statusData.Id,
                        //StatusData = statusData,
                        CreateDate = DateTime.Now,
                        Value      = null
                    };

                    statusData.MetricId = metric.Id;
                    statusData.Metric   = metric;

                    var repository = accountDbContext.GetMetricRepository();
                    repository.Add(metric);
                    accountDbContext.SaveChanges();

                    // обновим статистику лимитов
                    limitChecker.RefreshMetricsCount();

                    // обновляем ссылки у компонента
                    var metricReference = new CacheObjectReference(metric.Id, metricTypeId.ToString());
                    component.WriteMetrics.Add(metricReference);

                    component.BeginSave();
                    return(metric.Id);
                }
            }
        }
Beispiel #10
0
        public void DeleteMetric(Guid accountId, DeleteMetricRequestData data)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
            if (data.MetricId == null)
            {
                throw new ParameterRequiredException("MetricId");
            }

            // удаляем метрику
            Guid componentId;
            Guid statusDataId;
            Guid componentMetricsStatusDataId;

            var metricRequest = new AccountCacheRequest()
            {
                AccountId = accountId,
                ObjectId  = data.MetricId.Value
            };

            using (var metric = AllCaches.Metrics.Write(metricRequest))
            {
                componentId      = metric.ComponentId;
                statusDataId     = metric.StatusDataId;
                metric.IsDeleted = true;
                metric.BeginSave();
                metric.WaitSaveChanges();
            }

            // Проверим лимиты
            var limitChecker = AccountLimitsCheckerManager.GetCheckerForAccount(accountId);

            limitChecker.RefreshMetricsCount();

            // удаляем колбасу метрики
            var statusDataRequest = new AccountCacheRequest()
            {
                AccountId = accountId,
                ObjectId  = statusDataId
            };

            using (var statusData = AllCaches.StatusDatas.Write(statusDataRequest))
            {
                statusData.IsDeleted = true;
                statusData.BeginSave();
            }

            // удаляем ссылку на метрику в компоненте
            var componentRequest = new AccountCacheRequest()
            {
                AccountId = accountId,
                ObjectId  = componentId
            };

            using (var component = AllCaches.Components.Write(componentRequest))
            {
                componentMetricsStatusDataId = component.MetricsStatusId;
                component.WriteChilds.Delete(data.MetricId.Value);
                component.BeginSave();
            }

            // обновим колбасу метрик компонента
            var componentMetricsStatusDataIds = new List <Guid>();
            var component1 = AllCaches.Components.Find(componentRequest);

            foreach (var metricRef in component1.Metrics.GetAll())
            {
                var metric = AllCaches.Metrics.Find(new AccountCacheRequest()
                {
                    AccountId = accountId,
                    ObjectId  = metricRef.Id
                });
                if (metric == null)
                {
                    throw new Exception("metric == null");
                }
                if (metric.IsDeleted)
                {
                    continue;
                }
                componentMetricsStatusDataIds.Add(metric.StatusDataId);
            }

            Context.BulbService.CalculateByChilds(
                accountId,
                componentMetricsStatusDataId,
                componentMetricsStatusDataIds);
        }
Beispiel #11
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);
            }
        }
Beispiel #12
0
        public IEventCacheReadObject SendEvent(Guid accountId, Guid componentId, SendEventData message)
        {
            // Проверим, что компонент вообще есть
            var componentRequest = new AccountCacheRequest()
            {
                AccountId = accountId,
                ObjectId  = componentId
            };
            var component = AllCaches.Components.Find(componentRequest);

            if (component == null)
            {
                throw new UnknownComponentIdException(componentId, accountId);
            }
            if (component.CanProcess == false)
            {
                throw new ResponseCodeException(Zidium.Api.ResponseCode.ObjectDisabled, "Компонент выключен");
            }

            // проверка лимитов
            var accountDbContext = Context.GetAccountDbContext(accountId);
            var limitChecker     = AccountLimitsCheckerManager.GetCheckerForAccount(accountId);

            limitChecker.CheckEventsRequestsPerDay(accountDbContext);

            // Проверим лимит размера хранилища
            var size = message.GetSize();

            limitChecker.CheckStorageSize(accountDbContext, size);

            // todo нет проверки обязательных параметров
            FixEventMessageNames(message);
            FixEventMessageTypeCode(message);
            FixEventMessageJoinKey(message); // todo не уверен, что нужно менять ключ склейки при разных версиях (но склеивать с  разными версиями нельзя!)
            FixEventMessageJoinInterval(message);

            // категория
            if (message.Category == null)
            {
                message.Category = EventCategory.ComponentEvent;
            }

            // важность
            message.Importance = GetEventImportance(message.Importance, message.Category.Value);

            if (message.StartDate == null)
            {
                message.StartDate = DateTime.Now;
            }

            var eventType = GetOrCreateEventType(
                accountId,
                message.Category.Value,
                message.TypeSystemName,
                message.TypeDisplayName,
                component.ComponentTypeId,
                message.TypeCode);

            var joinTime = DataConverter.GetTimeSpanFromSeconds(message.JoinInterval);

            var localEvent = CreateEvent(
                accountId,
                message.StartDate,
                message.StartDate,
                message.Count,
                message.Version,
                message.Importance,
                TimeSpan.FromMinutes(1),
                message.Message,
                message.Properties,
                eventType,
                componentId,
                message.JoinKey ?? 0);

            // eventType.JoinInterval стоит на первом месте, чтобы можно было изменить поведение БЕЗ перекомпиляции кода
            var joinInterval = eventType.JoinInterval ?? joinTime ?? TimeSpan.Zero;

            if (!EventCategoryHelper.IsCustomerEventCategory(eventType.Category))
            {
                throw new Exception("Недопустимая категория события: " + eventType.Category);
            }

            var result = ProcessSimpleEvent(componentId, localEvent, null, joinInterval, accountId);

            limitChecker.AddEventsRequestsPerDay(accountDbContext);
            limitChecker.AddEventsSizePerDay(accountDbContext, size);

            // если есть закрытый или тестируемый дефект и событие - новая ошибка, то переоткроем дефект
            if (eventType.Defect != null)
            {
                var defectStatus = eventType.Defect.GetStatus();
                if ((defectStatus == DefectStatus.Closed || defectStatus == DefectStatus.Testing) && !EventIsOld(eventType.OldVersion, result.Version))
                {
                    var defectService = accountDbContext.GetDefectService();
                    defectService.AutoReopen(accountId, eventType.Defect);
                    accountDbContext.SaveChanges();
                }
            }

            // проверим "событие из будущего"
            CheckEventStartDate(message, accountId, eventType.Id, result.Id);

            return(result);
        }
        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);
            }
        }
        public void Delete(Guid accountId, Guid unitTestId)
        {
            // удаляем юнит-тест
            var unitTestRequest = new AccountCacheRequest()
            {
                AccountId = accountId,
                ObjectId  = unitTestId
            };
            Guid componentId;
            Guid componentUnitTestsStatudDataId;
            Guid unitTestStatusDataId;

            using (var unitTest = AllCaches.UnitTests.Write(unitTestRequest))
            {
                componentId          = unitTest.ComponentId;
                unitTestStatusDataId = unitTest.StatusDataId;
                unitTest.IsDeleted   = true;
                unitTest.BeginSave();
            }

            // удаляем колбасу юнит-теста
            var statusDataRequest = new AccountCacheRequest()
            {
                AccountId = accountId,
                ObjectId  = unitTestStatusDataId
            };

            using (var statusData = AllCaches.StatusDatas.Write(statusDataRequest))
            {
                statusData.IsDeleted = true;
                statusData.BeginSave();
            }

            // удаляем ссылку на юнит-тест в компоненте
            var componentRequest = new AccountCacheRequest()
            {
                AccountId = accountId,
                ObjectId  = componentId
            };

            using (var component = AllCaches.Components.Write(componentRequest))
            {
                componentUnitTestsStatudDataId = component.UnitTestsStatusId;
                component.WriteUnitTests.Delete(unitTestId);
                component.BeginSave();
            }

            // обновляем статус колбаски тестов
            var allUnitTestsStatusDataIds = new List <Guid>();
            var component1 = AllCaches.Components.Find(new AccountCacheRequest()
            {
                AccountId = accountId,
                ObjectId  = componentId
            });

            foreach (var unitTestRef in component1.UnitTests.GetAll())
            {
                var unitTest = AllCaches.UnitTests.Find(new AccountCacheRequest()
                {
                    AccountId = accountId,
                    ObjectId  = unitTestRef.Id
                });
                if (unitTest != null && unitTest.IsDeleted == false)
                {
                    allUnitTestsStatusDataIds.Add(unitTest.StatusDataId);
                }
            }
            var statuservice = Context.BulbService;

            statuservice.CalculateByChilds(accountId, componentUnitTestsStatudDataId, allUnitTestsStatusDataIds);

            var checker = AccountLimitsCheckerManager.GetCheckerForAccount(accountId);

            checker.RefreshApiChecksCount();
        }
        public void UpdateUnitTest(Guid accountId, UpdateUnitTestRequestData data)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
            if (data.UnitTestId == null)
            {
                throw new ParameterRequiredException("UnitTestId");
            }
            if (data.ComponentId == null)
            {
                throw new ParameterRequiredException("ComponentId");
            }
            if (data.UnitTestId == Guid.Empty)
            {
                throw new ParameterErrorException("UnitTestId не может быть Guid.Empty");
            }
            if (data.DisplayName == null)
            {
                throw new ParameterRequiredException("DisplayName");
            }
            if (string.IsNullOrWhiteSpace(data.DisplayName))
            {
                throw new ParameterErrorException("DisplayName не может быть пустым");
            }
            //if (data.ErrorColor == null)
            //{
            //    throw new ParameterRequiredException("ErrorColor");
            //}

            // SystemName сейчас не настраивается через GUI

            //if (data.SystemName == null)
            //{
            //    throw new ParameterRequiredException("SystemName");
            //}

            //получим компонент, чтобы убедится, что он принадлежит аккаунту
            var req = new AccountCacheRequest()
            {
                AccountId = accountId,
                ObjectId  = data.ComponentId.Value
            };
            var component = AllCaches.Components.Find(req);

            if (component == null)
            {
                throw new UnknownComponentIdException(data.ComponentId.Value, accountId);
            }

            var request = new AccountCacheRequest()
            {
                AccountId = accountId,
                ObjectId  = data.UnitTestId.Value
            };

            // сохраним изменения
            IUnitTestCacheReadObject unitTestCache = null;

            using (var unitTest = AllCaches.UnitTests.Write(request))
            {
                unitTestCache = unitTest;

                // период выполнения проверки
                if (unitTest.IsSystemType)
                {
                    // не для всех системных проверок можно указывать период (для проверки домена нельзя)
                    if (SystemUnitTestTypes.CanEditPeriod(unitTest.TypeId))
                    {
                        if (data.PeriodSeconds == null)
                        {
                            throw new ParameterRequiredException("Period");
                        }
                        if (data.PeriodSeconds.Value < 60)
                        {
                            throw new ParameterErrorException("Период проверки НЕ может быть меньше 1 минуты");
                        }
                        unitTest.PeriodSeconds = (int)data.PeriodSeconds.Value;
                    }

                    // чтобы выполнить проверку прямо сейчас с новыми параметрами и увидеть результат
                    unitTest.NextDate = DateTime.Now;
                }

                unitTest.DisplayName   = data.DisplayName;
                unitTest.ComponentId   = data.ComponentId.Value;
                unitTest.ErrorColor    = data.ErrorColor;
                unitTest.NoSignalColor = data.NoSignalColor;
                unitTest.ActualTime    = TimeSpanHelper.FromSeconds(data.ActualTime);

                if (data.SimpleMode.HasValue)
                {
                    unitTest.SimpleMode = data.SimpleMode.Value;
                }

                unitTest.BeginSave();
            }

            // ждем сохранения в кэше
            unitTestCache.WaitSaveChanges();
        }