78 lines
2.8 KiB
C#
78 lines
2.8 KiB
C#
|
|
using Books.Api.EventFlow.Extensions;
|
||
|
|
using Books.Api.EventFlow.Infrastructure;
|
||
|
|
using Books.Api.GraphQL;
|
||
|
|
using Books.Api.Infrastructure;
|
||
|
|
using Books.Api.Logging;
|
||
|
|
using EventFlow;
|
||
|
|
using EventFlow.Configuration;
|
||
|
|
using EventFlow.Extensions;
|
||
|
|
using EventFlow.Hangfire.Extensions;
|
||
|
|
using EventFlow.PostgreSql.Connections;
|
||
|
|
using EventFlow.PostgreSql.Extensions;
|
||
|
|
using EventFlow.ReadStores;
|
||
|
|
using EventFlow.Subscribers;
|
||
|
|
using GraphQL;
|
||
|
|
using Hangfire;
|
||
|
|
using Hangfire.PostgreSql;
|
||
|
|
using Npgsql;
|
||
|
|
|
||
|
|
namespace Books.Api;
|
||
|
|
|
||
|
|
public static class Startup
|
||
|
|
{
|
||
|
|
public static void ConfigureServices(IServiceCollection services, IConfiguration config, IHostEnvironment? environment = null)
|
||
|
|
{
|
||
|
|
var connectionString = config.GetConnectionString("Default")
|
||
|
|
?? throw new InvalidOperationException("Connection string 'Default' not found");
|
||
|
|
|
||
|
|
// Run database migrations (skipped in Test environment where migrations run separately with test connection string)
|
||
|
|
var isTestEnvironment = environment?.EnvironmentName == "Test";
|
||
|
|
if (!isTestEnvironment)
|
||
|
|
{
|
||
|
|
DatabaseMigrator.Migrate(connectionString);
|
||
|
|
}
|
||
|
|
|
||
|
|
// PostgreSQL data source
|
||
|
|
var dataSource = new NpgsqlDataSourceBuilder(connectionString).Build();
|
||
|
|
services.AddSingleton(dataSource);
|
||
|
|
|
||
|
|
// Hangfire
|
||
|
|
services.AddHangfire(c => c
|
||
|
|
.SetDataCompatibilityLevel(CompatibilityLevel.Version_180)
|
||
|
|
.UseSimpleAssemblyNameTypeSerializer()
|
||
|
|
.UseRecommendedSerializerSettings()
|
||
|
|
.UsePostgreSqlStorage(o => o.UseNpgsqlConnection(connectionString)));
|
||
|
|
services.AddHangfireServer();
|
||
|
|
|
||
|
|
// Scheduler abstraction over Hangfire
|
||
|
|
services.AddSingleton<IScheduler, HangfireScheduler>();
|
||
|
|
|
||
|
|
// EventFlow
|
||
|
|
services.AddEventFlow(o => o
|
||
|
|
.UsePostgreSqlEventStore()
|
||
|
|
.ConfigurePostgreSql(PostgreSqlConfiguration.New.SetConnectionString(connectionString))
|
||
|
|
.AddDefaults(typeof(Startup).Assembly)
|
||
|
|
.AddReadModels()
|
||
|
|
.Configure(c => c.IsAsynchronousSubscribersEnabled = true)
|
||
|
|
.UseHangfireJobScheduler());
|
||
|
|
|
||
|
|
// Resilience strategies
|
||
|
|
services.AddSingleton<IDispatchToReadStoresResilienceStrategy, ReadStoresResilienceStrategy>();
|
||
|
|
services.AddSingleton<IDispatchToSubscriberResilienceStrategy, DispatchToSubscriberResilienceStrategy>();
|
||
|
|
|
||
|
|
// Read model repositories
|
||
|
|
services.AddRepositories();
|
||
|
|
|
||
|
|
// Logging decorators
|
||
|
|
services.DecorateAsyncEventHandlersWithLogging();
|
||
|
|
|
||
|
|
// GraphQL
|
||
|
|
services.AddGraphQL(builder => builder
|
||
|
|
.AddSchema<BooksSchema>()
|
||
|
|
.AddSystemTextJson()
|
||
|
|
.AddDataLoader()
|
||
|
|
.AddGraphTypes(typeof(BooksSchema).Assembly)
|
||
|
|
.AddErrorInfoProvider(opt => opt.ExposeExceptionDetails = true));
|
||
|
|
}
|
||
|
|
}
|