Skip to content

Commit

Permalink
Option to disable persistence altogether with a HostBuilderExtension. C…
Browse files Browse the repository at this point in the history
…loses GH-723
  • Loading branch information
jeremydmiller committed Dec 30, 2024
1 parent 29a1d05 commit b9dfeab
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 14 deletions.
2 changes: 1 addition & 1 deletion docs/guide/durability/leadership-and-troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ builder.UseWolverine(opts =>
}
});

using var host = builder.Build();~~~~
using var host = builder.Build();
await host.StartAsync();
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Samples/DocumentationSamples/DurabilityModes.cs#L63-L90' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_configuring_the_solo_mode' title='Start of snippet'>anchor</a></sup>
Expand Down
22 changes: 22 additions & 0 deletions docs/guide/durability/managing.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,3 +165,25 @@ If you just want to export the SQL to create the necessary database objects, you
dotnet run -- db-dump export.sql
```
where `export.sql` should be a file name.
## Disabling All Persistence <Badge type="tip" text="3.6" />
Let's say that you want to use the command line tooling to generate OpenAPI documentation, but do so
without Wolverine being able to connect to any external databases (or transports, and you'll have to disable both for this to work).
You can now do that with the option shown below as part of an [Alba](https://jasperfx.github.io/alba) test:
<!-- snippet: sample_bootstrap_with_no_persistence -->
<a id='snippet-sample_bootstrap_with_no_persistence'></a>
```cs
using var host = await AlbaHost.For<Program>(builder =>
{
builder.ConfigureServices(services =>
{
// You probably have to do both
services.DisableAllExternalWolverineTransports();
services.DisableAllWolverineMessagePersistence();
});
});
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/Wolverine.Http.Tests/bootstrap_with_no_persistence.cs#L14-L26' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_bootstrap_with_no_persistence' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->
2 changes: 1 addition & 1 deletion docs/guide/extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ internal class DisableExternalTransports : IWolverineExtension
}
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Wolverine/HostBuilderExtensions.cs#L382-L392' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_disableexternaltransports' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Wolverine/HostBuilderExtensions.cs#L396-L406' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_disableexternaltransports' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

And that extension is just added to the application's IoC container at test bootstrapping time like this:
Expand Down
4 changes: 2 additions & 2 deletions docs/guide/http/multi-tenancy.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ public static string NoTenantNoProblem()
return "hey";
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/Wolverine.Http.Tests/multi_tenancy_detection_and_integration.cs#L421-L430' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_nottenanted' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/Wolverine.Http.Tests/multi_tenancy_detection_and_integration.cs#L430-L439' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_nottenanted' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

If the above usage completely disabled all tenant id detection or validation, in the case of an endpoint that *might* be
Expand All @@ -283,7 +283,7 @@ public static string MaybeTenanted(IMessageBus bus)
return bus.TenantId ?? "none";
}
```
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/Wolverine.Http.Tests/multi_tenancy_detection_and_integration.cs#L432-L441' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_maybe_tenanted_attribute_usage' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Http/Wolverine.Http.Tests/multi_tenancy_detection_and_integration.cs#L441-L450' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_maybe_tenanted_attribute_usage' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->


Expand Down
2 changes: 1 addition & 1 deletion src/Http/Wolverine.Http.Tests/Wolverine.Http.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Alba" Version="7.4.1" />
<PackageReference Include="Alba" Version="8.1.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.2" />
<PackageReference Include="Npgsql" Version="9.0.2" />
<PackageReference Include="Refit" Version="8.0.0" />
Expand Down
31 changes: 31 additions & 0 deletions src/Http/Wolverine.Http.Tests/bootstrap_with_no_persistence.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using Alba;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Wolverine.Persistence.Durability;
using Wolverine.Tracking;

namespace Wolverine.Http.Tests;

public class bootstrap_with_no_persistence
{
[Fact]
public async Task start_up_with_no_persistence()
{
#region sample_bootstrap_with_no_persistence

using var host = await AlbaHost.For<Program>(builder =>
{
builder.ConfigureServices(services =>
{
// You probably have to do both
services.DisableAllExternalWolverineTransports();
services.DisableAllWolverineMessagePersistence();
});
});

#endregion

host.Services.GetRequiredService<IMessageStore>().ShouldBeOfType<NullMessageStore>();
host.GetRuntime().Storage.ShouldBeOfType<NullMessageStore>();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
using IntegrationTests;
using Marten;
using Marten.Metadata;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
Expand Down Expand Up @@ -41,6 +43,7 @@ public void Dispose()
protected async Task configure(Action<WolverineHttpOptions> configure)
{
var builder = WebApplication.CreateBuilder([]);

builder.Services.AddScoped<IUserService, UserService>();

// Haven't gotten around to it yet, but there'll be some end to
Expand All @@ -57,17 +60,21 @@ protected async Task configure(Action<WolverineHttpOptions> configure)
});

builder.Services.AddWolverineHttp();
builder.Services.AddAuthentication("test");
builder.Services.AddAuthorization();

// Setting up Alba stubbed authentication so that we can fake
// out ClaimsPrincipal data on requests later
var securityStub = new AuthenticationStub()
var securityStub = new AuthenticationStub("test")
.With("foo", "bar")
.With(JwtRegisteredClaimNames.Email, "[email protected]")
.WithName("jeremy");

// Spinning up a test application using Alba
theHost = await AlbaHost.For(builder, app =>
{
app.UseAuthentication();
app.UseAuthorization();
app.MapWolverineEndpoints(configure);
}, securityStub);

Expand Down Expand Up @@ -367,12 +374,14 @@ public async Task does_tag_current_activity_with_tenant_id()

public static class TenantedEndpoints
{
[Authorize]
[WolverineGet("/tenant/route/{tenant}")]
public static string GetTenantIdFromRoute(IMessageBus bus)
{
return bus.TenantId;
}

[Authorize]
[WolverineGet("/tenant")]
public static string GetTenantIdFromWhatever(IMessageBus bus, HttpContext httpContext)
{
Expand Down Expand Up @@ -470,4 +479,12 @@ public static CustomActivityFeature FromHttpContext(HttpContext httpContext)
var activity = httpContext.Features.Get<IHttpActivityFeature>()?.Activity;
return new CustomActivityFeature(activity);
}
}

public class StubAuthenticationHandlerProvider : IAuthenticationHandlerProvider
{
public Task<IAuthenticationHandler?> GetHandlerAsync(HttpContext context, string authenticationScheme)
{
throw new NotImplementedException();
}
}
17 changes: 12 additions & 5 deletions src/Persistence/Wolverine.RDBMS/Polling/DatabaseBatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,19 @@ await _executor.Value.InvokeAsync(new DatabaseOperationBatch(_database, operatio

public async Task DrainAsync()
{
_internalCancellation.Cancel();
try
{
_internalCancellation.Cancel();

_batchingBlock.Complete();
await _batchingBlock.Completion;
_batchingBlock.Complete();
await _batchingBlock.Completion;

_executingBlock.Complete();
await _executingBlock.Completion;
_executingBlock.Complete();
await _executingBlock.Completion;
}
catch (Exception e)
{
_logger.LogError(e, "Error trying to drain the current database batcher");
}
}
}
23 changes: 23 additions & 0 deletions src/Wolverine/HostBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,20 @@ public static IServiceCollection DisableAllExternalWolverineTransports(this ISer
}

#endregion

/// <summary>
/// Disable all Wolverine message persistence bootstrapping and durability agents. This
/// was built for the case of needing to run the application for OpenAPI generation when
/// the database might not be available
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection DisableAllWolverineMessagePersistence(this IServiceCollection services)
{
services.AddSingleton<IMessageStore, NullMessageStore>();
services.AddSingleton<IWolverineExtension, DisablePersistence>();
return services;
}

#region sample_DisableExternalTransports

Expand All @@ -391,6 +405,15 @@ public void Configure(WolverineOptions options)

#endregion

internal class DisablePersistence : IWolverineExtension
{
public void Configure(WolverineOptions options)
{
options.Durability.DurabilityMetricsEnabled = false;
options.Durability.DurabilityAgentEnabled = false;
}
}

/// <summary>
/// Override the durability mode of Wolverine to be "Solo". This is valuable in automated
/// testing scenarios to make application activation and teardown faster and to bypass
Expand Down
7 changes: 5 additions & 2 deletions src/Wolverine/Runtime/WolverineRuntime.HostService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@ public async Task StartAsync(CancellationToken cancellationToken)

await ApplyAsyncExtensions();

foreach (var configuresRuntime in Options.Transports.OfType<ITransportConfiguresRuntime>().ToArray())
if (!Options.ExternalTransportsAreStubbed)
{
await configuresRuntime.ConfigureAsync(this);
foreach (var configuresRuntime in Options.Transports.OfType<ITransportConfiguresRuntime>().ToArray())
{
await configuresRuntime.ConfigureAsync(this);
}
}

// Build up the message handlers
Expand Down

0 comments on commit b9dfeab

Please sign in to comment.