From 68aa4a135e65a1ef887a4b3a9c850530112a6573 Mon Sep 17 00:00:00 2001 From: "Jeremy D. Miller" <jeremydmiller@yahoo.com> Date: Tue, 21 Nov 2023 07:31:59 -0600 Subject: [PATCH] Add routing diagnostics to diagnostics doc page Closes GH-324 --- docs/guide/diagnostics.md | 33 +++++++++++++++++++ docs/guide/durability/efcore.md | 8 ++--- docs/guide/durability/managing.md | 4 +-- docs/guide/durability/sqlserver.md | 2 +- docs/tutorials/best-practices.md | 2 +- .../Runtime/Routing/routing_precedence.cs | 17 ++++++++++ 6 files changed, 58 insertions(+), 8 deletions(-) diff --git a/docs/guide/diagnostics.md b/docs/guide/diagnostics.md index 4ed969950..706d88985 100644 --- a/docs/guide/diagnostics.md +++ b/docs/guide/diagnostics.md @@ -150,3 +150,36 @@ public static void assert_configuration_is_valid(IHost host) Note that this method will attempt to generate and compile the source code for each message type and use [Lamar's own diagnostics](https://jasperfx.github.io/lamar/guide/ioc/diagnostics/) as well. +## Troubleshooting Message Routing + +Among other information, you can find a preview of how Wolverine will route known message types through the command line +with: + +```bash +dotnet run -- describe +``` + +Part of this output is a table of the known message types and the routed destination of any subscriptions. You can enhance +this diagnostic by helping Wolverine to [discover message types](/guide/messages#message-discovery) in your system. + +And lastly, there's a programmatic way to "preview" the Wolverine message routing at runtime that might +be helpful: + +<!-- snippet: sample_using_preview_subscriptions --> +<a id='snippet-sample_using_preview_subscriptions'></a> +```cs +public static void using_preview_subscriptions(IMessageBus bus) +{ + // Preview where Wolverine is wanting to send a message + var outgoing = bus.PreviewSubscriptions(new BlueMessage()); + foreach (var envelope in outgoing) + { + // The URI value here will identify the endpoint where the message is + // going to be sent (Rabbit MQ exchange, Azure Service Bus topic, Kafka topic, local queue, etc.) + Debug.WriteLine(envelope.Destination); + } +} +``` +<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Testing/CoreTests/Runtime/Routing/routing_precedence.cs#L76-L90' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_preview_subscriptions' title='Start of snippet'>anchor</a></sup> +<!-- endSnippet --> + diff --git a/docs/guide/durability/efcore.md b/docs/guide/durability/efcore.md index 1a659ee95..547470966 100644 --- a/docs/guide/durability/efcore.md +++ b/docs/guide/durability/efcore.md @@ -31,7 +31,7 @@ builder.Host.UseWolverine(opts => opts.Policies.UseDurableLocalQueues(); }); ``` -<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Samples/EFCoreSample/ItemService/Program.cs#L35-L52' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_registering_efcore_middleware' title='Start of snippet'>anchor</a></sup> +<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Samples/EFCoreSample/ItemService/Program.cs#L36-L53' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_registering_efcore_middleware' title='Start of snippet'>anchor</a></sup> <!-- endSnippet --> ::: tip @@ -124,7 +124,7 @@ this syntax for the service registration: builder.Services.AddDbContextWithWolverineIntegration<ItemsDbContext>( x => x.UseSqlServer(connectionString), "wolverine"); ``` -<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Samples/EFCoreSample/ItemService/Program.cs#L18-L25' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_optimized_efcore_registration' title='Start of snippet'>anchor</a></sup> +<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Samples/EFCoreSample/ItemService/Program.cs#L19-L26' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_optimized_efcore_registration' title='Start of snippet'>anchor</a></sup> <!-- endSnippet --> That registration will: @@ -219,7 +219,7 @@ public async Task Post( await outbox.SaveChangesAndFlushMessagesAsync(); } ``` -<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Samples/EFCoreSample/ItemService/CreateItemController.cs#L8-L38' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_dbcontext_outbox_1' title='Start of snippet'>anchor</a></sup> +<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Samples/EFCoreSample/ItemService/CreateItemController.cs#L10-L40' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_dbcontext_outbox_1' title='Start of snippet'>anchor</a></sup> <!-- endSnippet --> Or use the `IDbContextOutbox` as shown below, but in this case you will need to explicitly call `Enroll()` on @@ -261,7 +261,7 @@ public async Task Post3( await outbox.SaveChangesAndFlushMessagesAsync(); } ``` -<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Samples/EFCoreSample/ItemService/CreateItemController.cs#L41-L76' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_dbcontext_outbox_2' title='Start of snippet'>anchor</a></sup> +<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Samples/EFCoreSample/ItemService/CreateItemController.cs#L43-L78' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_dbcontext_outbox_2' title='Start of snippet'>anchor</a></sup> <!-- endSnippet --> ## As Saga Storage diff --git a/docs/guide/durability/managing.md b/docs/guide/durability/managing.md index 6d1596080..bdbb1102b 100644 --- a/docs/guide/durability/managing.md +++ b/docs/guide/durability/managing.md @@ -75,7 +75,7 @@ To have any missing database schema objects built as needed on application start // This is rebuilding the persistent storage database schema on startup builder.Host.UseResourceSetupOnStartup(); ``` -<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Samples/EFCoreSample/ItemService/Program.cs#L54-L59' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_resource_setup_on_startup' title='Start of snippet'>anchor</a></sup> +<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Samples/EFCoreSample/ItemService/Program.cs#L55-L60' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_resource_setup_on_startup' title='Start of snippet'>anchor</a></sup> <!-- endSnippet --> ## Command Line Management @@ -89,7 +89,7 @@ shown in this last line of a .NET 6/7 `Program` code file: // Opt into using Oakton for command parsing await app.RunOaktonCommands(args); ``` -<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Samples/EFCoreSample/ItemService/Program.cs#L80-L85' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_oakton_for_command_line_parsing' title='Start of snippet'>anchor</a></sup> +<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Samples/EFCoreSample/ItemService/Program.cs#L83-L88' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_oakton_for_command_line_parsing' title='Start of snippet'>anchor</a></sup> <!-- endSnippet --> And you're using the message persistence from either the `WolverineFx.SqlServer` or `WolverineFx.Postgresql` diff --git a/docs/guide/durability/sqlserver.md b/docs/guide/durability/sqlserver.md index d7f2b907b..105051a78 100644 --- a/docs/guide/durability/sqlserver.md +++ b/docs/guide/durability/sqlserver.md @@ -30,7 +30,7 @@ builder.Host.UseWolverine(opts => opts.Policies.UseDurableLocalQueues(); }); ``` -<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Samples/EFCoreSample/ItemService/Program.cs#L35-L52' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_registering_efcore_middleware' title='Start of snippet'>anchor</a></sup> +<sup><a href='https://github.com/JasperFx/wolverine/blob/main/src/Samples/EFCoreSample/ItemService/Program.cs#L36-L53' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_registering_efcore_middleware' title='Start of snippet'>anchor</a></sup> <!-- endSnippet --> ## Sql Server Messaging Transport diff --git a/docs/tutorials/best-practices.md b/docs/tutorials/best-practices.md index 3881c2a68..a9cde4510 100644 --- a/docs/tutorials/best-practices.md +++ b/docs/tutorials/best-practices.md @@ -224,4 +224,4 @@ has quite a bit of features specifically to support a "Vertical Slice Architectu to utilize Wolverine to create a maintainable codebase with much less complexity than the state of the art Clean/Onion layered approach. -See [Low Ceremony Vertical Slice Architecture with Wolverine](https://jeremydmiller.com/2023/07/10/low-ceremony-vertical-slice-architecture-with-wolverine/) \ No newline at end of file +See [Low Ceremony Vertical Slice Architecture with Wolverine](https://jeremydmiller.com/2023/07/10/low-ceremony-vertical-slice-architecture-with-wolverine/) diff --git a/src/Testing/CoreTests/Runtime/Routing/routing_precedence.cs b/src/Testing/CoreTests/Runtime/Routing/routing_precedence.cs index fb236556f..42ea5b994 100644 --- a/src/Testing/CoreTests/Runtime/Routing/routing_precedence.cs +++ b/src/Testing/CoreTests/Runtime/Routing/routing_precedence.cs @@ -1,6 +1,7 @@ using System; using System.CodeDom.Compiler; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; @@ -71,6 +72,22 @@ public async Task explicit_routing_to_local_wins() bus.PreviewSubscriptions(new BlueMessage()) .Single().Destination.ShouldBe(new Uri("local://purple")); } + + #region sample_using_preview_subscriptions + + public static void using_preview_subscriptions(IMessageBus bus) + { + // Preview where Wolverine is wanting to send a message + var outgoing = bus.PreviewSubscriptions(new BlueMessage()); + foreach (var envelope in outgoing) + { + // The URI value here will identify the endpoint where the message is + // going to be sent (Rabbit MQ exchange, Azure Service Bus topic, Kafka topic, local queue, etc.) + Debug.WriteLine(envelope.Destination); + } + } + + #endregion [Fact] public async Task explicit_routing_to_elsewhere_wins()