using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using NLog.Extensions.Logging; using Selector.Cache.Extensions; using Selector.CLI.Extensions; using Selector.Events; using Selector.Extensions; using System; using System.CommandLine; using System.CommandLine.Invocation; namespace Selector.CLI { public class HostRootCommand: RootCommand { public HostRootCommand() { Handler = CommandHandler.Create(() => HostCommand.Execute()); } } public class HostCommand : Command { public HostCommand(string name, string description = null) : base(name, description) { Handler = CommandHandler.Create(() => Execute()); } public static int Execute() { try { var host = CreateHostBuilder(Environment.GetCommandLineArgs(),ConfigureDefault, ConfigureDefaultNlog) .Build(); var logger = host.Services.GetRequiredService>(); var env = host.Services.GetRequiredService(); SetupExceptionHandling(logger, env); host.Run(); } catch(Exception ex) { Console.WriteLine(ex); return 1; } return 0; } private static void SetupExceptionHandling(ILogger logger, IHostEnvironment env) { AppDomain.CurrentDomain.UnhandledException += (_, e) => { if(e.ExceptionObject is Exception ex) { logger.LogError(ex, "Unhandled exception thrown"); if (env.IsDevelopment()) { throw ex; } } }; } public static RootOptions ConfigureOptions(HostBuilderContext context, IServiceCollection services) { services.Configure(options => { OptionsHelper.ConfigureOptions(options, context.Configuration); }); var config = OptionsHelper.ConfigureOptions(context.Configuration); services.Configure(options => { options.ClientId = config.ClientId; options.ClientSecret = config.ClientSecret; }); return config; } public static void ConfigureDefault(HostBuilderContext context, IServiceCollection services) { Console.WriteLine("~~~ Selector CLI ~~~"); Console.WriteLine(); Console.WriteLine("> Configuring..."); // CONFIG var config = ConfigureOptions(context, services); context.Configuration.ConfigureOptionsInjection(services); Console.WriteLine("> Adding Services..."); // SERVICES services.AddHttpClient() .ConfigureDb(config); services.AddConsumerFactories(); services.AddCLIConsumerFactories(); if (config.RedisOptions.Enabled) { Console.WriteLine("> Adding caching consumers..."); services.AddCachingConsumerFactories(); } services.AddWatcher() .AddEvents() .AddSpotify(); services.ConfigureLastFm(config) .ConfigureEqual(config) .ConfigureJobs(config); if (config.RedisOptions.Enabled) { Console.WriteLine("> Adding Redis..."); services.AddRedisServices(config.RedisOptions.ConnectionString); Console.WriteLine("> Adding cache event maps..."); services.AddTransient() .AddTransient(); Console.WriteLine("> Adding caching Spotify consumers..."); services.AddCachingSpotify(); } // HOSTED SERVICES if (config.WatcherOptions.Enabled) { if (config.WatcherOptions.LocalEnabled) { Console.WriteLine("> Adding Local Watcher Service"); services.AddHostedService(); } if (config.DatabaseOptions.Enabled) { Console.WriteLine("> Adding Db Watcher Service"); services.AddHostedService(); } } } public static void ConfigureDefaultNlog(HostBuilderContext context, ILoggingBuilder builder) { builder.ClearProviders() .SetMinimumLevel(LogLevel.Trace) .AddNLog(context.Configuration); } static IHostBuilder CreateHostBuilder(string[] args, Action buildServices, Action buildLogs) => Host.CreateDefaultBuilder(args) .UseSystemd() .ConfigureServices((context, services) => buildServices(context, services)) .ConfigureLogging((context, builder) => buildLogs(context, builder)); } }