protected IEventCacheReadObject CreateOrUpdateStatusEvent(Guid accountId, BulbCacheWriteObject data) { if (data == null) { throw new ArgumentNullException("data"); } var request = new AccountCacheRequest() { AccountId = accountId, ObjectId = data.StatusEventId }; // обновляем существующее if (AllCaches.Events.ExistsInStorage(request)) { using (var statusEvent = AllCaches.Events.Write(request)) { statusEvent.Message = data.Message; statusEvent.EndDate = data.EndDate; statusEvent.StartDate = data.StartDate; statusEvent.ActualDate = data.ActualDate; statusEvent.Count = data.Count; statusEvent.BeginSave(); return(statusEvent); } } // создаем новое событие var ownerId = data.GetOwnerId(); return(AddStatusEvent(accountId, data, ownerId)); }
protected void ProlongStatus(BulbSignal signal, BulbCacheWriteObject data) { // проверим пробел var nextStartDate = GetStartDate(data, signal); bool hasSpace = data.ActualDate < nextStartDate; if (hasSpace) { throw new Exception("Тут не должно быть пробела"); } // разрыва нет // у виртуальных колбасок нет смысла увеличивать счетчик, т.к. это приводит только к лишнему сохранению объектов if (data.IsLeaf) { data.Count++; } data.HasSignal = signal.HasSignal; data.Message = signal.Message; if (signal.EventId != Guid.Empty) { data.LastEventId = signal.EventId; } data.LastChildBulbId = signal.ChildBulbId; // у листьев время завершения меняется, // а у родителей время завершения меняется только когда начинется новый статус if (data.IsLeaf) { // это нужно, например, чтобы у проверок и метрик EndDate показывал время последнего выполнения data.EndDate = signal.ProcessDate; // актуальность проверки и метрики определяется последним значением if (data.EventCategory == EventCategory.MetricStatus || data.EventCategory == EventCategory.UnitTestStatus) { data.ActualDate = signal.ActualDate; } else if (data.EventCategory == EventCategory.ComponentEventsStatus) { if (signal.ActualDate > data.ActualDate) { data.ActualDate = signal.ActualDate; } } else { throw new Exception("Неизвестный тип лампочки " + data.EventCategory); } } else { // у виртуальных лампочек время актуальности и завершения не меняется при продлении data.ActualDate = EventHelper.InfiniteActualDate; } CreateOrUpdateStatusEvent(signal.AccountId, data); }
protected void ChangeStatus(BulbSignal signal, BulbCacheWriteObject data) { // проверим пробел var startDate = GetStartDate(data, signal); if (startDate > data.ActualDate) { throw new Exception("startDate > data.ActualDate"); } // обновим статус data.PreviousStatus = data.Status; // запомним предыдущий if (signal.EventId != Guid.Empty) { data.FirstEventId = signal.EventId; data.LastEventId = signal.EventId; } data.Count = 1; data.Message = signal.Message; data.Status = signal.Status; data.LastChildBulbId = signal.ChildBulbId; if (data.IsLeaf) { data.ActualDate = signal.ActualDate; } else { // время актуальности колбасок, которые НЕ являются листьями дерева, бесконечо data.ActualDate = EventHelper.InfiniteActualDate; } data.StartDate = startDate; data.HasSignal = signal.HasSignal; data.EndDate = startDate; // меняется только при создании нового статуса var ownerId = data.GetOwnerId(); var statusEvent = AddStatusEvent(signal.AccountId, data, ownerId); }
protected IEventCacheReadObject AddStatusEvent(Guid accountId, BulbCacheWriteObject data, Guid ownerId) { var accountDbContext = Context.GetAccountDbContext(accountId); var eventType = SystemEventType.GetStatusEventType(data.EventCategory); var now = DateTime.Now; // создаем новый статус var newStatus = new Event() { Id = Guid.NewGuid(), Message = data.Message, ActualDate = data.ActualDate, Category = data.EventCategory, Count = data.Count, CreateDate = now, LastUpdateDate = now, EndDate = data.EndDate, Importance = EventImportanceHelper.Get(data.Status), OwnerId = ownerId, StartDate = data.StartDate, EventTypeId = eventType.Id, PreviousImportance = EventImportanceHelper.Get(data.PreviousStatus), IsSpace = data.IsSpace }; if (data.FirstEventId.HasValue && data.FirstEventId != Guid.Empty) { newStatus.FirstReasonEventId = data.FirstEventId; } var eventRepository = accountDbContext.GetEventRepository(); eventRepository.Add(newStatus); // обновим старый статус var oldStatus = eventRepository.GetByIdOrNull(data.StatusEventId); if (oldStatus != null) { // установим флажок, если это архивный статус if (oldStatus.Category == EventCategory.ComponentExternalStatus) { var archivedStatus = new ArchivedStatus() { EventId = oldStatus.Id }; var archivedStatusRepository = accountDbContext.GetArchivedStatusRepository(); archivedStatusRepository.Add(archivedStatus); } // старый статус завершается, когда начинается новый статус oldStatus.ActualDate = newStatus.StartDate; oldStatus.EndDate = newStatus.StartDate; oldStatus.LastUpdateDate = now; // убедимся, что очереди изменений нет изменений старого статуста, // иначе наши изменения через EF могут быть перезатёрты using (var oldStatusCache = AllCaches.Events.GetForWrite(oldStatus, accountId)) { oldStatusCache.WaitSaveChanges(); oldStatusCache.Unload(); } } // обновим лампочку через EF, чтобы {лампочка, старый статус и новый статус} сохранились одновременно // изменения лампочки будут сохранены дважды, воторой раз в очереди изменений // сейчас не понятно как этого избежать, дело в том, что после данного метода код может изменить кэш лампочки // и чтобы не потерять эти изменения сохраняем дважды data.StatusEventId = newStatus.Id; var bulbEF = accountDbContext.GetStatusDataRepository().GetById(data.Id); bulbEF.Count = data.Count; bulbEF.ActualDate = data.ActualDate; bulbEF.EndDate = data.EndDate; bulbEF.FirstEventId = data.FirstEventId; bulbEF.HasSignal = data.HasSignal; bulbEF.LastEventId = data.LastEventId; bulbEF.Message = data.Message; bulbEF.PreviousStatus = data.PreviousStatus; bulbEF.StartDate = data.StartDate; bulbEF.Status = data.Status; bulbEF.StatusEventId = data.StatusEventId; bulbEF.LastChildBulbId = data.LastChildBulbId; // убедимся что в очереди изменений нет других изменений лампочки, // иначе сохранённые через EF изменения могут быть потеряны data.WaitSaveChanges(); // todo нужно сохранять изменения в одном контексте (транзакции), // чтобы лампочка не потеряла ссылку на последний статус accountDbContext.SaveChanges(); var rEvent = AllCaches.Events.Find(new AccountCacheRequest() { AccountId = accountId, ObjectId = newStatus.Id }); return(rEvent); }