public AddEventResult(BufferEventData bufferEventData) { if (bufferEventData == null) { throw new ArgumentNullException("bufferEventData"); } BufferEventData = bufferEventData; }
protected virtual void PrepareBufferEventData(BufferEventData bufferEvent) { // обрежим длинные свойства события PrepareDataHelper.PrepareEvent(bufferEvent.SendEventBase); // установим GlobalJoinKey bufferEvent.GlobalJoinKey = GetGlobalJoinKey( bufferEvent.ComponentControl, bufferEvent.SendEventBase); }
public AddEventResult AddEvent(SendEventBase eventBase) { var inputEvent = new BufferEventData(eventBase.ComponentControl, eventBase); if (eventBase.Ignore) { // если игнорируем, то в очередь НЕ помещем inputEvent.Status = AddEventStatus.Removed; return(new AddEventResult(inputEvent)); } var outputEvent = AddOrJoin(inputEvent); return(new AddEventResult(outputEvent)); }
public void Add(BufferEventData bufferEvent) { lock (SynchRoot) { List <BufferEventData> list = null; if (Events.TryGetValue(bufferEvent.GlobalJoinKey, out list) == false) { list = new List <BufferEventData>(); Events.Add(bufferEvent.GlobalJoinKey, list); } list.Add(bufferEvent); bufferEvent.Size = 0; UpdateSize(bufferEvent); } }
protected virtual bool AreJoinPropertiesEqual(BufferEventData a, BufferEventData b) { // должны быть равны = EventCategory + JoinKey + IsServerTime + ComponentSystemName + TypeSystemName return(a.SendEventBase.EventCategory == b.SendEventBase.EventCategory && a.SendEventBase.JoinKey == b.SendEventBase.JoinKey && (a.SendEventBase.Importance ?? EventImportance.Unknown) == (b.SendEventBase.Importance ?? EventImportance.Unknown) && a.SendEventBase.IsServerTime == b.SendEventBase.IsServerTime && string.Equals( a.ComponentControl.SystemName, b.ComponentControl.SystemName, StringComparison.OrdinalIgnoreCase) && string.Equals( a.SendEventBase.TypeSystemName, b.SendEventBase.TypeSystemName, StringComparison.OrdinalIgnoreCase)); }
public void UpdateSize(BufferEventData bufferEvent) { lock (SynchRoot) { int oldSize = bufferEvent.Size; bufferEvent.Size = bufferEvent.GetSize(); SizeBytes -= oldSize; SizeBytes += bufferEvent.Size; if (SizeBytes < 0) { SizeBytes = 0; } if (SizeBytes > MaxSizeBytes) { Client.InternalLog.Warning("Очищаем очередь событий"); var allEvents = GetAll(); allEvents = allEvents.OrderBy(x => x.LastAttempSendOrJoinDate).ToList(); foreach (var bufferEventData in allEvents) { // удаляем события пока размер очереди не будет меньше половины максимума if (SizeBytes < MaxSizeBytes / 2) { break; } List <BufferEventData> list = null; if (Events.TryGetValue(bufferEventData.GlobalJoinKey, out list)) { if (list.Remove(bufferEventData)) { SizeBytes -= bufferEvent.Size; if (list.Count == 0) { Events.Remove(bufferEventData.GlobalJoinKey); } } } } if (Count() == 0) { SizeBytes = 0; } Client.InternalLog.Debug("Очередь событий очищена"); } } }
protected BufferEventData AddOrJoin(BufferEventData newBufferEvent) { Queue.MaxSizeBytes = Client.Config.Events.EventManager.QueueBytes; PrepareBufferEventData(newBufferEvent); lock (Queue.SynchRoot) { // если JoinInterval==0, то склеивать нельзя if (newBufferEvent.SendEventBase.JoinInterval == TimeSpan.Zero) { Queue.Add(newBufferEvent); return(newBufferEvent); } // проверим, можно ли склеить var bufferEvents = Queue.GetAllByGlobalJoinKey(newBufferEvent.GlobalJoinKey); // склеивать можно только с последним, поэтому отсортируем по дате создания bufferEvents = bufferEvents.OrderByDescending(x => x.CreateDate).ToList(); var lastEvent = bufferEvents.FirstOrDefault(x => AreJoinPropertiesEqual(x, newBufferEvent)); // если это первое событие if (lastEvent == null) { Queue.Add(newBufferEvent); return(newBufferEvent); } // рассчитаем время склейки TimeSpan joinInterval = newBufferEvent.SendEventBase.JoinInterval ?? TimeSpan.Zero; var currentDate = newBufferEvent.SendEventBase.StartDate.Value; bool canJoinByTime = currentDate + joinInterval >= currentDate; // если событие уже было и время склейки НЕ протухло if (canJoinByTime) { lock (lastEvent.SynchRoot) { // увеличим счетчик lastEvent.SendEventBase.Count = AddCount(lastEvent.SendEventBase.Count ?? 1, newBufferEvent.SendEventBase.Count ?? 1); // дату начала не меняем! // обновим сообщение lastEvent.SendEventBase.Message = newBufferEvent.SendEventBase.Message; // обновим важность lastEvent.SendEventBase.Importance = newBufferEvent.SendEventBase.Importance; lastEvent.LastAddDate = newBufferEvent.CreateDate; if (lastEvent.Status == AddEventStatus.Sended) { lastEvent.Status = AddEventStatus.WaitForJoin; } else if (lastEvent.Status == AddEventStatus.Joined) { lastEvent.Status = AddEventStatus.WaitForJoin; } } return(lastEvent); } // если такое событие уже было, но время склейки протухло Queue.Add(newBufferEvent); return(newBufferEvent); } }
protected virtual void BeginFlush(DateTime date) { try { if (Disabled) { return; } if (Queue.Count() == 0) { return; } if (Client.CanSendData == false) { return; } if (Client.CanConvertToServerDate() == false) { return; } List <BufferEventData> allEvents = null; lock (Queue.SynchRoot) { allEvents = Queue.GetAll(); } if (allEvents == null || allEvents.Count == 0) { return; } // получаем события для отправки int maxSendCount = Client.Config.Events.EventManager.MaxSend; var sendEvents = allEvents .Where(x => x.Status == AddEventStatus.WaitForSend && x.CreateDate <= date && x.ComponentControl.IsFake() == false) .OrderBy(x => x.Errors) .ThenBy(x => x.CreateDate) .Take(maxSendCount) .ToList(); // получаем события для склейки int maxJoinCount = Client.Config.Events.EventManager.MaxJoin; var joinEvents = allEvents .Where(x => x.Status == AddEventStatus.WaitForJoin && x.ComponentControl.IsFake() == false && x.LastAttempSendOrJoinDate <= date) .OrderBy(x => x.Errors) .Take(maxJoinCount) .ToList(); // создаем задачи для отправки foreach (var bufferEventData in sendEvents) { BufferEventData data = bufferEventData; TaskQueue.Add(() => SendOneEvent(data)); } // создаем задачи для склейки if (joinEvents.Any(x => x.ComponentControl.Info == null)) { throw new Exception("joinEvents.Any(x => x.ComponentControl.Info == null)"); } joinEvents = joinEvents.OrderBy(x => x.ComponentControl.Info.Id).ToList(); const int batchCount = 20;// будем продлевать 20 событий за раз var batchEvents = new List <BufferEventData>(batchCount); foreach (var bufferEventData in joinEvents) { batchEvents.Add(bufferEventData); if (batchEvents.Count == batchCount) { var tempEvents1 = new List <BufferEventData>(); tempEvents1.AddRange(batchEvents); TaskQueue.Add(() => JoinEvents(tempEvents1)); batchEvents.Clear(); } } if (batchEvents.Count > 0) { var tempEvents = new List <BufferEventData>(); tempEvents.AddRange(batchEvents); TaskQueue.Add(() => JoinEvents(tempEvents)); } } catch (Exception exception) { Client.InternalLog.Error("Ошибка обработки очереди событий", exception); } }
protected void SendOneEvent(BufferEventData bufferEventData) { if (Client.CanSendData == false) { return; } if (Client.CanConvertToServerDate() == false) { return; } bool success = false; try { int oldCount = 0; SendEventBase eventBase = null; lock (bufferEventData.SynchRoot) { oldCount = bufferEventData.SendEventBase.Count.Value; if (bufferEventData.Status != AddEventStatus.WaitForSend) { success = true; return; } eventBase = bufferEventData.SendEventBase.CreateBaseCopy(); bufferEventData.Status = AddEventStatus.BeginSend; } var response = eventBase.Send(); lock (bufferEventData.SynchRoot) { bufferEventData.LastAttempSendOrJoinDate = DateTime.Now; if (response.Success) { bufferEventData.EventId = response.Data.EventId; bufferEventData.EventTypeId = response.Data.EventTypeId; bufferEventData.Errors = 0; bufferEventData.LastSuccessSendOrJoinDate = bufferEventData.LastAttempSendOrJoinDate; // вычтим из текущего Count то что отправили if (bufferEventData.SendEventBase.Count < int.MaxValue) { bufferEventData.SendEventBase.Count -= oldCount; } if (bufferEventData.SendEventBase.Count < 0) { bufferEventData.SendEventBase.Count = 0; } if (bufferEventData.Status != AddEventStatus.Removed) { if (bufferEventData.SendEventBase.Count > 1) { bufferEventData.Status = AddEventStatus.WaitForJoin; } else { bufferEventData.Status = AddEventStatus.Sended; } } success = true; } } } catch (Exception exception) { Client.InternalLog.Error("Ошибка отправки события из очереди", exception); } finally { lock (bufferEventData.SynchRoot) { if (success) { } else { if (bufferEventData.Status != AddEventStatus.Removed) { bufferEventData.Status = AddEventStatus.WaitForSend; } bufferEventData.Errors++; } } } }