protected bool RegisterIncomingMessage(TMessage message) { try { var resolver = new Newtonsoft.Json.Serialization.DefaultContractResolver(); resolver.DefaultMembersSearchFlags = resolver.DefaultMembersSearchFlags | System.Reflection.BindingFlags.NonPublic; using (var db = new DB.DataContext()) { var mess = new DB.MessageQueue() { IdMessageType = IdMessageType, StateType = DB.MessageStateType.NotProcessed, Direction = true, DateCreate = DateTime.Now, MessageInfo = Newtonsoft.Json.JsonConvert.SerializeObject(message, new Newtonsoft.Json.JsonSerializerSettings() { ContractResolver = resolver }), }; db.MessageQueue.Add(mess); db.SaveChanges(); return(true); } } catch (Exception ex) { this.RegisterEvent(Journaling.EventType.Error, "Ошибка регистрации входящего сообщения", null, ex); return(false); } }
private void ClearLastNDays() { try { if (_taskDescriptionClear == null) { return; } foreach (var pair in _messagingServiceOptions) { var lastNDaysValue = pair.Value.LimitByLastNDays ?? _messagingServiceOptionsDefault.LimitByLastNDays; if (!lastNDaysValue.HasValue || lastNDaysValue.Value < 0) { continue; } var dateLimit = DateTimeOffset.UtcNow.AddDays(-lastNDaysValue.Value); using (var db = new DB.DataContext()) { var hasRecords = true; while (hasRecords) { for (int i = 0; i <= 2; i++) { try { var rows = db.MessageQueue.Where(x => x.IdMessageType == pair.Key && x.DateCreate < dateLimit).OrderBy(x => x.DateCreate).Take(500).ToList(); hasRecords = rows.Count > 0; if (hasRecords) { db.MessageQueue.RemoveRange(rows); db.SaveChanges(); } break; } catch { if (i == 2) { hasRecords = false; } } } } } } } catch (Exception ex) { this.RegisterEvent(EventType.Error, "Ошибка очистки старых сообщений сервисов обработки сообщений", null, ex); } }
protected bool RegisterOutcomingMessage(TMessage message, out MessageInfo <TMessage> messageInfo) { try { var resolver = new Newtonsoft.Json.Serialization.DefaultContractResolver(); resolver.DefaultMembersSearchFlags = resolver.DefaultMembersSearchFlags | System.Reflection.BindingFlags.NonPublic; using (var db = new DB.DataContext()) { var mess = new DB.MessageQueue() { IdMessageType = IdMessageType, StateType = DB.MessageStateType.NotProcessed, Direction = false, DateCreate = DateTime.Now, MessageInfo = Newtonsoft.Json.JsonConvert.SerializeObject(message, new Newtonsoft.Json.JsonSerializerSettings() { ContractResolver = resolver }), }; db.MessageQueue.Add(mess); db.SaveChanges(); var taskOutcomingMessages = _taskOutcomingMessages; if (taskOutcomingMessages != null) { AppCore.Get <TaskSchedulingManager>()?.ExecuteTask(taskOutcomingMessages); } messageInfo = new MessageInfo <TMessage>(new IntermediateStateMessage <TMessage>(message, mess)); return(true); } } catch (Exception ex) { this.RegisterEvent(Journaling.EventType.Error, "Ошибка регистрации исходящего сообщения", null, ex); messageInfo = null; return(false); } }
void IMessagingServiceInternal.PrepareIncomingHandle(TimeSpan executeInterval) { if (AppCore.GetState() != CoreComponentState.Started) { return; } var type = GetType(); if (!_executingFlags.TryLock(TasksIncomingHandle)) { return; } _executingFlags.ReleaseLock(nameof(RegisterIncomingMessage)); int messagesAll = 0; int messagesHandled = 0; int messagesErrors = 0; try { using (var db = new DB.DataContext()) using (var scope = db.CreateScope(TransactionScopeOption.Suppress)) { var timeEnd = DateTimeOffset.Now.Add(executeInterval); while (DateTimeOffset.Now < timeEnd) { var messages = GetMessages(db, true, 100, _incomingHandleQueueInfo); if (messages.IsNullOrEmpty()) { break; } messagesAll += messages.Count; var components = GetComponents(). OfType <IncomingMessageHandler <TMessage> >(). Select(x => new { Component = x, IdTypeComponent = ItemTypeFactory.GetItemType(x.GetType())?.IdItemType }). OrderBy(x => ((IPoolObjectOrdered)x.Component).OrderInPool). ToList(); foreach (var intermediateMessage in messages) { if (DateTimeOffset.Now >= timeEnd) { break; } var componentsForMessage = components; if (intermediateMessage.MessageSource.IdTypeComponent.HasValue) { components = components.Where(x => x.IdTypeComponent.HasValue && x.IdTypeComponent == intermediateMessage.MessageSource.IdTypeComponent).ToList(); } foreach (var componentInfo in components) { try { var component = componentInfo.Component; var messageInfo = new MessageInfo <TMessage>(intermediateMessage); var componentResult = component.OnPrepare(messageInfo, this); if (componentResult != null) { intermediateMessage.MessageSource.DateChange = DateTime.Now; switch (componentResult.StateType) { case MessageStateType.Completed: intermediateMessage.MessageSource.StateType = DB.MessageStateType.Complete; intermediateMessage.MessageSource.State = null; intermediateMessage.MessageSource.IdTypeComponent = null; intermediateMessage.MessageSource.DateDelayed = null; break; case MessageStateType.Delayed: intermediateMessage.MessageSource.StateType = DB.MessageStateType.NotProcessed; intermediateMessage.MessageSource.State = componentResult.State; intermediateMessage.MessageSource.IdTypeComponent = null; intermediateMessage.MessageSource.DateDelayed = componentResult.DateDelayed; break; case MessageStateType.Repeat: intermediateMessage.MessageSource.StateType = DB.MessageStateType.Repeat; intermediateMessage.MessageSource.State = componentResult.State; intermediateMessage.MessageSource.IdTypeComponent = componentInfo.IdTypeComponent; intermediateMessage.MessageSource.DateDelayed = componentResult.DateDelayed; break; case MessageStateType.Error: intermediateMessage.MessageSource.StateType = DB.MessageStateType.Error; intermediateMessage.MessageSource.State = componentResult.State; intermediateMessage.MessageSource.IdTypeComponent = null; intermediateMessage.MessageSource.DateDelayed = null; break; } messagesHandled++; db.SaveChanges(); break; } } catch { messagesErrors++; continue; } } _incomingHandleQueueInfo.IdQueueCurrent = intermediateMessage.MessageSource.IdQueue; } } db.SaveChanges(); scope.Complete(); } } catch (Exception ex) { this.RegisterServiceState(ServiceStatus.RunningWithErrors, $"Сообщений получено для обработки - {messagesAll}. Обработано - {messagesHandled}. Ошибки обработки - {messagesErrors}.", ex); } finally { _executingFlags.ReleaseLock(TasksIncomingHandle); } }
void IMessagingServiceInternal.PrepareIncomingReceive(TimeSpan executeInterval) { if (AppCore.GetState() != CoreComponentState.Started) { return; } var type = GetType(); if (!_executingFlags.TryLock(TasksIncomingReceive)) { return; } int messagesReceived = 0; try { using (var db = new DB.DataContext()) { var components = GetComponents(). OfType <IncomingMessageReceiver <TMessage> >(). Select(x => new { Component = x, IdTypeComponent = ItemTypeFactory.GetItemType(x.GetType())?.IdItemType }). OrderBy(x => ((IPoolObjectOrdered)x.Component).OrderInPool). ToList(); var timeEnd = DateTimeOffset.Now.Add(executeInterval); using (var scope = db.CreateScope(TransactionScopeOption.Suppress)) // Здесь Suppress вместо RequiresNew, т.к. весь процесс отправки занимает много времени и блокировать таблицу нельзя. { foreach (var componentInfo in components) { try { var messages = componentInfo.Component.OnReceive(this); if (messages != null && messages.Count > 0) { int countAdded = 0; foreach (var message in messages) { if (message == null) { continue; } var stateType = DB.MessageStateType.NotProcessed; if (message.IsComplete) { stateType = DB.MessageStateType.Complete; } if (message.IsError) { stateType = DB.MessageStateType.Error; } var mess = new DB.MessageQueue() { IdMessageType = IdMessageType, Direction = true, State = message.State, StateType = stateType, DateCreate = DateTime.Now, DateDelayed = message.DateDelayed, MessageInfo = Newtonsoft.Json.JsonConvert.SerializeObject(message.Message), }; db.MessageQueue.Add(mess); countAdded++; messagesReceived++; if (countAdded >= 50) { db.SaveChanges(); countAdded = 0; } } db.SaveChanges(); } } catch (Exception ex) { this.RegisterServiceEvent(Journaling.EventType.Error, $"Ошибка вызова '{nameof(componentInfo.Component.OnReceive)}'", $"Ошибка вызова '{nameof(componentInfo.Component.OnReceive)}' для компонента '{componentInfo?.Component?.GetType()?.FullName}'.", ex); continue; } try { while (true) { var message = componentInfo.Component.OnBeginReceive(this); if (message == null) { break; } DB.MessageQueue queueMessage = null; var queueState = DB.MessageStateType.NotProcessed; if (message.IsComplete) { queueState = DB.MessageStateType.Complete; } if (message.IsError) { queueState = DB.MessageStateType.Error; } try { var mess = new DB.MessageQueue() { IdMessageType = IdMessageType, Direction = true, State = message.State, StateType = DB.MessageStateType.IntermediateAdded, DateCreate = DateTime.Now, DateDelayed = message.DateDelayed, MessageInfo = Newtonsoft.Json.JsonConvert.SerializeObject(message.Message), }; db.MessageQueue.Add(mess); db.SaveChanges(); queueMessage = mess; } catch (Exception ex) { this.RegisterServiceEvent(Journaling.EventType.Error, $"Ошибка регистрации сообщения после '{nameof(componentInfo.Component.OnBeginReceive)}'", $"Ошибка регистрации сообщения после вызова '{nameof(componentInfo.Component.OnBeginReceive)}' для компонента '{componentInfo?.Component?.GetType()?.FullName}'.", ex); try { componentInfo.Component.OnEndReceive(false, message, this); } catch (Exception ex2) { this.RegisterServiceEvent(Journaling.EventType.Error, $"Ошибка вызова '{nameof(componentInfo.Component.OnBeginReceive)}'", $"Ошибка вызова '{nameof(componentInfo.Component.OnBeginReceive)}' для компонента '{componentInfo?.Component?.GetType()?.FullName}' после ошибки регистрации сообщения.", ex2); } continue; } try { var endReceiveResult = componentInfo.Component.OnEndReceive(true, message, this); if (endReceiveResult) { queueMessage.StateType = queueState; } else { db.MessageQueue.Remove(queueMessage); } db.SaveChanges(); } catch (Exception ex) { this.RegisterServiceEvent(Journaling.EventType.Error, $"Ошибка вызова '{nameof(componentInfo.Component.OnBeginReceive)}'", $"Ошибка вызова '{nameof(componentInfo.Component.OnBeginReceive)}' для компонента '{componentInfo?.Component?.GetType()?.FullName}' после успешной регистрации сообщения.", ex); } if (DateTimeOffset.Now >= timeEnd) { break; } } } catch (Exception ex) { this.RegisterServiceEvent(Journaling.EventType.Error, $"Ошибка вызова '{nameof(componentInfo.Component.OnBeginReceive)}'", $"Ошибка вызова '{nameof(componentInfo.Component.OnBeginReceive)}' для компонента '{componentInfo?.Component?.GetType()?.FullName}'.", ex); continue; } } db.SaveChanges(); scope.Complete(); } } if (messagesReceived > 0) { this.RegisterServiceState(ServiceStatus.RunningIdeal, $"Сообщений получено - {messagesReceived}."); } var service = AppCore.Get <Monitor>().GetService(ServiceID); if (service != null && (DateTime.Now - service.LastDateEvent).TotalHours >= 1) { this.RegisterServiceState(ServiceStatus.RunningIdeal, $"Сообщений нет, сервис работает без ошибок."); } } catch (Exception ex) { this.RegisterServiceState(ServiceStatus.RunningWithErrors, $"Сообщений получено - {messagesReceived}.", ex); } finally { _executingFlags.ReleaseLock(TasksIncomingReceive); } }
void IMessagingServiceInternal.PrepareOutcoming(TimeSpan executeInterval) { if (AppCore.GetState() != CoreComponentState.Started) { return; } var type = GetType(); if (!_executingFlags.TryLock(TasksOutcomingSend)) { return; } _executingFlags.ReleaseLock(nameof(RegisterOutcomingMessage)); int messagesAll = 0; int messagesSent = 0; int messagesErrors = 0; try { using (var db = new DB.DataContext()) using (var scope = db.CreateScope(TransactionScopeOption.Suppress)) // Здесь Suppress вместо RequiresNew, т.к. весь процесс отправки занимает много времени и блокировать таблицу нельзя. { var timeEnd = DateTimeOffset.Now.Add(executeInterval); while (DateTimeOffset.Now < timeEnd) { var messages = GetMessages(db, false, 100, _outcomingQueueInfo); if (messages.IsNullOrEmpty()) { break; } messagesAll += messages.Count; OnBeforeExecuteOutcoming(messagesAll); var processedMessages = new List <IntermediateStateMessage <TMessage> >(); var time = new MeasureTime(); foreach (var intermediateMessage in messages) { if (DateTimeOffset.Now >= timeEnd) { break; } if (intermediateMessage.MessageSource.StateType == DB.MessageStateType.Error) { processedMessages.Add(intermediateMessage); continue; } var components = GetComponents(). OfType <OutcomingMessageSender <TMessage> >(). Select(x => new { Component = x, IdTypeComponent = ItemTypeFactory.GetItemType(x.GetType())?.IdItemType }). OrderBy(x => ((IPoolObjectOrdered)x.Component).OrderInPool). ToList(); if (intermediateMessage.MessageSource.IdTypeComponent.HasValue) { components = components.Where(x => x.IdTypeComponent.HasValue && x.IdTypeComponent == intermediateMessage.MessageSource.IdTypeComponent).ToList(); } foreach (var componentInfo in components) { try { var component = componentInfo.Component; var messageInfo = new MessageInfo <TMessage>(intermediateMessage); var componentResult = component.OnSend(messageInfo, this); if (componentResult != null) { intermediateMessage.MessageSource.DateChange = DateTime.Now; switch (componentResult.StateType) { case MessageStateType.Completed: intermediateMessage.MessageSource.StateType = DB.MessageStateType.Complete; intermediateMessage.MessageSource.State = null; intermediateMessage.MessageSource.IdTypeComponent = null; intermediateMessage.MessageSource.DateDelayed = null; break; case MessageStateType.Delayed: intermediateMessage.MessageSource.StateType = DB.MessageStateType.NotProcessed; intermediateMessage.MessageSource.State = componentResult.State; intermediateMessage.MessageSource.IdTypeComponent = null; intermediateMessage.MessageSource.DateDelayed = componentResult.DateDelayed; break; case MessageStateType.Repeat: intermediateMessage.MessageSource.StateType = DB.MessageStateType.Repeat; intermediateMessage.MessageSource.State = componentResult.State; intermediateMessage.MessageSource.IdTypeComponent = componentInfo.IdTypeComponent; intermediateMessage.MessageSource.DateDelayed = componentResult.DateDelayed; break; case MessageStateType.Error: intermediateMessage.MessageSource.StateType = DB.MessageStateType.Error; intermediateMessage.MessageSource.State = componentResult.State; intermediateMessage.MessageSource.IdTypeComponent = null; intermediateMessage.MessageSource.DateDelayed = componentResult.DateDelayed; break; } messagesSent++; processedMessages.Add(intermediateMessage); break; } } catch { messagesErrors++; continue; } } _outcomingQueueInfo.IdQueueCurrent = intermediateMessage.MessageSource.IdQueue; if (time.Calculate(false).TotalSeconds >= 3) { db.SaveChanges(); processedMessages.Clear(); time.Start(); } } if (processedMessages.Count > 0) { db.SaveChanges(); } } db.SaveChanges(); scope.Complete(); } } catch (Exception ex) { this.RegisterServiceState(ServiceStatus.RunningWithErrors, $"Сообщений получено для отправки - {messagesAll}. Отправлено - {messagesSent}. Ошибки отправки - {messagesErrors}.", ex); } finally { _executingFlags.ReleaseLock(TasksOutcomingSend); } }