/// <summary> /// Initializes a new instance of the <see cref="MessagePublisher"/> class. /// </summary> /// <param name="message">The message to publish.</param> internal void PublishMessage(string message) { // Add the message into the queue. //this.messageQueue.Enqueue(message); try { using (var databaseContext = new ZentityAdministrationDataContext(Globals.ZentityConnectionString)) { MessageQueueRecovery newMessage = new MessageQueueRecovery { Id = Guid.NewGuid(), RawMessage = message }; databaseContext.MessageQueueRecoveries.InsertOnSubmit(newMessage); databaseContext.SubmitChanges(); this.resetEvent.Set(); } } catch (Exception ex) { Globals.TraceMessage(TraceEventType.Error, ex.ToString(), TraceMessages.ExceptionAddingBrokerMessageToQueue); } }
/// <summary> /// Parses the message. /// </summary> /// <param name="currentMessageQueueCount">The current message queue count.</param> /// <returns>Number of messages parsed.</returns> private static int ParseMessages(int currentMessageQueueCount) { int messagesParsed = 0; if (currentMessageQueueCount == 0) { return(messagesParsed); } try { using (var databaseContext = new ZentityAdministrationDataContext(Globals.ZentityConnectionString)) { var messagesCurrentlyInQueue = databaseContext.MessageQueueRecoveries.Where(message => message.DateTimeStamp <= DateTime.Now).ToList(); // Iterate on each raw message from the queue and parse them into ChangeMessage records foreach (var messageFromQueue in messagesCurrentlyInQueue) { if (string.IsNullOrWhiteSpace(messageFromQueue.RawMessage)) { continue; } try { // Make it a proper xml. StringBuilder messageBuilder = new StringBuilder(); messageBuilder.Append("<"); messageBuilder.Append(MessagesElement); messageBuilder.Append(">"); messageBuilder.Append(messageFromQueue.RawMessage); messageBuilder.Append("</"); messageBuilder.Append(MessagesElement); messageBuilder.Append(">"); XElement messages = XElement.Parse(messageBuilder.ToString()); // Create a list of ChangeMessages for the current raw message in the iteration List <ChangeMessageRecovery> changeMessageList = new List <ChangeMessageRecovery>(); // Parse each raw message in and add them to the ChangeMessage list. Parallel.ForEach(messages.Elements(ZentityMessageElement), message => { IEnumerable <ChangeMessageRecovery> parsedChangeMessageList = ParseMessage(message); lock (changeMessageList) { changeMessageList.AddRange(parsedChangeMessageList); messagesParsed++; } }); if (changeMessageList.Count > 0) { databaseContext.ChangeMessageRecoveries.InsertAllOnSubmit(changeMessageList); } } catch (Exception ex) { Globals.TraceMessage(TraceEventType.Error, ex.ToString(), TraceMessages.ExceptionParsingMessage); } } databaseContext.MessageQueueRecoveries.DeleteAllOnSubmit(messagesCurrentlyInQueue); databaseContext.SubmitChanges(System.Data.Linq.ConflictMode.ContinueOnConflict); } } catch (Exception exception) { Globals.TraceMessage(TraceEventType.Error, exception.ToString(), exception.Message); } return(messagesParsed); }
/// <summary> /// Pushes the messages to the publishing service. /// </summary> /// <param name="currentChangeMessageCount">The current change message count.</param> private void PushMessages(int currentChangeMessageCount) { if (currentChangeMessageCount <= 0) { return; } using (var databaseContext = new ZentityAdministrationDataContext(Globals.ZentityConnectionString)) { // Fetch the distinct list of resource type names //var distinctResourceTypes = databaseContext.ChangeMessageRecoveries.Select(changeMessage => new {changeMessage.DataModelNamespace, changeMessage.ResourceTypeName}).Distinct().ToArray(); var distinctResourceTypes = (from changeMessage in databaseContext.ChangeMessageRecoveries group changeMessage by new { changeMessage.DataModelNamespace, changeMessage.ResourceTypeName } into groupResType orderby groupResType.Count() select groupResType.Key).Distinct().ToArray(); // Iterate on the resource type names and push the messages for that resource type // to the publishing service. foreach (var resourceType in distinctResourceTypes) { // Keep retrying to send the messages in the list till it is successfully sent to the publishing service bool flagSucceeded = false; int retryCounter = 0; IQueryable <ChangeMessageRecovery> changeMessageListForResourceType = null; do { try { PublishStatus resourceTypePublishStatus = this.publishingProxy.GetPublishingStatusByResourceType(resourceType.DataModelNamespace, resourceType.ResourceTypeName); int messagesSent; if (resourceTypePublishStatus == null || resourceTypePublishStatus.CurrentStage == PublishStage.Completed || resourceTypePublishStatus.CurrentStage == PublishStage.AbortedOnError || resourceTypePublishStatus.CurrentStage == PublishStage.AbortedOnDemand) { // Fetch all messages of a particular resource type changeMessageListForResourceType = databaseContext.ChangeMessageRecoveries.Where(changeMessage => changeMessage.ResourceTypeName == resourceType.ResourceTypeName && changeMessage.DataModelNamespace == resourceType.DataModelNamespace); // Convert the change message list from database into resource change messages for the publishing service var resChangeMessageListForResourceType = changeMessageListForResourceType.ToResourceChangeMessageList(); messagesSent = resChangeMessageListForResourceType.Count(); // Call the publishing service with the resource change message list. string serializedFilePath = SerializeResourceChangeMessageList(resChangeMessageListForResourceType); if (!string.IsNullOrWhiteSpace(serializedFilePath)) { this.publishingProxy.UpdateCollection(serializedFilePath, resourceType.DataModelNamespace, resourceType.ResourceTypeName, null); flagSucceeded = true; } } else { Globals.TraceMessage(TraceEventType.Information, string.Empty, string.Format(TraceMessages.PublishingServiceBusyMessagesWillNotBeSent, resourceType)); break; } Globals.TraceMessage(TraceEventType.Information, string.Empty, string.Format(TraceMessages.MessagesSentToPublishingService, resourceType, messagesSent)); } catch (EndpointNotFoundException ex) { Globals.TraceMessage( TraceEventType.Error, ex.Message, string.Format("{0} {1}", string.Format(TraceMessages.PublishingServiceEndpointUnavailableWithSuggestion, Worker.RetryInterval.Minutes), string.Format(TraceMessages.RetryCount, retryCounter))); } catch (Exception ex) { Globals.TraceMessage( TraceEventType.Error, ex.Message, string.Format("{0} {1}", string.Format(TraceMessages.ExceptionThrownByPublishingService, Worker.RetryInterval.Minutes), string.Format(TraceMessages.RetryCount, retryCounter))); } // If the message couldnt be sent to the publishing service then wait and retry. if (!flagSucceeded) { if (retryCounter < MaxRetryCount) { this.publishingProxy = Worker.RecreatePublishingProxy(this.publishingProxy); retryCounter++; } else { // Break the loop for this ResourceType as the max retry count has been reached. // The messages for this ResourceType will not be deleted and will be retried next time. break; } } } while (flagSucceeded == false); // Remove the messages of a particular resource type from the message list. if (flagSucceeded) { databaseContext.ChangeMessageRecoveries.DeleteAllOnSubmit(changeMessageListForResourceType); databaseContext.SubmitChanges(System.Data.Linq.ConflictMode.ContinueOnConflict); } } } }