/// <summary> /// Initializes a new instance of the <see cref="T:RequestSubscriber"/> class. /// </summary> /// <param name="requestProcessor">The request processor.</param> public RequestSubscriber(RequestProcessor requestProcessor) { // Create the custom settings list customSettings = new Dictionary <string, string>(); // Create the filters list requestFilters = new List <RequestFilter>(); // Store the request processor this.requestProcessor = requestProcessor; // Create the regular expression instances regexBody = null; regexLabel = null; regexOperator = ""; }
/// <summary> /// Loads the configuration. /// </summary> /// <param name="xmlNodeConfig">The XML node config.</param> internal virtual void LoadConfiguration(XmlNode xmlNodeConfig) { // Load request manager general settings isEnabled = Convert.ToBoolean(xmlNodeConfig.Attributes["Enabled"].Value); description = xmlNodeConfig.Attributes["Description"].Value; processorType = xmlNodeConfig.Attributes["ProcessorType"].Value; minThreads = Math.Max(Convert.ToInt32(xmlNodeConfig.Attributes["MinThreads"].Value), 1); maxThreads = Math.Max(Convert.ToInt32(xmlNodeConfig.Attributes["MaxThreads"].Value), 1); workPauseSeconds = Math.Min(Convert.ToDecimal(xmlNodeConfig.Attributes["WorkPauseSeconds"].Value), 10); shutdownPauseSeconds = Math.Min(Convert.ToDecimal(xmlNodeConfig.Attributes["ShutdownPauseSeconds"].Value), 10); consumeUnprocessed = Convert.ToBoolean(xmlNodeConfig.Attributes["ConsumeUnprocessed"].Value); maxErrors = Math.Max(Convert.ToInt32(xmlNodeConfig.Attributes["MaxErrors"].Value), 0); // See if we're tracing if (this.RequestController.Trace) { // String builder message StringBuilder logMessage = new StringBuilder(); logMessage.AppendFormat("Loaded Request Manager <b>\"{0}\"</b> configuration.", description); logMessage.AppendFormat("<br>Type: {0}", processorType); logMessage.AppendFormat("<br>Enabled: {0}", isEnabled); logMessage.AppendFormat("<br>Description: {0}", description); logMessage.AppendFormat("<br>Min Threads: {0}", minThreads); logMessage.AppendFormat("<br>Max Threads: {0}", maxThreads); logMessage.AppendFormat("<br>Work Pause Secs: {0}", workPauseSeconds); logMessage.AppendFormat("<br>Shutdown Pause Secs: {0}", shutdownPauseSeconds); logMessage.AppendFormat("<br>Consume Unprocessed: {0}", consumeUnprocessed); logMessage.AppendFormat("<br>Max Errors: {0}", maxErrors); // Log debug information (using HTML file format) Logger.Write(new LogEntry( logMessage.ToString(), "Request Management Trace", 0, 0, TraceEventType.Information, "Request Management Trace", null)); } // If we're enabled load remaining settings if (IsEnabled) { // Load request manager custom settings RequestController.LoadCustomSettings(xmlNodeConfig.SelectSingleNode("CustomSettings"), customSettings); // The constructor for request processors ConstructorInfo requestProcessorConstructor = null; // Use reflection to store the constructor of the class that implements DataProvider Type t = Type.GetType(processorType, true); // Get public instance constructor that takes a RequestManager requestProcessorConstructor = t.GetConstructor(new Type[] { typeof(RequestManager) }); // Create the request processors, one for each thread for (int i = 0; i < maxThreads; i++) { // Create the request processor and pass this request manager RequestProcessor reqProcessor = (RequestProcessor)requestProcessorConstructor.Invoke(new Object[] { this }); // See if we're tracing if (this.RequestController.Trace) { // Log debug information (using HTML file format) Logger.Write(new LogEntry( string.Format("Loading Subscribers for Request Processor <b>#{0}</b> for Request Manager <b>\"{1}\"</b>", i + 1, description), "Request Management Trace", 0, 0, TraceEventType.Information, "Request Management Trace", null)); } // Get the request processor to load its configuration reqProcessor.LoadConfiguration(xmlNodeConfig.SelectSingleNode("Subscribers")); // Add the request processor to our list of processors requestProcessors.Add(reqProcessor); } } }
/// <summary> /// Threads the pool exception handler. /// </summary> /// <param name="workItem">The work item.</param> /// <param name="lastError">The last error.</param> public void ThreadPoolExceptionHandler(ThreadPoolWorkItem workItem, Exception lastError) { // One of the request processors has failed, // Exception handling is configured to "NotifyRethrow". // This is being called from a thread in the thread pool, // we must synchronise access to the controller try { // Enter the controller Monitor.Enter(this.requestController); // Get the request processor that failed RequestProcessor requestProcessor = (RequestProcessor)workItem.objInput[0]; // Make sure that we've stopped the request processor that failed requestProcessor.Stop(); // Increment the error count Interlocked.Increment(ref errorCount); // See if we've exceeded the error count for this request manager if (errorCount <= maxErrors) { // We can re-start, add the process request method back into the queue threadPool.InsertWorkItem(new ThreadPoolWorkItem(requestProcessor.RequestManager.Description, requestProcessor.Start, new object[] { requestProcessor }, false)); // Log that we had to restart the processor LogEntry logEntry = new LogEntry( "A Request Processor for the Request Manager \"" + description + "\"was restarted due to the following error; " + lastError.Message, "Request Management", 0, 0, TraceEventType.Warning, "Request Management", null); // Write to the log Logger.Write(logEntry); } else if (requestController.IsRunning) { // Store the error in the controller requestController.lastError = new Exception( "The Request Controller was stopped, the maximum number of errors (" + maxErrors.ToString() + ") was exceeded.", lastError); // Stop the controller, stops all the request managers and all the // request processors. We will continue to get exceptions until // this method completes, especially if the request manager is // configured for multiple threads requestController.Stop(); // Log that we had to stop the controller LogEntry logEntry = new LogEntry( "The Request Controller was stopped, the maximum number of errors (" + maxErrors.ToString() + ") for Request Manager \"" + description + "\" was exceeded." + Environment.NewLine + Environment.NewLine + "If you want the Request Manager to recover from errors and continue running, configure the RequestProcessor.Exception PostHandlingAction to None in your configuration file.", "Request Management", 0, 0, TraceEventType.Warning, "Request Management", null); // Write to the log Logger.Write(logEntry); } } finally { // Leave the controller Monitor.Exit(requestController); } }