Skip to content
Open
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
2 changes: 1 addition & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Alba" Version="8.4.0" />
<PackageVersion Include="Alba" Version="8.4.1" />
<PackageVersion Include="AWSSDK.SimpleNotificationService" Version="4.0.2.14" />
<PackageVersion Include="AWSSDK.SQS" Version="4.0.2.14" />
<PackageVersion Include="Azure.Identity" Version="1.17.0" />
Expand Down
119 changes: 73 additions & 46 deletions src/Http/Wolverine.Http.Tests/Bugs/Bug_using_host_stop.cs
Original file line number Diff line number Diff line change
@@ -1,82 +1,109 @@
using Alba;
using JasperFx.CommandLine;
using JasperFx.Core.Reflection;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Hosting;
using Shouldly;
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
using Wolverine.Runtime;
using Wolverine.Tracking;

namespace Wolverine.Http.Tests.Bugs;

public class Bug_using_host_stop
{
[Fact]
public async Task stops_wolverine_runtime_when_created_via_host_builder()
public enum HostType
{
var builder = WebApplication.CreateBuilder([]);
builder.Services.DisableAllWolverineMessagePersistence();
builder.Services.DisableAllExternalWolverineTransports();
builder.Services.AddWolverine(_ => { });
var host = await AlbaHost.For(builder, _ => { });
var runtime = host.GetRuntime();
var checkPoints = new bool[3];

checkPoints[0] = IsRunning(runtime);
await host.StopAsync();
checkPoints[1] = IsRunning(runtime);
await host.DisposeAsync();
checkPoints[2] = IsRunning(runtime);
WebApplicationBuilder,
AlbaHostWithWebApplicationBuilder,
AlbaHostWithFactory
}

// Note WolverineRuntime is stopped when host.StopAsync() is called,
// which is expected as WolverineRuntime is IHostedService.
checkPoints.ShouldBe([true, false, false]);
private class HostTypeData : TheoryData<HostType>
{
public HostTypeData() => AddRange(Enum.GetValues<HostType>());
}

[Fact]
public async Task does_not_stop_wolverine_runtime_when_created_via_web_factory()
[Theory]
[ClassData(typeof(HostTypeData))]
public async Task wolverine_runtime_stops_when_host_is_stopped(HostType type)
{
var builder = WebApplication.CreateBuilder([]);
builder.Services.DisableAllWolverineMessagePersistence();
builder.Services.DisableAllExternalWolverineTransports();
builder.Services.AddWolverine(_ => { });
var host = await AlbaHost.For<WolverineWebApi.Program>(_ => { });
using var host = await CreateHostAsync(type);
var wolverineRuntime = host.GetRuntime();
var checkPoints = new bool[3];
var checkPoints = new bool[2];

checkPoints[0] = IsRunning(wolverineRuntime);
await host.StopAsync();
checkPoints[1] = IsRunning(wolverineRuntime);
await host.DisposeAsync();
checkPoints[2] = IsRunning(wolverineRuntime);

// If you expect host.StopAsync() to stop WolverineRuntime -
// [true, false, false] - it's not the case here.
checkPoints.ShouldBe([true, true, false]);
checkPoints.ShouldBe([true, false]);
}

[Fact]
public async Task wolverine_runtime_can_be_stopped_explicitly_when_created_via_web_factory()
[Theory]
[ClassData(typeof(HostTypeData))]
public async Task wolverine_runtime_stops_when_host_is_disposed(HostType type)
{
var builder = WebApplication.CreateBuilder([]);
builder.Services.DisableAllWolverineMessagePersistence();
builder.Services.DisableAllExternalWolverineTransports();
builder.Services.AddWolverine(_ => { });
var host = await AlbaHost.For<WolverineWebApi.Program>(_ => { });
using var host = await CreateHostAsync(type);
var wolverineRuntime = host.GetRuntime();
var checkPoints = new bool[3];
var checkPoints = new bool[2];

checkPoints[0] = IsRunning(wolverineRuntime);
await host.GetRuntime().StopAsync(default); // Can be stopped explicitly.
await host.StopAsync();
await host.As<IAsyncDisposable>().DisposeAsync();
checkPoints[1] = IsRunning(wolverineRuntime);
await host.DisposeAsync();
checkPoints[2] = IsRunning(wolverineRuntime);

checkPoints.ShouldBe([true, false, false]);
checkPoints.ShouldBe([true, false]);
}

static bool IsRunning(WolverineRuntime runtime)
{
var field = typeof(WolverineRuntime).GetField("_hasStopped", BindingFlags.NonPublic | BindingFlags.Instance);
var field = typeof(WolverineRuntime).GetField("_hasStopped",
BindingFlags.NonPublic | BindingFlags.Instance);
return (bool?)field?.GetValue(runtime) == false;
}
}

private static async Task<IHost> CreateHostAsync(HostType hostType) =>
hostType switch
{
HostType.WebApplicationBuilder =>
await CreateHostWithWebApplicationBuilder(),

HostType.AlbaHostWithWebApplicationBuilder =>
await AlbaHost.For(CreateWebApplicationBuilder(), _ => { }),

_ =>
await CreateAlbaHostWithWithFactory()
};

private static async Task<IHost> CreateAlbaHostWithWithFactory()
{
JasperFxEnvironment.AutoStartHost = true; // to start the underlying host

return await AlbaHost.For<WolverineWebApi.Program>(x =>
x.ConfigureServices(ConfigureWolverine));
}

private static async Task<IHost> CreateHostWithWebApplicationBuilder()
{
var builder = CreateWebApplicationBuilder();
var host = builder.Build();
await host.StartAsync();
return host;
}

private static WebApplicationBuilder CreateWebApplicationBuilder()
{
var builder = WebApplication.CreateBuilder([]);
ConfigureWolverine(builder.Services);
builder.Services.AddWolverine(_ => { });
return builder;
}

private static void ConfigureWolverine(IServiceCollection services)
{
services
.RunWolverineInSoloMode()
.DisableAllWolverineMessagePersistence()
.DisableAllExternalWolverineTransports();
}
}
1 change: 0 additions & 1 deletion src/Http/Wolverine.Http.Tests/IntegrationContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ public async Task DisposeAsync()
if (Host is null)
return;

await Host.GetRuntime().StopAsync(default);
await Host.StopAsync();

await Host.DisposeAsync();
Expand Down
Loading