Example #1
0
        public ConsoleHost(string[] args)
        {
            Log.Logger = new LoggerConfiguration()
                         .MinimumLevel.Debug()
                         .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
                         .MinimumLevel.Override("System", LogEventLevel.Warning)
                         .MinimumLevel.Override("CoinbasePro", LogEventLevel.Information)
                         .MinimumLevel.Override("Microsoft.Azure.KeyVault", LogEventLevel.Verbose)
                         .MinimumLevel.Override("CoinbasePro.Application.RabbitMq", LogEventLevel.Verbose)
                         .Enrich.FromLogContext()
                         .WriteTo.Console()
                         .CreateLogger();

            var builder = new HostBuilder().UseConsoleLifetime();

            builder.ConfigureHostConfiguration(config => {
                config.AddEnvironmentVariables(); // pulls environment name from Properties/launchSettings.json
            });

            builder.ConfigureLogging((hostingContext, config) => {
                config.AddSerilog();
            });

            builder.ConfigureAppConfiguration((hostContext, configurationBuilder) =>
            {
                var env = hostContext.HostingEnvironment;
                configurationBuilder.SetBasePath(env.ContentRootPath);

                // These files are copied to bin in the build, so needs rebuild to push changes into app
                configurationBuilder.AddJsonFile("appsettings.json", optional: false, true);
                configurationBuilder.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
                configurationBuilder.AddEnvironmentVariables();

                if (args != null)
                {
                    configurationBuilder.AddCommandLine(args);
                }

                var builtConfig = configurationBuilder.Build();

                Register.AddAzureKeyVault(builtConfig, configurationBuilder);
            });

            builder.ConfigureServices((hostContext, services) =>
            {
                // --------------------------------------------
                // Coinbase Pro log-on credentials, usually these should be saved in the Azure Key vault so they're never exposed
                // without Azure, comment out the azureServiceTokenProvider part above and use the app config file directly
                services.AddSingleton <IAuthenticator>(new Authenticator(hostContext.Configuration["apiKey"]
                                                                         , hostContext.Configuration["apiSecret"]
                                                                         , hostContext.Configuration["passPhrase"]));

                // Customise the HttpClient to ensure we don't ever get HTTP 429 rate limit errors
                services.AddSingleton <IHttpClient>(new RateLimitedHttpClient(3, 2.1));
                services.AddSingleton <ICoinbaseProClient, CoinbaseProClient>();

                // --------------------------------------------
                // The IStartupWorkflow controls the startup order of services in order
                // the ensure inter dependencies receive events or data correctly
                // As all the services are not yet in Github ensure CandleMonitor can still start
                // so use StartupWorkflow.ForCandleMonitorOnly()
                services.AddSingleton(sp => StartupWorkflow.ForCandleMonitorOnly());

                // Usually SQL Server would be used (sql scripts not in Github yet)
                //services.AddSingleton<ICandleProvider, SqlServerCandleProvider>();
                //services.AddTransient<ICandleMonitorFeedProvider, SqlServerCandleMonitorFeed>();

                // Instead use the CSV route for ease of demonstration
                services.AddSingleton <ICandleProvider, CsvCandleProvider>();
                // Setup the markets to pull data for
                services.AddTransient <ICandleMonitorFeedProvider>(sp => new CsvCandleMonitorFeed(new List <CandleMonitorFeeds>()
                {
                    new CandleMonitorFeeds(ProductType.BtcUsd, CandleGranularity.Hour1),
                    new CandleMonitorFeeds(ProductType.EthUsd, CandleGranularity.Hour1),
                    new CandleMonitorFeeds(ProductType.EthEur, CandleGranularity.Minutes15),
                    new CandleMonitorFeeds(ProductType.DaiUsdc, CandleGranularity.Hour1)
                })
                                                                   );

                // Use the event driven candle production / consumption
                services.AddSingleton <CandleProducerConsumer>();
                services.AddSingleton <ICandleProducer>(x => x.GetRequiredService <CandleProducerConsumer>());
                services.AddSingleton <ICandleConsumer>(x => x.GetRequiredService <CandleProducerConsumer>());

                // Add the hosted services
                services.AddSingleton <ICandleMonitor, CandleMonitor>();
                services.AddHostedService <HostedService <ICandleMonitor> >();

                //// Finish up and add database
                //    services.AddDbContext<CryptoDbX>(options =>
                //    {
                //        options.UseSqlServer(hostContext.Configuration.GetConnectionString("MyDbConnection"),
                //            // retry https://blogs.msdn.microsoft.com/cesardelatorre/2017/03/26/using-resilient-entity-framework-core-sql-connections-and-transactions-retries-with-exponential-backoff/
                //            sqlServerOptionsAction: sqlOptions =>
                //            {
                //                sqlOptions.EnableRetryOnFailure(
                //                    maxRetryCount: 5,
                //                    maxRetryDelay: TimeSpan.FromSeconds(30),
                //                    errorNumbersToAdd: null);
                //            });
                //        options.EnableSensitiveDataLogging(Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") != "Production");
                //    });

                services.Configure <AppSetting>(hostContext.Configuration);

                // All calls to services.Configure *MUST* have come before this
                ServiceProvider = services.BuildServiceProvider();
            });

            _host = builder.Build();

            //// Automatically perform database migration
            //serviceProvider.GetService<CryptoXContext>().Database.Migrate();
        }