Merge pull request #255 from meysamhadeli/fix/fix-problem-persist-message-background-job

fix: Fix problem run persist-message background job service in test-base
This commit is contained in:
Meysam Hadeli 2023-05-09 01:55:49 +03:30 committed by GitHub
commit d59c17671e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 65 additions and 44 deletions

View File

@ -373,6 +373,11 @@ dotnet_naming_rule.sanity_check_uncovered_field_case_rule.symbols = sanity_chec
dotnet_naming_rule.sanity_check_uncovered_field_case_rule.style = internal_error_style
dotnet_naming_rule.sanity_check_uncovered_field_case_rule.severity = error
##########################################
# VSThread
##########################################
dotnet_diagnostic.VSTHRD111.severity = none
##########################################
# Other Naming Rules

View File

@ -159,7 +159,6 @@
<Folder Include="Core\Pagination" />
<Folder Include="EventStoreDB\BackgroundWorkers" />
<Folder Include="PersistMessageProcessor\Data\Configurations" />
<Folder Include="PersistMessageProcessor\Data\Migrations" />
</ItemGroup>
</Project>

View File

@ -12,7 +12,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace BuildingBlocks.PersistMessageProcessor.Data.Migrations
{
[DbContext(typeof(PersistMessageDbContext))]
[Migration("20230331173133_initial")]
[Migration("20230508215131_initial")]
partial class initial
{
/// <inheritdoc />

View File

@ -10,7 +10,8 @@ using Microsoft.AspNetCore.Hosting;
public static class Extensions
{
public static IServiceCollection AddPersistMessageProcessor(this IServiceCollection services)
public static IServiceCollection AddPersistMessageProcessor(this IServiceCollection services,
IWebHostEnvironment env)
{
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
@ -21,23 +22,28 @@ public static class Extensions
var persistMessageOptions = sp.GetRequiredService<PersistMessageOptions>();
options.UseNpgsql(persistMessageOptions.ConnectionString,
dbOptions =>
{
dbOptions.MigrationsAssembly(typeof(PersistMessageDbContext).Assembly.GetName().Name);
})
dbOptions =>
{
dbOptions.MigrationsAssembly(typeof(PersistMessageDbContext).Assembly.GetName().Name);
})
// https://github.com/efcore/EFCore.NamingConventions
.UseSnakeCaseNamingConvention();;
.UseSnakeCaseNamingConvention();
});
services.AddScoped<IPersistMessageDbContext>(provider => provider.GetService<PersistMessageDbContext>());
services.AddScoped<IPersistMessageProcessor, PersistMessageProcessor>();
services.AddHostedService<PersistMessageBackgroundService>();
if (env.EnvironmentName != "test")
{
services.AddHostedService<PersistMessageBackgroundService>();
}
return services;
}
public static IApplicationBuilder UseMigrationPersistMessage<TContext>(this IApplicationBuilder app, IWebHostEnvironment env)
public static IApplicationBuilder UseMigrationPersistMessage<TContext>(this IApplicationBuilder app,
IWebHostEnvironment env)
where TContext : DbContext, IPersistMessageDbContext
{
using var scope = app.ApplicationServices.CreateScope();

View File

@ -5,7 +5,6 @@ using BuildingBlocks.EFCore;
using BuildingBlocks.Mongo;
using BuildingBlocks.PersistMessageProcessor;
using BuildingBlocks.Web;
using DotNet.Testcontainers.Containers;
using EasyNetQ.Management.Client;
using Grpc.Net.Client;
using MassTransit;
@ -49,6 +48,10 @@ public class TestFixture<TEntryPoint> : IAsyncLifetime
public RabbitMqContainer RabbitMqTestContainer;
public MongoDbContainer MongoDbTestContainer;
public EventStoreDbContainer EventStoreDbTestContainer;
public CancellationTokenSource CancellationTokenSource;
public PersistMessageBackgroundService PersistMessageBackgroundService =>
ServiceProvider.GetRequiredService<PersistMessageBackgroundService>();
public HttpClient HttpClient
{
@ -85,6 +88,12 @@ public class TestFixture<TEntryPoint> : IAsyncLifetime
TestRegistrationServices?.Invoke(services);
services.ReplaceSingleton(AddHttpContextAccessorMock);
services.AddSingleton<PersistMessageBackgroundService>();
// // remove persist-message processor background service
// var descriptor = services.Single(s => s.ImplementationType == typeof(PersistMessageBackgroundService));
// services.Remove(descriptor);
// add authentication using a fake jwt bearer - we can use SetAdminUser method to set authenticate user to existing HttContextAccessor
// https://github.com/webmotions/fake-authentication-jwtbearer
// https://github.com/webmotions/fake-authentication-jwtbearer/issues/14
@ -99,6 +108,7 @@ public class TestFixture<TEntryPoint> : IAsyncLifetime
public async Task InitializeAsync()
{
CancellationTokenSource = new CancellationTokenSource();
await StartTestContainerAsync();
}
@ -106,6 +116,7 @@ public class TestFixture<TEntryPoint> : IAsyncLifetime
{
await StopTestContainerAsync();
await _factory.DisposeAsync();
CancellationTokenSource.Cancel();
}
public virtual void RegisterServices(Action<IServiceCollection> services)
@ -141,6 +152,7 @@ public class TestFixture<TEntryPoint> : IAsyncLifetime
return result;
}
public Task<TResponse> SendAsync<TResponse>(IRequest<TResponse> request)
{
return ExecuteScopeAsync(sp =>
@ -173,7 +185,6 @@ public class TestFixture<TEntryPoint> : IAsyncLifetime
{
var published = await TestHarness.Published.Any<TMessage>(cancellationToken);
var faulty = await TestHarness.Published.Any<Fault<TMessage>>(cancellationToken);
return published && faulty == false;
});
return result;
@ -193,6 +204,30 @@ public class TestFixture<TEntryPoint> : IAsyncLifetime
return result;
}
public async Task<bool> ShouldProcessedPersistInternalCommand<TInternalCommand>(
CancellationToken cancellationToken = default)
where TInternalCommand : class, IInternalCommand
{
var result = await WaitUntilConditionMet(async () =>
{
return await ExecuteScopeAsync(async sp =>
{
var persistMessageProcessor = sp.GetService<IPersistMessageProcessor>();
Guard.Against.Null(persistMessageProcessor, nameof(persistMessageProcessor));
var filter = await persistMessageProcessor.GetByFilterAsync(x =>
x.DeliveryType == MessageDeliveryType.Internal &&
typeof(TInternalCommand).ToString() == x.DataType);
var res = filter.Any(x => x.MessageStatus == MessageStatus.Processed);
return res;
});
});
return result;
}
// Ref: https://tech.energyhelpline.com/in-memory-testing-with-masstransit/
private async Task<bool> WaitUntilConditionMet(Func<Task<bool>> conditionToMet, int? timeoutSecond = null)
{
@ -216,30 +251,6 @@ public class TestFixture<TEntryPoint> : IAsyncLifetime
return true;
}
public async Task<bool> ShouldProcessedPersistInternalCommand<TInternalCommand>()
where TInternalCommand : class, IInternalCommand
{
var result = await WaitUntilConditionMet(async () =>
{
return await ExecuteScopeAsync(async sp =>
{
var persistMessageProcessor = sp.GetService<IPersistMessageProcessor>();
Guard.Against.Null(persistMessageProcessor, nameof(persistMessageProcessor));
var filter = await persistMessageProcessor.GetByFilterAsync(x =>
x.DeliveryType == MessageDeliveryType.Internal &&
typeof(TInternalCommand).ToString() == x.DataType);
var res = filter.Any(x => x.MessageStatus == MessageStatus.Processed);
return res;
});
});
return result;
}
private async Task StartTestContainerAsync()
{
PostgresTestcontainer = TestContainers.PostgresTestContainer();
@ -496,6 +507,8 @@ public class TestFixtureCore<TEntryPoint> : IAsyncLifetime
if (!string.IsNullOrEmpty(persistOptions?.ConnectionString))
{
await Fixture.PersistMessageBackgroundService.StartAsync(Fixture.CancellationTokenSource.Token);
PersistDbConnection = new NpgsqlConnection(persistOptions.ConnectionString);
await PersistDbConnection.OpenAsync();
@ -520,6 +533,8 @@ public class TestFixtureCore<TEntryPoint> : IAsyncLifetime
if (PersistDbConnection is not null)
{
await _reSpawnerPersistDb.ResetAsync(PersistDbConnection);
await Fixture.PersistMessageBackgroundService.StopAsync(Fixture.CancellationTokenSource.Token);
}
if (DefaultDbConnection is not null)

View File

@ -57,7 +57,7 @@ public static class InfrastructureExtensions
}));
});
builder.Services.AddPersistMessageProcessor();
builder.Services.AddPersistMessageProcessor(env);
builder.Services.AddMongoDbContext<BookingReadDbContext>(configuration);
builder.AddCustomSerilog(env);

View File

@ -65,7 +65,7 @@ public static class InfrastructureExtensions
builder.Services.AddCustomDbContext<FlightDbContext>();
builder.Services.AddScoped<IDataSeeder, FlightDataSeeder>();
builder.Services.AddMongoDbContext<FlightReadDbContext>(configuration);
builder.Services.AddPersistMessageProcessor();
builder.Services.AddPersistMessageProcessor(env);
builder.AddCustomSerilog(env);
builder.Services.AddJwt();

View File

@ -9,8 +9,6 @@ using Xunit;
namespace Integration.Test.Aircraft.Features;
using global::Flight.Aircrafts.Features.CreatingAircraft.V1;
public class CreateAircraftTests : FlightIntegrationTestBase
{
public CreateAircraftTests(

View File

@ -9,8 +9,6 @@ using Xunit;
namespace Integration.Test.Airport.Features;
using global::Flight.Airports.Features.CreatingAirport.V1;
public class CreateAirportTests : FlightIntegrationTestBase
{
public CreateAirportTests(

View File

@ -59,7 +59,7 @@ public static class InfrastructureExtensions
});
builder.Services.AddControllers();
builder.Services.AddPersistMessageProcessor();
builder.Services.AddPersistMessageProcessor(env);
builder.Services.AddCustomDbContext<IdentityContext>();
builder.Services.AddScoped<IDataSeeder, IdentityDataSeeder>();
builder.AddCustomSerilog(env);

View File

@ -58,7 +58,7 @@ public static class InfrastructureExtensions
}));
});
builder.Services.AddPersistMessageProcessor();
builder.Services.AddPersistMessageProcessor(env);
builder.Services.AddCustomDbContext<PassengerDbContext>();
builder.Services.AddMongoDbContext<PassengerReadDbContext>(configuration);