public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .UseServiceProviderFactory(new AutofacServiceProviderFactory()) .ConfigureWebHostDefaults(whb => whb .UseConfiguration(InitUtils.BuildConfiguration(args).Build()) .ConfigureKestrel(opts => { opts.ListenAnyIP(5000); }) .UseStartup <Startup>());
public ServiceProvider BuildServiceProvider() => new ServiceCollection() .AddTransient(_ => _config.GetSection("PluralKit").Get <CoreConfig>() ?? new CoreConfig()) .AddTransient(_ => _config.GetSection("PluralKit").GetSection("Bot").Get <BotConfig>() ?? new BotConfig()) .AddSingleton <DbConnectionCountHolder>() .AddTransient <DbConnectionFactory>() .AddSingleton <IDiscordClient, DiscordShardedClient>(_ => new DiscordShardedClient(new DiscordSocketConfig { MessageCacheSize = 5, ExclusiveBulkDelete = true })) .AddSingleton <Bot>() .AddSingleton(_ => new CommandService(new CommandServiceConfig { CaseSensitiveCommands = false, QuotationMarkAliasMap = new Dictionary <char, char> { { '"', '"' }, { '\'', '\'' }, { '‘', '’' }, { '“', '”' }, { '„', '‟' }, }, // We're already asyncing stuff by forking off at the client event handlers // So adding an additional layer of forking is pointless // and leads to the service scope being disposed of prematurely DefaultRunMode = RunMode.Sync })) .AddTransient <EmbedService>() .AddTransient <ProxyService>() .AddTransient <LogChannelService>() .AddTransient <DataFileService>() .AddTransient <WebhookExecutorService>() .AddTransient <ProxyCacheService>() .AddSingleton <WebhookCacheService>() .AddTransient <SystemStore>() .AddTransient <MemberStore>() .AddTransient <MessageStore>() .AddTransient <SwitchStore>() .AddSingleton(svc => InitUtils.InitMetrics(svc.GetRequiredService <CoreConfig>())) .AddSingleton <PeriodicStatCollector>() .AddScoped(_ => new Sentry.Scope(null)) .AddTransient <PKEventHandler>() .AddScoped <EventIdProvider>() .AddSingleton(svc => new LoggerProvider(svc.GetRequiredService <CoreConfig>(), "bot")) .AddScoped(svc => svc.GetRequiredService <LoggerProvider>().RootLogger.ForContext("EventId", svc.GetRequiredService <EventIdProvider>().EventId)) .AddMemoryCache() .BuildServiceProvider();
public void ConfigureContainer(ContainerBuilder builder) { builder.RegisterInstance(InitUtils.BuildConfiguration(Environment.GetCommandLineArgs()).Build()) .As <IConfiguration>(); builder.RegisterModule(new ConfigModule <ApiConfig>("API")); builder.RegisterModule(new LoggingModule("api")); builder.RegisterModule(new MetricsModule("API")); builder.RegisterModule <DataStoreModule>(); builder.RegisterModule <APIModule>(); }
public static async Task Main(string[] args) { InitUtils.InitStatic(); await BuildInfoService.LoadVersion(); var host = CreateHostBuilder(args).Build(); var config = host.Services.GetRequiredService <CoreConfig>(); await host.Services.GetRequiredService <RedisService>().InitAsync(config); await host.RunAsync(); }
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .UseServiceProviderFactory(new AutofacServiceProviderFactory()) .UseSerilog() .ConfigureWebHostDefaults(whb => whb .UseConfiguration(InitUtils.BuildConfiguration(args).Build()) .ConfigureKestrel(opts => { opts.ListenAnyIP(opts.ApplicationServices.GetRequiredService <ApiConfig>().Port); }) .UseStartup <Startup>());
public void ConfigureContainer(ContainerBuilder builder) { builder.RegisterInstance(InitUtils.BuildConfiguration(Environment.GetCommandLineArgs()).Build()) .As <IConfiguration>(); builder.RegisterModule(new ConfigModule <ApiConfig>("API")); builder.RegisterModule(new LoggingModule("api", cfg: new LoggerConfiguration().Filter.ByExcluding(exc => exc.Exception is PKError || exc.Exception.IsUserError()))); builder.RegisterModule(new MetricsModule("API")); builder.RegisterModule <DataStoreModule>(); builder.RegisterModule <APIModule>(); }
public ServiceProvider BuildServiceProvider() => new ServiceCollection() .AddTransient(_ => _config.GetSection("PluralKit").Get <CoreConfig>() ?? new CoreConfig()) .AddTransient(_ => _config.GetSection("PluralKit").GetSection("Bot").Get <BotConfig>() ?? new BotConfig()) .AddSingleton <DbConnectionCountHolder>() .AddTransient <DbConnectionFactory>() .AddSingleton <IDiscordClient, DiscordShardedClient>(_ => new DiscordShardedClient(new DiscordSocketConfig { MessageCacheSize = 5, ExclusiveBulkDelete = true, DefaultRetryMode = RetryMode.AlwaysRetry, // Commented this out since Debug actually sends, uh, quite a lot that's not necessary in production // but leaving it here in case I (or someone else) get[s] confused about why logging isn't working again :p // LogLevel = LogSeverity.Debug // We filter log levels in Serilog, so just pass everything through (Debug is lower than Verbose) })) .AddSingleton <Bot>() .AddTransient <CommandTree>() .AddTransient <SystemCommands>() .AddTransient <MemberCommands>() .AddTransient <SwitchCommands>() .AddTransient <LinkCommands>() .AddTransient <APICommands>() .AddTransient <ImportExportCommands>() .AddTransient <HelpCommands>() .AddTransient <ModCommands>() .AddTransient <MiscCommands>() .AddTransient <EmbedService>() .AddTransient <ProxyService>() .AddTransient <LogChannelService>() .AddTransient <DataFileService>() .AddTransient <WebhookExecutorService>() .AddTransient <ProxyCacheService>() .AddSingleton <WebhookCacheService>() .AddTransient <IDataStore, PostgresDataStore>() .AddSingleton(svc => InitUtils.InitMetrics(svc.GetRequiredService <CoreConfig>())) .AddSingleton <PeriodicStatCollector>() .AddScoped(_ => new Sentry.Scope(null)) .AddTransient <PKEventHandler>() .AddScoped <EventIdProvider>() .AddSingleton(svc => new LoggerProvider(svc.GetRequiredService <CoreConfig>(), "bot")) .AddScoped(svc => svc.GetRequiredService <LoggerProvider>().RootLogger.ForContext("EventId", svc.GetRequiredService <EventIdProvider>().EventId)) .AddMemoryCache() .BuildServiceProvider();
public ServiceProvider BuildServiceProvider() => new ServiceCollection() .AddTransient(_ => _config.GetSection("PluralKit").Get <CoreConfig>() ?? new CoreConfig()) .AddTransient(_ => _config.GetSection("PluralKit").GetSection("Bot").Get <BotConfig>() ?? new BotConfig()) .AddSingleton <DbConnectionCountHolder>() .AddTransient <DbConnectionFactory>() .AddSingleton <IDiscordClient, DiscordShardedClient>(_ => new DiscordShardedClient(new DiscordSocketConfig { MessageCacheSize = 5, ExclusiveBulkDelete = true, DefaultRetryMode = RetryMode.AlwaysRetry })) .AddSingleton <Bot>() .AddTransient <CommandTree>() .AddTransient <SystemCommands>() .AddTransient <MemberCommands>() .AddTransient <SwitchCommands>() .AddTransient <LinkCommands>() .AddTransient <APICommands>() .AddTransient <ImportExportCommands>() .AddTransient <HelpCommands>() .AddTransient <ModCommands>() .AddTransient <MiscCommands>() .AddTransient <EmbedService>() .AddTransient <ProxyService>() .AddTransient <LogChannelService>() .AddTransient <DataFileService>() .AddTransient <WebhookExecutorService>() .AddTransient <ProxyCacheService>() .AddSingleton <WebhookCacheService>() .AddTransient <SystemStore>() .AddTransient <MemberStore>() .AddTransient <MessageStore>() .AddTransient <SwitchStore>() .AddSingleton(svc => InitUtils.InitMetrics(svc.GetRequiredService <CoreConfig>())) .AddSingleton <PeriodicStatCollector>() .AddScoped(_ => new Sentry.Scope(null)) .AddTransient <PKEventHandler>() .AddScoped <EventIdProvider>() .AddSingleton(svc => new LoggerProvider(svc.GetRequiredService <CoreConfig>(), "bot")) .AddScoped(svc => svc.GetRequiredService <LoggerProvider>().RootLogger.ForContext("EventId", svc.GetRequiredService <EventIdProvider>().EventId)) .AddMemoryCache() .BuildServiceProvider();
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { InitUtils.Init(); var config = Configuration.GetSection("PluralKit").Get <CoreConfig>(); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); services .AddScoped <IDbConnection, NpgsqlConnection>(_ => new NpgsqlConnection(config.Database)) .AddTransient <SystemStore>() .AddTransient <MemberStore>() .AddSingleton(config); }
private async Task MainAsync() { ThreadPool.SetMinThreads(32, 32); ThreadPool.SetMaxThreads(128, 128); Console.WriteLine("Starting PluralKit..."); InitUtils.Init(); // Set up a CancellationToken and a SIGINT hook to properly dispose of things when the app is closed // The Task.Delay line will throw/exit (forgot which) and the stack and using statements will properly unwind var token = new CancellationTokenSource(); Console.CancelKeyPress += delegate(object e, ConsoleCancelEventArgs args) { args.Cancel = true; token.Cancel(); }; using (var services = BuildServiceProvider()) { var logger = services.GetRequiredService <ILogger>().ForContext <Initialize>(); var coreConfig = services.GetRequiredService <CoreConfig>(); var botConfig = services.GetRequiredService <BotConfig>(); var schema = services.GetRequiredService <SchemaService>(); using (Sentry.SentrySdk.Init(coreConfig.SentryUrl)) { logger.Information("Connecting to database"); await schema.ApplyMigrations(); logger.Information("Connecting to Discord"); var client = services.GetRequiredService <IDiscordClient>() as DiscordShardedClient; await client.LoginAsync(TokenType.Bot, botConfig.Token); logger.Information("Initializing bot"); await services.GetRequiredService <Bot>().Init(); await client.StartAsync(); try { await Task.Delay(-1, token.Token); } catch (TaskCanceledException) { } // We'll just exit normally logger.Information("Shutting down"); } } }
static Task Main(string[] args) { // Load configuration and run global init stuff var config = InitUtils.BuildConfiguration(args).Build(); InitUtils.InitStatic(); // Set up DI container and modules var services = BuildContainer(config); return(RunWrapper(services, async ct => { var logger = services.Resolve <ILogger>().ForContext <Init>(); // Initialize Sentry SDK, and make sure it gets dropped at the end using var _ = Sentry.SentrySdk.Init(services.Resolve <CoreConfig>().SentryUrl); // "Connect to the database" (ie. set off database migrations and ensure state) logger.Information("Connecting to database"); await services.Resolve <IDatabase>().ApplyMigrations(); // Init the bot instance itself, register handlers and such to the client before beginning to connect logger.Information("Initializing bot"); var bot = services.Resolve <Bot>(); bot.Init(); // Install observer for request/responses DiscordRequestObserver.Install(services); // Start the Discord shards themselves (handlers already set up) logger.Information("Connecting to Discord"); var info = await services.Resolve <DiscordApiClient>().GetGatewayBot(); await services.Resolve <Cluster>().Start(info); logger.Information("Connected! All is good (probably)."); // Lastly, we just... wait. Everything else is handled in the DiscordClient event loop try { await Task.Delay(-1, ct); } catch (TaskCanceledException) { // Once the CancellationToken fires, we need to shut stuff down // (generally happens given a SIGINT/SIGKILL/Ctrl-C, see calling wrapper) await bot.Shutdown(); } })); }
public static async Task Main(string[] args) { _metrics = AppMetrics.CreateDefaultBuilder() .OutputMetrics.AsPrometheusPlainText() .OutputMetrics.AsPrometheusProtobuf() .Build(); InitUtils.InitStatic(); await BuildInfoService.LoadVersion(); var host = CreateHostBuilder(args).Build(); var config = host.Services.GetRequiredService <CoreConfig>(); await host.Services.GetRequiredService <RedisService>().InitAsync(config); await host.RunAsync(); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddCors(); services.AddMvc(opts => { }) .SetCompatibilityVersion(CompatibilityVersion.Version_2_2) .AddJsonOptions(opts => { opts.SerializerSettings.BuildSerializerSettings(); }); services .AddTransient <IDataStore, PostgresDataStore>() .AddSingleton(svc => InitUtils.InitMetrics(svc.GetRequiredService <CoreConfig>(), "API")) .AddScoped <TokenAuthService>() .AddTransient(_ => Configuration.GetSection("PluralKit").Get <CoreConfig>() ?? new CoreConfig()) .AddSingleton(svc => InitUtils.InitLogger(svc.GetRequiredService <CoreConfig>(), "api")) .AddTransient <DbConnectionCountHolder>() .AddTransient <DbConnectionFactory>(); }
private static async Task Main(string[] args) { // Load configuration and run global init stuff var config = InitUtils.BuildConfiguration(args).Build(); InitUtils.InitStatic(); await BuildInfoService.LoadVersion(); var services = BuildContainer(config); var cfg = services.Resolve <CoreConfig>(); if (cfg.UseRedisMetrics) { await services.Resolve <RedisService>().InitAsync(cfg); } services.Resolve <TaskHandler>().Run(); await Task.Delay(-1); }
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureMetrics(_metrics) .UseMetricsWebTracking() .UseMetricsEndpoints() .UseMetrics( options => { options.EndpointOptions = endpointsOptions => { endpointsOptions.MetricsTextEndpointOutputFormatter = _metrics.OutputMetricsFormatters.OfType <MetricsPrometheusTextOutputFormatter>().First(); endpointsOptions.MetricsEndpointOutputFormatter = _metrics.OutputMetricsFormatters.OfType <MetricsPrometheusProtobufOutputFormatter>().First(); }; }) .UseServiceProviderFactory(new AutofacServiceProviderFactory()) .UseSerilog() .ConfigureWebHostDefaults(whb => whb .UseConfiguration(InitUtils.BuildConfiguration(args).Build()) .ConfigureKestrel(opts => { opts.ListenAnyIP(opts.ApplicationServices.GetRequiredService <ApiConfig>().Port); }) .UseStartup <Startup>());
private static async Task Main(string[] args) { // Load configuration and run global init stuff var config = InitUtils.BuildConfiguration(args).Build(); InitUtils.InitStatic(); // init version service await BuildInfoService.LoadVersion(); // Set up DI container and modules var services = BuildContainer(config); await RunWrapper(services, async ct => { var logger = services.Resolve <ILogger>().ForContext <Init>(); // Initialize Sentry SDK, and make sure it gets dropped at the end using var _ = SentrySdk.Init(opts => { opts.Dsn = services.Resolve <CoreConfig>().SentryUrl; opts.Release = BuildInfoService.FullVersion; opts.AutoSessionTracking = true; opts.DisableTaskUnobservedTaskExceptionCapture(); }); var config = services.Resolve <BotConfig>(); var coreConfig = services.Resolve <CoreConfig>(); // initialize Redis var redis = services.Resolve <RedisService>(); if (config.UseRedisRatelimiter) { await redis.InitAsync(coreConfig); } if (config.Cluster == null) { // "Connect to the database" (ie. set off database migrations and ensure state) logger.Information("Connecting to database"); await services.Resolve <IDatabase>().ApplyMigrations(); // Clear shard status from Redis if (redis.Connection != null) { await redis.Connection.GetDatabase().KeyDeleteAsync("pluralkit:shardstatus"); } } // Init the bot instance itself, register handlers and such to the client before beginning to connect logger.Information("Initializing bot"); var bot = services.Resolve <Bot>(); bot.Init(); // Start the Discord shards themselves (handlers already set up) logger.Information("Connecting to Discord"); await StartCluster(services); logger.Information("Connected! All is good (probably)."); // Lastly, we just... wait. Everything else is handled in the DiscordClient event loop try { await Task.Delay(-1, ct); } catch (TaskCanceledException) { // Once the CancellationToken fires, we need to shut stuff down // (generally happens given a SIGINT/SIGKILL/Ctrl-C, see calling wrapper) await bot.Shutdown(); } }); }
private async Task MainAsync() { ThreadPool.SetMinThreads(32, 32); ThreadPool.SetMaxThreads(128, 128); Console.WriteLine("Starting PluralKit..."); InitUtils.Init(); // Set up a CancellationToken and a SIGINT hook to properly dispose of things when the app is closed // The Task.Delay line will throw/exit (forgot which) and the stack and using statements will properly unwind var token = new CancellationTokenSource(); Console.CancelKeyPress += delegate(object e, ConsoleCancelEventArgs args) { args.Cancel = true; token.Cancel(); }; var builder = new ContainerBuilder(); builder.RegisterInstance(_config); builder.RegisterModule(new ConfigModule <BotConfig>("Bot")); builder.RegisterModule(new LoggingModule("bot")); builder.RegisterModule(new MetricsModule()); builder.RegisterModule <DataStoreModule>(); builder.RegisterModule <BotModule>(); using var services = builder.Build(); var logger = services.Resolve <ILogger>().ForContext <Initialize>(); try { SchemaService.Initialize(); var coreConfig = services.Resolve <CoreConfig>(); var botConfig = services.Resolve <BotConfig>(); var schema = services.Resolve <SchemaService>(); using var _ = Sentry.SentrySdk.Init(coreConfig.SentryUrl); logger.Information("Connecting to database"); await schema.ApplyMigrations(); logger.Information("Connecting to Discord"); var client = services.Resolve <DiscordShardedClient>(); await client.LoginAsync(TokenType.Bot, botConfig.Token); logger.Information("Initializing bot"); await client.StartAsync(); await services.Resolve <Bot>().Init(); try { await Task.Delay(-1, token.Token); } catch (TaskCanceledException) { } // We'll just exit normally } catch (Exception e) { logger.Fatal(e, "Unrecoverable error while initializing bot"); } logger.Information("Shutting down"); }
static void Main(string[] args) => new Initialize { _config = InitUtils.BuildConfiguration(args).Build() } .MainAsync().GetAwaiter().GetResult();
public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseConfiguration(InitUtils.BuildConfiguration(args).Build()) .ConfigureKestrel(opts => { opts.ListenAnyIP(5000); }) .UseStartup <Startup>();
public static void Main(string[] args) { InitUtils.Init(); CreateHostBuilder(args).Build().Run(); }