예제 #1
0
 public ApplicationService(ApplicationServiceConfig config)
 {
     _databaseName         = config.DatabaseName;
     _schemaName           = config.SchemaName;
     _queueName            = config.QueueName;
     _executablePath       = config.ExecutablePath;
     _workingDirectory     = config.WorkingDirectory;
     _commandLineArguments = config.CommandLineArguments;
     _processes            = new Process[config.MaxConcurrency];
     _minimumConcurrency   = config.MinConcurrency;
 }
예제 #2
0
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main(params string[] args)
        {
            var notificationConfigs = new List <NotificationServiceConfig>();
            var applicationConfigs  = new List <ApplicationServiceConfig>();

            try
            {
                Logger.TraceEvent(TraceEventType.Information, "Loading configuration...");
                var      appDirectory = System.Reflection.Assembly.GetExecutingAssembly().Location;
                FileInfo file         = new FileInfo(appDirectory);
                var      configPath   = Path.Combine(file.Directory.Parent.FullName, @"Config\EAService.config");
                var      eaConfig     = XElement.Load(configPath);
                Logger.TraceEvent(TraceEventType.Information, "Loaded config from file.");
                XmlNamespaceManager nsman = new XmlNamespaceManager(new NameTable());
                XNamespace          ea    = "http://schemas.microsoft.com/sqlserver/2008/10/servicebroker/externalactivator";
                nsman.AddNamespace("ea", ea.ToString());
                var storedProc = eaConfig.Element(ea + "StoredProcedure").AsString();
                if (string.IsNullOrWhiteSpace(storedProc))
                {
                    throw new Exception("The configuration needs to include the StoredProcedure element as a child of the Activator element.");
                }

                var notificationElements = eaConfig.XPathSelectElements("ea:NotificationServiceList/ea:NotificationService", nsman);
                if (notificationElements == null || !notificationElements.Any())
                {
                    throw new Exception("The EAService.config was not configured with notification services.");
                }

                foreach (var notificationElement in notificationElements)
                {
                    var config = new NotificationServiceConfig()
                    {
                        StoredProcedure  = storedProc,
                        ConnectionString = notificationElement.XPathSelectElement("ea:ConnectionString/ea:Unencrypted", nsman).AsString()
                    };
                    notificationConfigs.Add(config);
                }

                var applicationElements = eaConfig.XPathSelectElements("ea:ApplicationServiceList/ea:ApplicationService", nsman);
                if (applicationElements == null || !applicationElements.Any())
                {
                    throw new Exception("The EAService.config was not configured with application services.");
                }

                foreach (var applicationElement in applicationElements)
                {
                    string maxConcVal = applicationElement.XPathSelectElement("ea:Concurrency", nsman)?.Attribute("max")?.Value;
                    string minConcVal = applicationElement.XPathSelectElement("ea:Concurrency", nsman)?.Attribute("min")?.Value;
                    int    maxConc    = int.TryParse(maxConcVal, out maxConc) ? Math.Max(maxConc, 0) : 0;
                    int    minConc    = int.TryParse(minConcVal, out minConc) ? Math.Max(minConc, 0) : 0;
                    var    config     = new ApplicationServiceConfig()
                    {
                        DatabaseName         = applicationElement.XPathSelectElement("ea:OnNotification/ea:DatabaseName", nsman).AsString(),
                        SchemaName           = applicationElement.XPathSelectElement("ea:OnNotification/ea:SchemaName", nsman).AsString(),
                        QueueName            = applicationElement.XPathSelectElement("ea:OnNotification/ea:QueueName", nsman).AsString(),
                        ExecutablePath       = applicationElement.XPathSelectElement("ea:LaunchInfo/ea:ImagePath", nsman).AsString(),
                        WorkingDirectory     = applicationElement.XPathSelectElement("ea:LaunchInfo/ea:WorkDir", nsman).AsString(),
                        CommandLineArguments = applicationElement.XPathSelectElement("ea:LaunchInfo/ea:CmdLineArgs", nsman).AsString(),
                        MaxConcurrency       = maxConc,
                        MinConcurrency       = minConc
                    };
                    applicationConfigs.Add(config);
                }
                Logger.TraceEvent(TraceEventType.Information, "Configuration parsed successfully.");
            }
            catch (Exception ex)
            {
                Logger.TraceEvent(TraceEventType.Error, $"{ex}");
                throw ex;
            }

            CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
            var applicationServiceList = new ApplicationServiceList(applicationConfigs);
            var tasks = notificationConfigs
                        .Select(c => new NotificationService(c, applicationServiceList))
                        .SelectMany(n => new []
            {
                new Task(() => n.Execute(cancellationTokenSource.Token), TaskCreationOptions.LongRunning),
                new Task(() => n.MonitorQueueReaders(cancellationTokenSource.Token), TaskCreationOptions.LongRunning)
            })
                        .ToArray();

            if (args.Length > 0 && args[0].StartsWith("/service:", StringComparison.OrdinalIgnoreCase))
            {
                var argParts = args[0].Split(':');
                if (argParts.Length != 2)
                {
                    throw new InvalidOperationException($"Invalid argument '{args[0]}'. Expected /service:<serviceName>");
                }

                ExecuteAsWindowsService(tasks, cancellationTokenSource, argParts[1]);
            }
            else
            {
                ExecuteAsConsoleApplication(tasks, cancellationTokenSource);
            }
        }