From 9e3cc5aa28f88a7da212ace3a068e751dca156f8 Mon Sep 17 00:00:00 2001 From: "Jeremy D. Miller" Date: Fri, 11 Oct 2024 12:12:24 -0500 Subject: [PATCH 1/4] Updates to the documentation about the Lamar usage --- docs/guide/configuration.md | 38 ++++++++++++++++++- package-lock.json | 1 - .../Configuration/DocumentationSamples.cs | 29 ++++++++++++++ 3 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 src/Testing/CoreTests/Configuration/DocumentationSamples.cs diff --git a/docs/guide/configuration.md b/docs/guide/configuration.md index 052458d68..50a22053c 100644 --- a/docs/guide/configuration.md +++ b/docs/guide/configuration.md @@ -7,7 +7,7 @@ Wolverine 3.0 *is* tested with both the built in `ServiceProvider` and Lamar. It IoC containers now as long as they conform to the .NET conforming container, but this isn't tested by the Wolverine team. ::: -Wolverine is configured with the `IHostBuilder.UseWolverine()` extension methods, with the actual configuration +Wolverine is configured with the `IHostBuilder.UseWolverine()` or `HostApplicationBuilder` extension methods, with the actual configuration living on a single `WolverineOptions` object. The `WolverineOptions` is the configuration model for your Wolverine application, and as such it can be used to configure directives about: @@ -25,6 +25,42 @@ At this point, Wolverine only supports [IHostBuilder](https://learn.microsoft.co model in the future. ::: +## Replacing ServiceProvider with Lamar + +If you run into any trouble whatsoever with code generation after upgrading to Wolverine 3.0, please: + +1. Please [raise a GitHub issue in Wolverine](https://github.com/JasperFx/wolverine/issues/new/choose) with some description of the offending message handler or http endpoint +2. Fall back to Lamar for your IoC tool + +To use Lamar, add this Nuget to your main project: + +```bash +dotnet add package Lamar.Microsoft.DependencyInjection +``` + +If you're using `IHostBuilder` like you might for a simple console app, it's: + +snippet: sample_use_lamar_with_host_builder + +In a web application, it's: + +```csharp +var builder = WebApplication.CreateBuilder(args); +builder.Host.UseLamar(); +``` + +and with `HostApplicationBuilder`, try: + +```csharp +var builder = Host.CreateApplicationBuilder(); + +// Little ugly, and Lamar *should* have a helper for this... +builder.ConfigureContainer(new LamarServiceProviderFactory()); +``` + + + + ## With ASP.NET Core Below is a sample of adding Wolverine to an ASP.NET Core application that is bootstrapped with diff --git a/package-lock.json b/package-lock.json index 7661213a0..eb82049c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,7 +4,6 @@ "requires": true, "packages": { "": { - "name": "wolverine", "devDependencies": { "@mermaid-js/mermaid-mindmap": "^9.3.0", "chai": "^4", diff --git a/src/Testing/CoreTests/Configuration/DocumentationSamples.cs b/src/Testing/CoreTests/Configuration/DocumentationSamples.cs new file mode 100644 index 000000000..fae214201 --- /dev/null +++ b/src/Testing/CoreTests/Configuration/DocumentationSamples.cs @@ -0,0 +1,29 @@ +using Lamar; +using Lamar.Microsoft.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace CoreTests.Configuration; + +public static class DocumentationSamples +{ + public static async Task bootstrap_with_lamar() + { + #region sample_use_lamar_with_host_builder + + // With IHostBuilder + var builder = Host.CreateDefaultBuilder(); + builder.UseLamar(); + + #endregion + + + } + + public static async Task bootstrap_with_lamar_using_web_app() + { + var builder = Host.CreateApplicationBuilder(); + + // Little ugly, and Lamar *should* have a helper for this... + builder.ConfigureContainer(new LamarServiceProviderFactory()); + } +} \ No newline at end of file From 4ccef7ecb249e3a11e4664a9344f429489502570 Mon Sep 17 00:00:00 2001 From: "Jeremy D. Miller" Date: Sun, 13 Oct 2024 13:23:53 -0500 Subject: [PATCH 2/4] Significant clean up of random problems with various transport test suites --- docker-compose.yml | 17 ++---- .../BufferedSendingAndReceivingCompliance.cs | 3 +- .../DurableSendingAndReceivingCompliance.cs | 1 - .../InlineSendingAndReceivingCompliance.cs | 1 - .../NoParallelization.cs | 3 ++ .../sending_compliance_with_prefixes.cs | 1 - .../Internal/AmazonSqsTransport.cs | 2 +- .../BufferedSendingAndReceivingCompliance.cs | 1 - .../conventional_listener_discovery.cs | 5 +- .../discover_with_naming_prefix.cs | 2 +- .../end_to_end_with_conventional_routing.cs | 45 +++++++++------- ..._a_listening_endpoint_with_all_defaults.cs | 2 +- .../InlineSendingAndReceivingCompliance.cs | 1 - .../clean_off_queues.cs | 52 +++++++++++++++++++ ...d_receive_with_topics_and_subscriptions.cs | 1 - ...pics_and_subscriptions_with_custom_rule.cs | 1 - .../sending_compliance_with_prefixes.cs | 1 - .../AzureServiceBusTransport.cs | 5 ++ .../Internal/AzureServiceBusEndpoint.cs | 5 ++ .../Internal/AzureServiceBusQueue.cs | 18 +++++-- .../DocumentationSamples.cs | 2 +- .../StatefulResourceSmokeTests.cs | 4 +- .../broadcast_to_topic_async.cs | 4 +- .../broadcast_to_topic_rules.cs | 4 +- .../Kafka/Wolverine.Kafka.Tests/compliance.cs | 10 ++-- .../publish_and_receive_raw_json.cs | 4 +- .../Wolverine.MQTT.Tests/ack_smoke_tests.cs | 4 +- 27 files changed, 134 insertions(+), 65 deletions(-) create mode 100644 src/Transports/AWS/Wolverine.AmazonSqs.Tests/NoParallelization.cs create mode 100644 src/Transports/Azure/Wolverine.AzureServiceBus.Tests/clean_off_queues.cs diff --git a/docker-compose.yml b/docker-compose.yml index 844939aa7..1e190ac6e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -36,7 +36,7 @@ services: localstack: - image: localstack/localstack + image: localstack/localstack:stable ports: - "127.0.0.1:4566:4566" # LocalStack Gateway - "127.0.0.1:4510-4559:4510-4559" # external services port range @@ -59,15 +59,8 @@ services: - 22181:2181 kafka: - image: confluentinc/cp-kafka:latest - depends_on: - - zookeeper + image: confluentinc/confluent-local:latest ports: - - 29092:29092 - environment: - KAFKA_BROKER_ID: 1 - KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 - KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092 - KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT - KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT - KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 \ No newline at end of file + - "8082:8082" + - "9092:9092" + - "9101:9101" \ No newline at end of file diff --git a/src/Transports/AWS/Wolverine.AmazonSqs.Tests/BufferedSendingAndReceivingCompliance.cs b/src/Transports/AWS/Wolverine.AmazonSqs.Tests/BufferedSendingAndReceivingCompliance.cs index d967f354f..4472d7d34 100644 --- a/src/Transports/AWS/Wolverine.AmazonSqs.Tests/BufferedSendingAndReceivingCompliance.cs +++ b/src/Transports/AWS/Wolverine.AmazonSqs.Tests/BufferedSendingAndReceivingCompliance.cs @@ -15,7 +15,7 @@ public BufferedComplianceFixture() : base(new Uri("sqs://receiver"), 120) public async Task InitializeAsync() { - var number = Guid.NewGuid().ToString(); + var number = Guid.NewGuid().ToString().Replace(".", "-"); OutboundAddress = new Uri("sqs://receiver-" + number); @@ -42,7 +42,6 @@ public async Task DisposeAsync() } } -[Collection("acceptance")] public class BufferedSendingAndReceivingCompliance : TransportCompliance { [Fact] diff --git a/src/Transports/AWS/Wolverine.AmazonSqs.Tests/DurableSendingAndReceivingCompliance.cs b/src/Transports/AWS/Wolverine.AmazonSqs.Tests/DurableSendingAndReceivingCompliance.cs index cb8d78213..691a7dc67 100644 --- a/src/Transports/AWS/Wolverine.AmazonSqs.Tests/DurableSendingAndReceivingCompliance.cs +++ b/src/Transports/AWS/Wolverine.AmazonSqs.Tests/DurableSendingAndReceivingCompliance.cs @@ -72,7 +72,6 @@ public async Task DisposeAsync() await DisposeAsync(); } - [Collection("acceptance")] public class DurableSendingAndReceivingCompliance : TransportCompliance { [Fact] diff --git a/src/Transports/AWS/Wolverine.AmazonSqs.Tests/InlineSendingAndReceivingCompliance.cs b/src/Transports/AWS/Wolverine.AmazonSqs.Tests/InlineSendingAndReceivingCompliance.cs index 13e721570..c77baa104 100644 --- a/src/Transports/AWS/Wolverine.AmazonSqs.Tests/InlineSendingAndReceivingCompliance.cs +++ b/src/Transports/AWS/Wolverine.AmazonSqs.Tests/InlineSendingAndReceivingCompliance.cs @@ -48,7 +48,6 @@ public async Task DisposeAsync() } } -[Collection("acceptance")] public class InlineSendingAndReceivingCompliance : TransportCompliance { [Fact] diff --git a/src/Transports/AWS/Wolverine.AmazonSqs.Tests/NoParallelization.cs b/src/Transports/AWS/Wolverine.AmazonSqs.Tests/NoParallelization.cs new file mode 100644 index 000000000..b1fa88422 --- /dev/null +++ b/src/Transports/AWS/Wolverine.AmazonSqs.Tests/NoParallelization.cs @@ -0,0 +1,3 @@ +using Xunit; + +[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly)] \ No newline at end of file diff --git a/src/Transports/AWS/Wolverine.AmazonSqs.Tests/sending_compliance_with_prefixes.cs b/src/Transports/AWS/Wolverine.AmazonSqs.Tests/sending_compliance_with_prefixes.cs index ae72658d9..c7c8016a3 100644 --- a/src/Transports/AWS/Wolverine.AmazonSqs.Tests/sending_compliance_with_prefixes.cs +++ b/src/Transports/AWS/Wolverine.AmazonSqs.Tests/sending_compliance_with_prefixes.cs @@ -46,7 +46,6 @@ public async Task DisposeAsync() } } -[Collection("acceptance")] public class PrefixedSendingAndReceivingCompliance : TransportCompliance { [Fact] diff --git a/src/Transports/AWS/Wolverine.AmazonSqs/Internal/AmazonSqsTransport.cs b/src/Transports/AWS/Wolverine.AmazonSqs/Internal/AmazonSqsTransport.cs index 28cc1df0a..472a85dbf 100644 --- a/src/Transports/AWS/Wolverine.AmazonSqs/Internal/AmazonSqsTransport.cs +++ b/src/Transports/AWS/Wolverine.AmazonSqs/Internal/AmazonSqsTransport.cs @@ -85,7 +85,7 @@ protected override AmazonSqsQueue findEndpointByUri(Uri uri) { throw new ArgumentOutOfRangeException(nameof(uri)); } - return Queues.Where(x => x.Uri.OriginalString == uri.OriginalString).FirstOrDefault() ?? Queues[uri.OriginalString.Split("//")[1]]; + return Queues.Where(x => x.Uri.OriginalString == uri.OriginalString).FirstOrDefault() ?? Queues[uri.OriginalString.Split("//")[1].TrimEnd('/')]; } public override ValueTask ConnectAsync(IWolverineRuntime runtime) diff --git a/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/BufferedSendingAndReceivingCompliance.cs b/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/BufferedSendingAndReceivingCompliance.cs index 89ac5120b..1b7f8c4aa 100644 --- a/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/BufferedSendingAndReceivingCompliance.cs +++ b/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/BufferedSendingAndReceivingCompliance.cs @@ -40,7 +40,6 @@ public async Task DisposeAsync() } } -[Collection("acceptance")] public class BufferedSendingAndReceivingCompliance : TransportCompliance { [Fact] diff --git a/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/ConventionalRouting/conventional_listener_discovery.cs b/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/ConventionalRouting/conventional_listener_discovery.cs index c2f6335fb..b222b4c56 100644 --- a/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/ConventionalRouting/conventional_listener_discovery.cs +++ b/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/ConventionalRouting/conventional_listener_discovery.cs @@ -95,7 +95,10 @@ public void disable_listener_by_lambda() [Fact] public void configure_listener() { - ConfigureConventions(c => c.ConfigureListeners((x, _) => { x.UseDurableInbox(); })); + ConfigureConventions(c => c.ConfigureListeners((x, _) => + { + x.UseDurableInbox(); + })); var endpoint = theRuntime.Endpoints.EndpointFor("asb://queue/routed".ToUri()) .ShouldBeOfType(); diff --git a/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/ConventionalRouting/discover_with_naming_prefix.cs b/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/ConventionalRouting/discover_with_naming_prefix.cs index d0959f8d7..cec8e3988 100644 --- a/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/ConventionalRouting/discover_with_naming_prefix.cs +++ b/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/ConventionalRouting/discover_with_naming_prefix.cs @@ -35,6 +35,6 @@ public void discover_listener_with_prefix() var uris = runtime.Endpoints.ActiveListeners().Select(x => x.Uri).ToArray(); uris.ShouldContain(new Uri("asb://queue/zztop.routed")); - uris.ShouldContain(new Uri("asb://queue/zztop.Wolverine.AzureServiceBus.Tests.AsbMessage")); + uris.ShouldContain(new Uri("asb://queue/zztop.wolverine.azureservicebus.tests.asbmessage1")); } } \ No newline at end of file diff --git a/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/ConventionalRouting/end_to_end_with_conventional_routing.cs b/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/ConventionalRouting/end_to_end_with_conventional_routing.cs index 0af795e85..86a511c0d 100644 --- a/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/ConventionalRouting/end_to_end_with_conventional_routing.cs +++ b/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/ConventionalRouting/end_to_end_with_conventional_routing.cs @@ -1,5 +1,6 @@ using JasperFx.Core; using Microsoft.Extensions.Hosting; +using Oakton.Resources; using Shouldly; using Wolverine.ComplianceTests; using Wolverine.Tracking; @@ -7,31 +8,37 @@ namespace Wolverine.AzureServiceBus.Tests.ConventionalRouting; -public class end_to_end_with_conventional_routing : IDisposable +public class end_to_end_with_conventional_routing : IAsyncLifetime { - private readonly IHost _receiver; - private readonly IHost _sender; + private IHost _receiver; + private IHost _sender; - public end_to_end_with_conventional_routing() + public async Task InitializeAsync() { - _sender = WolverineHost.For(opts => - { - opts.UseAzureServiceBusTesting().UseConventionalRouting().AutoProvision().AutoPurgeOnStartup(); - opts.DisableConventionalDiscovery(); - opts.ServiceName = "Sender"; - }); - - _receiver = WolverineHost.For(opts => - { - opts.UseAzureServiceBusTesting().UseConventionalRouting().AutoProvision().AutoPurgeOnStartup(); - opts.ServiceName = "Receiver"; - }); + _sender = await Host.CreateDefaultBuilder() + .UseWolverine(opts => + { + opts.UseAzureServiceBusTesting().UseConventionalRouting().AutoProvision().AutoPurgeOnStartup(); + opts.DisableConventionalDiscovery(); + opts.ServiceName = "Sender"; + + opts.Services.AddResourceSetupOnStartup(); + }).StartAsync(); + + _receiver = await Host.CreateDefaultBuilder() + .UseWolverine(opts => + { + opts.UseAzureServiceBusTesting().UseConventionalRouting().AutoProvision().AutoPurgeOnStartup(); + opts.ServiceName = "Receiver"; + + opts.Services.AddResourceSetupOnStartup(); + }).StartAsync(); } - public void Dispose() + public async Task DisposeAsync() { - _sender?.Dispose(); - _receiver?.Dispose(); + await _sender.StopAsync(); + await _receiver.StopAsync(); } [Fact] diff --git a/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/ConventionalRouting/when_discovering_a_listening_endpoint_with_all_defaults.cs b/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/ConventionalRouting/when_discovering_a_listening_endpoint_with_all_defaults.cs index e02eff794..017d1e490 100644 --- a/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/ConventionalRouting/when_discovering_a_listening_endpoint_with_all_defaults.cs +++ b/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/ConventionalRouting/when_discovering_a_listening_endpoint_with_all_defaults.cs @@ -8,7 +8,7 @@ namespace Wolverine.AzureServiceBus.Tests.ConventionalRouting; public class when_discovering_a_listening_endpoint_with_all_defaults : ConventionalRoutingContext { - private readonly Uri theExpectedUri = "asb://queue/routed".ToUri(); + private readonly Uri theExpectedUri = "asb://queue/routed2".ToUri(); private readonly AzureServiceBusQueue theQueue; public when_discovering_a_listening_endpoint_with_all_defaults() diff --git a/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/InlineSendingAndReceivingCompliance.cs b/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/InlineSendingAndReceivingCompliance.cs index 53ef59d85..201f0552e 100644 --- a/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/InlineSendingAndReceivingCompliance.cs +++ b/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/InlineSendingAndReceivingCompliance.cs @@ -42,5 +42,4 @@ public Task DisposeAsync() } } -[Collection("acceptance")] public class InlineSendingAndReceivingCompliance : TransportCompliance; \ No newline at end of file diff --git a/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/clean_off_queues.cs b/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/clean_off_queues.cs new file mode 100644 index 000000000..f11577dc5 --- /dev/null +++ b/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/clean_off_queues.cs @@ -0,0 +1,52 @@ +using Microsoft.Extensions.Hosting; +using Wolverine.Tracking; +using Xunit; +using Xunit.Abstractions; + +namespace Wolverine.AzureServiceBus.Tests; + +public class clean_off_queues +{ + private readonly ITestOutputHelper _output; + + public clean_off_queues(ITestOutputHelper output) + { + _output = output; + } + + //[Fact] -- leaving this here for later + public async Task clean_off_existing_queues() + { + using var host = await Host.CreateDefaultBuilder() + .UseWolverine(opts => + { + opts.UseAzureServiceBusTesting(); + }).StartAsync(); + + var transport = host.GetRuntime().Options.Transports.GetOrCreate(); + + + while (true) + { + var queueNames = new List(); + await foreach (var what in transport.ManagementClient.GetQueuesAsync(CancellationToken.None)) + { + queueNames.Add(what.Name); + } + + if (!queueNames.Any()) + { + return; + } + + foreach (var queueName in queueNames) + { + await transport.ManagementClient.DeleteQueueAsync(queueName, CancellationToken.None); + _output.WriteLine("Deleted " + queueName); + } + } + + + + } +} \ No newline at end of file diff --git a/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/send_and_receive_with_topics_and_subscriptions.cs b/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/send_and_receive_with_topics_and_subscriptions.cs index 856c7690e..68905ef06 100644 --- a/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/send_and_receive_with_topics_and_subscriptions.cs +++ b/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/send_and_receive_with_topics_and_subscriptions.cs @@ -32,5 +32,4 @@ public Task DisposeAsync() } } -[Collection("acceptance")] public class TopicAndSubscriptionSendingAndReceivingCompliance : TransportCompliance; \ No newline at end of file diff --git a/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/send_and_receive_with_topics_and_subscriptions_with_custom_rule.cs b/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/send_and_receive_with_topics_and_subscriptions_with_custom_rule.cs index 9fab1dc8b..f18de9d4d 100644 --- a/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/send_and_receive_with_topics_and_subscriptions_with_custom_rule.cs +++ b/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/send_and_receive_with_topics_and_subscriptions_with_custom_rule.cs @@ -38,7 +38,6 @@ public Task DisposeAsync() } } -[Collection("acceptance")] public class TopicAndSubscriptionWithCustomRuleSendingAndReceivingCompliance : TransportCompliance { [Fact] diff --git a/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/sending_compliance_with_prefixes.cs b/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/sending_compliance_with_prefixes.cs index ce17d2fcf..5c932caad 100644 --- a/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/sending_compliance_with_prefixes.cs +++ b/src/Transports/Azure/Wolverine.AzureServiceBus.Tests/sending_compliance_with_prefixes.cs @@ -43,7 +43,6 @@ public Task DisposeAsync() } } -[Collection("acceptance")] public class PrefixedSendingAndReceivingCompliance : TransportCompliance { [Fact] diff --git a/src/Transports/Azure/Wolverine.AzureServiceBus/AzureServiceBusTransport.cs b/src/Transports/Azure/Wolverine.AzureServiceBus/AzureServiceBusTransport.cs index 3fe2db3a2..f5d3699c1 100644 --- a/src/Transports/Azure/Wolverine.AzureServiceBus/AzureServiceBusTransport.cs +++ b/src/Transports/Azure/Wolverine.AzureServiceBus/AzureServiceBusTransport.cs @@ -33,6 +33,11 @@ public AzureServiceBusTransport() : base(ProtocolName, "Azure Service Bus") IdentifierDelimiter = "."; } + public override string SanitizeIdentifier(string identifier) + { + return identifier.ToLowerInvariant(); + } + /// /// Is this transport connection allowed to build and use response and retry queues /// for just this node? diff --git a/src/Transports/Azure/Wolverine.AzureServiceBus/Internal/AzureServiceBusEndpoint.cs b/src/Transports/Azure/Wolverine.AzureServiceBus/Internal/AzureServiceBusEndpoint.cs index 055ef9d63..f5d258a8f 100644 --- a/src/Transports/Azure/Wolverine.AzureServiceBus/Internal/AzureServiceBusEndpoint.cs +++ b/src/Transports/Azure/Wolverine.AzureServiceBus/Internal/AzureServiceBusEndpoint.cs @@ -78,4 +78,9 @@ internal IAzureServiceBusEnvelopeMapper BuildMapper(IWolverineRuntime runtime) /// If specified, applies a custom envelope mapper to this endp[oint /// public IAzureServiceBusEnvelopeMapper? Mapper { get; set; } + + public override string ToString() + { + return $"{GetType().Name}: {Uri}"; + } } \ No newline at end of file diff --git a/src/Transports/Azure/Wolverine.AzureServiceBus/Internal/AzureServiceBusQueue.cs b/src/Transports/Azure/Wolverine.AzureServiceBus/Internal/AzureServiceBusQueue.cs index f72b3bae1..1798c2740 100644 --- a/src/Transports/Azure/Wolverine.AzureServiceBus/Internal/AzureServiceBusQueue.cs +++ b/src/Transports/Azure/Wolverine.AzureServiceBus/Internal/AzureServiceBusQueue.cs @@ -57,11 +57,23 @@ public override async ValueTask SetupAsync(ILogger logger) var client = Parent.ManagementClient; var exists = await client.QueueExistsAsync(QueueName); - if (!exists) + if (!exists.Value) { Options.Name = QueueName; - await client.CreateQueueAsync(Options); + try + { + await client.CreateQueueAsync(Options); + } + catch (ServiceBusException e) + { + if (e.Reason == ServiceBusFailureReason.MessagingEntityAlreadyExists) + { + return; + } + + throw; + } } } @@ -82,7 +94,7 @@ public async ValueTask PurgeAsync(ILogger logger) } catch (Exception e) { - logger.LogError(e, "Error trying to purge Azure Service Bus queue {Queue}", QueueName); + logger.LogDebug(e, "Error trying to purge Azure Service Bus queue {Queue}", QueueName); } } diff --git a/src/Transports/Kafka/Wolverine.Kafka.Tests/DocumentationSamples.cs b/src/Transports/Kafka/Wolverine.Kafka.Tests/DocumentationSamples.cs index faa43d2c1..414246240 100644 --- a/src/Transports/Kafka/Wolverine.Kafka.Tests/DocumentationSamples.cs +++ b/src/Transports/Kafka/Wolverine.Kafka.Tests/DocumentationSamples.cs @@ -12,7 +12,7 @@ public static async Task configure() using var host = await Host.CreateDefaultBuilder() .UseWolverine(opts => { - opts.UseKafka("localhost:29092") + opts.UseKafka("localhost:9092") // See https://github.com/confluentinc/confluent-kafka-dotnet for the exact options here .ConfigureClient(client => diff --git a/src/Transports/Kafka/Wolverine.Kafka.Tests/StatefulResourceSmokeTests.cs b/src/Transports/Kafka/Wolverine.Kafka.Tests/StatefulResourceSmokeTests.cs index 57e0abfcd..01318d512 100644 --- a/src/Transports/Kafka/Wolverine.Kafka.Tests/StatefulResourceSmokeTests.cs +++ b/src/Transports/Kafka/Wolverine.Kafka.Tests/StatefulResourceSmokeTests.cs @@ -14,11 +14,11 @@ private IHostBuilder ConfigureBuilder(bool autoProvision, int starting = 1) { if (autoProvision) { - opts.UseKafka("localhost:29092").AutoProvision(); + opts.UseKafka("localhost:9092").AutoProvision(); } else { - opts.UseKafka("localhost:29092");; + opts.UseKafka("localhost:9092");; } opts.PublishMessage() diff --git a/src/Transports/Kafka/Wolverine.Kafka.Tests/broadcast_to_topic_async.cs b/src/Transports/Kafka/Wolverine.Kafka.Tests/broadcast_to_topic_async.cs index 4e064dc49..1851bfbb6 100644 --- a/src/Transports/Kafka/Wolverine.Kafka.Tests/broadcast_to_topic_async.cs +++ b/src/Transports/Kafka/Wolverine.Kafka.Tests/broadcast_to_topic_async.cs @@ -25,7 +25,7 @@ public async Task InitializeAsync() _sender = await Host.CreateDefaultBuilder() .UseWolverine(opts => { - opts.UseKafka("localhost:29092").AutoProvision(); + opts.UseKafka("localhost:9092").AutoProvision(); opts.Policies.DisableConventionalLocalRouting(); opts.Services.AddResourceSetupOnStartup(); @@ -34,7 +34,7 @@ public async Task InitializeAsync() _receiver = await Host.CreateDefaultBuilder() .UseWolverine(opts => { - opts.UseKafka("localhost:29092").AutoProvision(); + opts.UseKafka("localhost:9092").AutoProvision(); opts.ListenToKafkaTopic("incoming.one"); opts.Services.AddResourceSetupOnStartup(); diff --git a/src/Transports/Kafka/Wolverine.Kafka.Tests/broadcast_to_topic_rules.cs b/src/Transports/Kafka/Wolverine.Kafka.Tests/broadcast_to_topic_rules.cs index e42f3ee54..d39d4065e 100644 --- a/src/Transports/Kafka/Wolverine.Kafka.Tests/broadcast_to_topic_rules.cs +++ b/src/Transports/Kafka/Wolverine.Kafka.Tests/broadcast_to_topic_rules.cs @@ -25,7 +25,7 @@ public async Task InitializeAsync() _receiver = await Host.CreateDefaultBuilder() .UseWolverine(opts => { - opts.UseKafka("localhost:29092").AutoProvision(); + opts.UseKafka("localhost:9092").AutoProvision(); opts.ListenToKafkaTopic("red"); opts.ListenToKafkaTopic("green"); opts.ListenToKafkaTopic("blue"); @@ -40,7 +40,7 @@ public async Task InitializeAsync() _sender = await Host.CreateDefaultBuilder() .UseWolverine(opts => { - opts.UseKafka("localhost:29092").AutoProvision(); + opts.UseKafka("localhost:9092").AutoProvision(); opts.Policies.DisableConventionalLocalRouting(); opts.PublishAllMessages().ToKafkaTopics(); diff --git a/src/Transports/Kafka/Wolverine.Kafka.Tests/compliance.cs b/src/Transports/Kafka/Wolverine.Kafka.Tests/compliance.cs index d0589965e..a8aa2540b 100644 --- a/src/Transports/Kafka/Wolverine.Kafka.Tests/compliance.cs +++ b/src/Transports/Kafka/Wolverine.Kafka.Tests/compliance.cs @@ -19,7 +19,7 @@ public async Task InitializeAsync() await ReceiverIs(opts => { - opts.UseKafka("localhost:29092"); + opts.UseKafka("localhost:9092"); opts.ListenToKafkaTopic(receiverTopic).Named("receiver").BufferedInMemory(); @@ -28,7 +28,7 @@ await ReceiverIs(opts => await SenderIs(opts => { - opts.UseKafka("localhost:29092").ConfigureConsumers(x => x.EnableAutoCommit = false); + opts.UseKafka("localhost:9092").ConfigureConsumers(x => x.EnableAutoCommit = false); opts.ListenToKafkaTopic(senderTopic); @@ -44,7 +44,6 @@ await SenderIs(opts => } } -[Collection("acceptance")] public class BufferedSendingAndReceivingCompliance : TransportCompliance; public class InlineComplianceFixture : TransportComplianceFixture, IAsyncLifetime @@ -64,7 +63,7 @@ public async Task InitializeAsync() await SenderIs(opts => { - opts.UseKafka("localhost:29092").AutoProvision(); + opts.UseKafka("localhost:9092").AutoProvision(); opts.ListenToKafkaTopic(senderTopic).UseForReplies(); @@ -75,7 +74,7 @@ await SenderIs(opts => await ReceiverIs(opts => { - opts.UseKafka("localhost:29092").AutoProvision(); + opts.UseKafka("localhost:9092").AutoProvision(); opts.ListenToKafkaTopic(receiverTopic).Named("receiver").ProcessInline(); @@ -89,5 +88,4 @@ await ReceiverIs(opts => } } -[Collection("acceptance")] public class InlineSendingAndReceivingCompliance : TransportCompliance; \ No newline at end of file diff --git a/src/Transports/Kafka/Wolverine.Kafka.Tests/publish_and_receive_raw_json.cs b/src/Transports/Kafka/Wolverine.Kafka.Tests/publish_and_receive_raw_json.cs index 329a4ffac..258da13fc 100644 --- a/src/Transports/Kafka/Wolverine.Kafka.Tests/publish_and_receive_raw_json.cs +++ b/src/Transports/Kafka/Wolverine.Kafka.Tests/publish_and_receive_raw_json.cs @@ -17,7 +17,7 @@ public async Task InitializeAsync() _receiver = await Host.CreateDefaultBuilder() .UseWolverine(opts => { - opts.UseKafka("localhost:29092").AutoProvision(); + opts.UseKafka("localhost:9092").AutoProvision(); opts.ListenToKafkaTopic("json") .ReceiveRawJson(); @@ -27,7 +27,7 @@ public async Task InitializeAsync() _sender = await Host.CreateDefaultBuilder() .UseWolverine(opts => { - opts.UseKafka("localhost:29092").AutoProvision(); + opts.UseKafka("localhost:9092").AutoProvision(); opts.Policies.DisableConventionalLocalRouting(); opts.Services.AddResourceSetupOnStartup(); diff --git a/src/Transports/MQTT/Wolverine.MQTT.Tests/ack_smoke_tests.cs b/src/Transports/MQTT/Wolverine.MQTT.Tests/ack_smoke_tests.cs index 51190ecb2..f8bbb28ee 100644 --- a/src/Transports/MQTT/Wolverine.MQTT.Tests/ack_smoke_tests.cs +++ b/src/Transports/MQTT/Wolverine.MQTT.Tests/ack_smoke_tests.cs @@ -53,7 +53,7 @@ public async Task InitializeAsync() [Fact] public async Task send_zero_message() { - var bus = _sender.Services.GetRequiredService(); + var bus = _sender.MessageBus(); await bus.BroadcastToTopicAsync("red", new ZeroMessage("Zero")); await Task.Delay(2.Seconds()); @@ -62,7 +62,7 @@ public async Task send_zero_message() [Fact] public async Task send_ack_message() { - var bus = _sender.Services.GetRequiredService(); + var bus = _sender.MessageBus(); await bus.BroadcastToTopicAsync("red", new TriggerZero("red")); await Task.Delay(2.Seconds()); From ac947f4e0188049a3b3bdf3f2f8087325c93db8c Mon Sep 17 00:00:00 2001 From: "Jeremy D. Miller" Date: Sun, 13 Oct 2024 13:28:51 -0500 Subject: [PATCH 3/4] Fix for AWS SQS test --- .../Bugs/disabling_dead_letter_queue.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Transports/AWS/Wolverine.AmazonSqs.Tests/Bugs/disabling_dead_letter_queue.cs b/src/Transports/AWS/Wolverine.AmazonSqs.Tests/Bugs/disabling_dead_letter_queue.cs index 923f829c0..c35d754b5 100644 --- a/src/Transports/AWS/Wolverine.AmazonSqs.Tests/Bugs/disabling_dead_letter_queue.cs +++ b/src/Transports/AWS/Wolverine.AmazonSqs.Tests/Bugs/disabling_dead_letter_queue.cs @@ -67,7 +67,7 @@ public async Task no_seriously_do_not_create_dlq() .UseWolverine(options => { options.PersistMessagesWithPostgresql(Servers.PostgresConnectionString); - options.UseAmazonSqsTransportLocally(); + options.UseAmazonSqsTransportLocally().DisableAllNativeDeadLetterQueues().AutoProvision(); options.Durability.Mode = DurabilityMode.Solo; From 78bc676942d8718213493ddf8322ac018b059c25 Mon Sep 17 00:00:00 2001 From: "Jeremy D. Miller" Date: Sun, 13 Oct 2024 13:55:19 -0500 Subject: [PATCH 4/4] Pulsar docs and Nuget publishing. Closes GH-1066 --- build/build.cs | 492 +++++++++--------- docs/guide/messaging/transports/kafka.md | 1 - docs/guide/messaging/transports/pulsar.md | 26 +- .../DocumentationSamples.cs | 41 ++ .../Wolverine.Pulsar/Wolverine.Pulsar.csproj | 10 +- 5 files changed, 314 insertions(+), 256 deletions(-) create mode 100644 src/Transports/Pulsar/Wolverine.Pulsar.Tests/DocumentationSamples.cs diff --git a/build/build.cs b/build/build.cs index eb1c0f920..39cd41caf 100644 --- a/build/build.cs +++ b/build/build.cs @@ -1,322 +1,308 @@ -using System; -using System.IO; -using System.Linq; using System.Reflection; using System.Runtime.Versioning; using System.Text.RegularExpressions; -using System.Threading; using IntegrationTests; using Npgsql; using static System.Globalization.CultureInfo; using static Bullseye.Targets; using static SimpleExec.Command; -namespace build +namespace build; + +internal class Build { - internal class Build + private static void Main(string[] args) { - private static void Main(string[] args) + Target("default", DependsOn("test-core", "test-policy", "test-extensions", "test-http", "commands")); + + Target("restore", () => { Run("dotnet", "restore wolverine.sln"); }); + + Target("compile", DependsOn("restore"), () => { + Run("dotnet", + "build wolverine.sln --no-restore --framework net8.0"); + }); - Target("default", DependsOn("test-core", "test-policy", "test-extensions", "test-http", "commands")); + Target("clean", () => { Run("dotnet", "clean wolverine.sln --framework net8.0"); }); - Target("restore", () => - { - Run("dotnet", "restore wolverine.sln"); - }); + TestTarget("test-core", "CoreTests"); + TestTarget("test-policy", "PolicyTests"); - Target("compile", DependsOn("restore"),() => - { - Run("dotnet", - $"build wolverine.sln --no-restore --framework net8.0"); - }); + Target("test-extensions", DependsOn("compile"), () => + { + RunTests("Extensions", "Wolverine.FluentValidation.Te" + + "sts"); + RunTests("Extensions", "Wolverine.MemoryPack.Tests"); + RunTests("Extensions", "Wolverine.MessagePack.Tests"); + }); - Target("clean",() => - { - Run("dotnet", "clean wolverine.sln --framework net8.0"); - }); - - TestTarget("test-core", "CoreTests"); - TestTarget("test-policy", "PolicyTests"); + IntegrationTestTarget("test-http", "Http", "Wolverine.Http.Tests"); - Target("test-extensions", DependsOn("compile"),() => - { - RunTests("Extensions", "Wolverine.FluentValidation.Te" + - "sts"); - RunTests("Extensions", "Wolverine.MemoryPack.Tests"); - RunTests("Extensions", "Wolverine.MessagePack.Tests"); - }); - - IntegrationTestTarget("test-http", "Http", "Wolverine.Http.Tests"); + IntegrationTestTarget("test-persistence", "Persistence", "PersistenceTests"); - IntegrationTestTarget("test-persistence", "Persistence", "PersistenceTests"); + IntegrationTestTarget("test-rabbit", "Transports", "RabbitMQ", "Wolverine.RabbitMQ.Tests"); - IntegrationTestTarget("test-rabbit", "Transports", "RabbitMQ", "Wolverine.RabbitMQ.Tests"); + IntegrationTestTarget("test-pulsar", "Transports", "Wolverine.Pulsar.Tests"); - IntegrationTestTarget("test-pulsar", "Transports", "Wolverine.Pulsar.Tests"); + Target("test-samples", DependsOn("compile", "docker-up"), () => + { + RunTests("samples", "TodoWebService", "TodoWebServiceTests"); + RunTests("samples", "TestHarness", "BankingService.Tests"); + RunTests("samples", "Middleware", "AppWithMiddleware.Tests"); + RunTests("samples", "EFCoreSample", "ItemService.Tests"); + }); - Target("test-samples", DependsOn("compile", "docker-up"), () => - { - RunTests("samples", "TodoWebService", "TodoWebServiceTests"); - RunTests("samples", "TestHarness", "BankingService.Tests"); - RunTests("samples", "Middleware", "AppWithMiddleware.Tests"); - RunTests("samples", "EFCoreSample", "ItemService.Tests"); - }); + Target("full", DependsOn("default", "test-persistence", "test-rabbit", "test-pulsar"), + () => { Console.WriteLine("Look Ma, I'm running full!"); }); - Target("full", DependsOn("default", "test-persistence", "test-rabbit", "test-pulsar"), () => - { - Console.WriteLine("Look Ma, I'm running full!"); - }); + Target("commands", DependsOn("compile"), () => + { + var original = Directory.GetCurrentDirectory(); - Target("commands", DependsOn("compile"),() => - { - var original = Directory.GetCurrentDirectory(); - - /* - Dir.chdir("src/Subscriber") do - sh "dotnet run -- ?" - sh "dotnet run -- export-json-schema obj/schema" - end - */ - - Directory.SetCurrentDirectory(Path.Combine(original, "src", "Testing", "ConsoleApp")); - RunCurrentProject("?"); - RunCurrentProject("describe"); - - Directory.SetCurrentDirectory(Path.Combine(original, "src", "Http", "WolverineWebApi")); - RunCurrentProject("codegen preview"); - - Directory.SetCurrentDirectory(original); - }); - - Target("ci", DependsOn("test-core")); - - Target("install", () => - RunNpm("install")); - - Target("install-mdsnippets", IgnoreIfFailed(() => - Run("dotnet", $"tool install -g MarkdownSnippets.Tool") - )); - - Target("docs", DependsOn("install", "install-mdsnippets"), () => { - // Run docs site - RunNpm("run docs"); - }); - - Target("docs-build", DependsOn("install", "install-mdsnippets"), () => { - // Run docs site - RunNpm("run docs:build"); - }); - - Target("publish-docs", DependsOn("docs-build"), () => - Run("npm", "run docs:publish")); - - Target("clear-inline-samples", () => { - var files = Directory.GetFiles("./docs", "*.md", SearchOption.AllDirectories); - var pattern = @"[\s\S]*?"; - var replacePattern = $"{Environment.NewLine}"; - foreach (var file in files) - { - // Console.WriteLine(file); - var content = File.ReadAllText(file); + /* +Dir.chdir("src/Subscriber") do +sh "dotnet run -- ?" +sh "dotnet run -- export-json-schema obj/schema" +end + */ - if (!content.Contains("[\s\S]*?"; + var replacePattern = $"{Environment.NewLine}"; + foreach (var file in files) { - RunTests(testTarget); - }); - } - - public static void IntegrationTestTarget(string taskName, params string[] testTarget) + // Console.WriteLine(file); + var content = File.ReadAllText(file); + + if (!content.Contains("