Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,20 @@ public static ModelBuilder AddPostgresEnums(this ModelBuilder modelBuilder)
/// This method is typically called when setting up the DbContextFactory in the
/// AddPostgresEffect extension method.
/// </remarks>
public static NpgsqlDataSource BuildDataSource(string connectionString)
public static NpgsqlDataSource BuildDataSource(string connectionString) =>
BuildDataSource(connectionString, configure: null);

/// <summary>
/// Builds a PostgreSQL data source with enum mappings and optional custom configuration.
/// </summary>
/// <param name="connectionString">The connection string to use</param>
/// <param name="configure">Optional action to configure the data source builder after enum mappings
/// (e.g., set <c>ConnectionStringBuilder.MaxPoolSize</c> or enable multiplexing)</param>
/// <returns>A configured NpgsqlDataSource</returns>
public static NpgsqlDataSource BuildDataSource(
string connectionString,
Action<NpgsqlDataSourceBuilder>? configure
)
{
var npgsqlDataSourceBuilder = new NpgsqlDataSourceBuilder(connectionString);

Expand All @@ -78,6 +91,8 @@ public static NpgsqlDataSource BuildDataSource(string connectionString)
npgsqlDataSourceBuilder.MapEnum<WorkQueueStatus>("trax.work_queue_status");
npgsqlDataSourceBuilder.MapEnum<MisfirePolicy>("trax.misfire_policy");

configure?.Invoke(npgsqlDataSourceBuilder);

return npgsqlDataSourceBuilder.Build();
}

Expand Down
24 changes: 23 additions & 1 deletion src/Trax.Effect.Data.Postgres/Extensions/ServiceExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,36 @@ public static TraxEffectBuilder SkipMigrations(this TraxEffectBuilder builder)
public static TraxEffectBuilderWithData UsePostgres(
this TraxEffectBuilder configurationBuilder,
string connectionString
) => configurationBuilder.UsePostgres(connectionString, configureDataSource: null);

/// <summary>
/// Adds PostgreSQL database support to the Trax.Effect system with custom data source configuration.
/// </summary>
/// <param name="configurationBuilder">The Trax.Core effect configuration builder</param>
/// <param name="connectionString">The connection string to the PostgreSQL database</param>
/// <param name="configureDataSource">Optional action to configure the <see cref="NpgsqlDataSourceBuilder"/>
/// after enum mappings. Use this to tune connection pool settings, enable multiplexing, or add custom type mappings.
/// <code>
/// effects.UsePostgres(connectionString, dataSource =>
/// dataSource.ConnectionStringBuilder.MaxPoolSize = 50);
/// </code>
/// </param>
/// <returns>The configuration builder for method chaining</returns>
public static TraxEffectBuilderWithData UsePostgres(
this TraxEffectBuilder configurationBuilder,
string connectionString,
Action<NpgsqlDataSourceBuilder>? configureDataSource
)
{
// Migrate the database schema to the latest version (unless explicitly skipped)
if (!configurationBuilder.MigrationsDisabled)
DatabaseMigrator.Migrate(connectionString).Wait();

// Create a data source with enum mappings and register for disposal on shutdown
var dataSource = ModelBuilderExtensions.BuildDataSource(connectionString);
var dataSource = ModelBuilderExtensions.BuildDataSource(
connectionString,
configureDataSource
);
configurationBuilder.ServiceCollection.AddSingleton(dataSource);

// Register the DbContextFactory
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,66 @@ public void UsePostgres_WithSkipMigrations_StillRegistersDataContext()
}

#endregion

#region UsePostgres with ConfigureDataSource

[Test]
public void UsePostgres_WithConfigureAction_DoesNotThrow()
{
var act = () =>
new ServiceCollection().AddTrax(trax =>
trax.AddEffects(effects =>
effects
.SkipMigrations()
.UsePostgres(
UnreachableConnectionString,
dataSource => dataSource.ConnectionStringBuilder.MaxPoolSize = 50
)
)
);

act.Should().NotThrow();
}

[Test]
public void UsePostgres_WithConfigureAction_StillRegistersDbContextFactory()
{
var services = new ServiceCollection();

services.AddTrax(trax =>
trax.AddEffects(effects =>
effects
.SkipMigrations()
.UsePostgres(
UnreachableConnectionString,
dataSource => dataSource.ConnectionStringBuilder.MaxPoolSize = 50
)
)
);

services
.Should()
.Contain(sd =>
sd.ServiceType.IsGenericType
&& sd.ServiceType.GetGenericTypeDefinition()
== typeof(Microsoft.EntityFrameworkCore.IDbContextFactory<>)
);
}

[Test]
public void UsePostgres_WithNullConfigureAction_BehavesLikeDefault()
{
var act = () =>
new ServiceCollection().AddTrax(trax =>
trax.AddEffects(effects =>
effects
.SkipMigrations()
.UsePostgres(UnreachableConnectionString, configureDataSource: null)
)
);

act.Should().NotThrow();
}

#endregion
}
Loading