From 66e08ac2a48d118c038312b88d7131ed3d622d92 Mon Sep 17 00:00:00 2001 From: "Jeremy D. Miller" Date: Wed, 11 Mar 2026 07:55:02 -0500 Subject: [PATCH] Remove NServiceBus shim interfaces from Wolverine Remove all code in the Wolverine.Shims.NServiceBus namespace including IHandleMessages, IMessageSession, IEndpointInstance, IMessageHandlerContext, IUniformSession, ITransactionalSession, and their Wolverine implementations. Also removes the MessageHandlerContextVariableSource code generation hook, all NServiceBus shim tests, and shim documentation from the migration guide. Wire-protocol interop (UseNServiceBusInterop) is preserved as it serves a different purpose. Co-Authored-By: Claude Opus 4.6 --- docs/guide/migrating-to-wolverine.md | 123 ----- .../CoreTests/Shims/nservicebus_end_to_end.cs | 138 ----- .../CoreTests/Shims/nservicebus_shim_tests.cs | 470 ------------------ .../Shims/NServiceBus/ExtendableOptions.cs | 50 -- .../Shims/NServiceBus/IEndpointInstance.cs | 15 - .../Shims/NServiceBus/IHandleMessages.cs | 17 - .../NServiceBus/IMessageHandlerContext.cs | 57 --- .../Shims/NServiceBus/IMessageSession.cs | 20 - .../NServiceBus/ITransactionalSession.cs | 22 - .../Shims/NServiceBus/IUniformSession.cs | 21 - .../MessageHandlerContextVariableSource.cs | 51 -- .../NServiceBus/NServiceBusShimExtensions.cs | 36 -- .../Shims/NServiceBus/PublishOptions.cs | 9 - .../Shims/NServiceBus/ReplyOptions.cs | 9 - .../Shims/NServiceBus/SendOptions.cs | 62 --- .../NServiceBus/WolverineEndpointInstance.cs | 44 -- .../WolverineMessageHandlerContext.cs | 60 --- .../NServiceBus/WolverineMessageSession.cs | 35 -- .../WolverineTransactionalSession.cs | 50 -- .../NServiceBus/WolverineUniformSession.cs | 35 -- src/Wolverine/WolverineOptions.cs | 3 - 21 files changed, 1327 deletions(-) delete mode 100644 src/Testing/CoreTests/Shims/nservicebus_end_to_end.cs delete mode 100644 src/Testing/CoreTests/Shims/nservicebus_shim_tests.cs delete mode 100644 src/Wolverine/Shims/NServiceBus/ExtendableOptions.cs delete mode 100644 src/Wolverine/Shims/NServiceBus/IEndpointInstance.cs delete mode 100644 src/Wolverine/Shims/NServiceBus/IHandleMessages.cs delete mode 100644 src/Wolverine/Shims/NServiceBus/IMessageHandlerContext.cs delete mode 100644 src/Wolverine/Shims/NServiceBus/IMessageSession.cs delete mode 100644 src/Wolverine/Shims/NServiceBus/ITransactionalSession.cs delete mode 100644 src/Wolverine/Shims/NServiceBus/IUniformSession.cs delete mode 100644 src/Wolverine/Shims/NServiceBus/MessageHandlerContextVariableSource.cs delete mode 100644 src/Wolverine/Shims/NServiceBus/NServiceBusShimExtensions.cs delete mode 100644 src/Wolverine/Shims/NServiceBus/PublishOptions.cs delete mode 100644 src/Wolverine/Shims/NServiceBus/ReplyOptions.cs delete mode 100644 src/Wolverine/Shims/NServiceBus/SendOptions.cs delete mode 100644 src/Wolverine/Shims/NServiceBus/WolverineEndpointInstance.cs delete mode 100644 src/Wolverine/Shims/NServiceBus/WolverineMessageHandlerContext.cs delete mode 100644 src/Wolverine/Shims/NServiceBus/WolverineMessageSession.cs delete mode 100644 src/Wolverine/Shims/NServiceBus/WolverineTransactionalSession.cs delete mode 100644 src/Wolverine/Shims/NServiceBus/WolverineUniformSession.cs diff --git a/docs/guide/migrating-to-wolverine.md b/docs/guide/migrating-to-wolverine.md index b34cbca67..610fc61cf 100644 --- a/docs/guide/migrating-to-wolverine.md +++ b/docs/guide/migrating-to-wolverine.md @@ -688,129 +688,6 @@ opts.Policies.RegisterInteropMessageAssembly(typeof(SharedMessages).Assembly); Wolverine detects message types from standard NServiceBus headers. You may need [message type aliases](/guide/messages#message-type-name-or-alias) to bridge naming differences. See the full [interoperability guide](/tutorials/interop#interop-with-nservicebus). -### NServiceBus Shim Interfaces - -Wolverine provides shim interfaces in the `Wolverine.Shims.NServiceBus` namespace that mimic the core NServiceBus -API surface while delegating to Wolverine's `IMessageBus` and `IMessageContext` under the hood. These shims let -you migrate handler code incrementally without rewriting every handler signature at once. - -::: tip -The shim interfaces are included in the core Wolverine NuGet package -- no additional packages are needed. -While these shims ease migration, the Wolverine team recommends eventually moving to Wolverine's native -convention-based handlers and pure function style for the best developer experience. -::: - -#### Automatic Handler Discovery - -Wolverine automatically discovers classes implementing `IHandleMessages` during its normal -[handler discovery](/guide/handlers/discovery) assembly scanning -- no explicit registration is needed. -The `IMessageHandlerContext` parameter in `Handle(T message, IMessageHandlerContext context)` is -automatically resolved via Wolverine's built-in code generation. - -Just make sure the assembly containing your `IHandleMessages` implementations is included in -Wolverine's discovery. By default, Wolverine scans the application assembly and any assemblies -explicitly added via `opts.Discovery.IncludeAssembly()`. See the -[handler discovery documentation](/guide/handlers/discovery) for more details on controlling which -assemblies are scanned. - -#### DI Registration for Non-Handler Interfaces - -If you need to inject NServiceBus shim interfaces (`IMessageSession`, `IEndpointInstance`, -`IUniformSession`, `ITransactionalSession`) into services outside of message handlers via -constructor injection, register them with: - -```csharp -builder.Host.UseWolverine(opts => -{ - opts.UseNServiceBusShims(); - - // Your Wolverine configuration... -}); -``` - -#### Available Interfaces - -| NServiceBus Shim | Delegates To | Purpose | -|-----------------|-------------|---------| -| `IMessageSession` | `IMessageBus` | Send/Publish outside of handlers | -| `IEndpointInstance` | `IMessageBus` + `IHost` | Running endpoint with lifecycle | -| `IMessageHandlerContext` | `IMessageContext` | Send/Publish/Reply inside handlers | -| `IUniformSession` | `IMessageBus` | Unified Send/Publish (inside or outside handlers) | -| `ITransactionalSession` | `IMessageBus` | Transactional Send/Publish (Open/Commit are obsolete) | -| `IHandleMessages` | `IWolverineHandler` | Handler discovery marker | - -#### Using IHandleMessages\ - -The `IHandleMessages` shim extends `IWolverineHandler`, so implementing it automatically registers your -handler with Wolverine's handler discovery: - -```csharp -using Wolverine.Shims.NServiceBus; - -// This handler is discovered by Wolverine via the IWolverineHandler marker -public class OrderHandler : IHandleMessages -{ - public async Task Handle(PlaceOrder message, IMessageHandlerContext context) - { - // context.Send, context.Publish, context.Reply all delegate to Wolverine - await context.Publish(new OrderPlaced(message.OrderId)); - await context.Reply(new PlaceOrderResponse { Success = true }); - } -} -``` - -#### Using IMessageSession / IEndpointInstance - -Inject `IMessageSession` or `IEndpointInstance` to send and publish messages outside of handlers: - -```csharp -using Wolverine.Shims.NServiceBus; - -public class OrderController : ControllerBase -{ - private readonly IMessageSession _session; - - public OrderController(IMessageSession session) => _session = session; - - [HttpPost] - public async Task PlaceOrder(PlaceOrderRequest request) - { - await _session.Send(new PlaceOrder(request.OrderId)); - return Accepted(); - } -} -``` - -#### NServiceBus-Style Options - -The shims include `SendOptions`, `PublishOptions`, and `ReplyOptions` classes that map to Wolverine's -`DeliveryOptions`: - -```csharp -var options = new SendOptions(); -options.SetDestination("remote-endpoint"); // routes to a named endpoint -options.SetHeader("tenant-id", "acme"); // adds a header -options.DelayDeliveryWith(TimeSpan.FromMinutes(5)); // schedules delivery - -await session.Send(new PlaceOrder("ABC-123"), options); -``` - -#### ITransactionalSession - -`ITransactionalSession` delegates `Send` and `Publish` to `IMessageBus`. The `Open()` and `Commit()` -lifecycle methods are marked `[Obsolete]` and throw `NotSupportedException` because Wolverine handles -transactional messaging automatically via its built-in [outbox](/guide/durability/): - -```csharp -// These methods are obsolete -- just delete the calls -// session.Open(); // throws NotSupportedException -// session.Commit(); // throws NotSupportedException - -// Send and Publish work normally -await session.Send(new PlaceOrder("ABC-123")); -await session.Publish(new OrderPlaced("ABC-123")); -``` - ### Migration Checklist **Phase 1: Coexistence** diff --git a/src/Testing/CoreTests/Shims/nservicebus_end_to_end.cs b/src/Testing/CoreTests/Shims/nservicebus_end_to_end.cs deleted file mode 100644 index c667150af..000000000 --- a/src/Testing/CoreTests/Shims/nservicebus_end_to_end.cs +++ /dev/null @@ -1,138 +0,0 @@ -using JasperFx.Core.Reflection; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Wolverine.ComplianceTests; -using Wolverine.Runtime.Handlers; -using Wolverine.Shims.NServiceBus; -using Wolverine.Tracking; -using Xunit; -using Xunit.Abstractions; - -namespace CoreTests.Shims; - -public class nservicebus_end_to_end : IAsyncLifetime -{ - private readonly ITestOutputHelper _output; - private IHost _host = null!; - - public nservicebus_end_to_end(ITestOutputHelper output) - { - _output = output; - } - - public async Task InitializeAsync() - { - _host = await Host.CreateDefaultBuilder() - .UseWolverine(opts => - { - opts.UseNServiceBusShims(); - - opts.IncludeType(); - opts.IncludeType(); - }) - .StartAsync(); - } - - public async Task DisposeAsync() - { - await _host.StopAsync(); - _host.Dispose(); - } - - [Fact] - public async Task handler_handles_message_and_publishes_cascading_event() - { - NsbSubmitOrderHandler.Reset(); - NsbOrderSubmittedCascadeHandler.Reset(); - - var session = await _host.InvokeMessageAndWaitAsync(new NsbSubmitOrder("ORD-101")); - - NsbSubmitOrderHandler.LastOrderId.ShouldBe("ORD-101"); - NsbOrderSubmittedCascadeHandler.LastOrderId.ShouldBe("ORD-101"); - } - - [Fact] - public async Task handler_receives_message_handler_context() - { - NsbSubmitOrderHandler.Reset(); - - await _host.InvokeMessageAndWaitAsync(new NsbSubmitOrder("ORD-102")); - - NsbSubmitOrderHandler.LastOrderId.ShouldBe("ORD-102"); - NsbSubmitOrderHandler.ReceivedContext.ShouldBeTrue(); - } - - [Fact] - public void print_generated_code_for_handler() - { - // Force code generation by resolving the handler - _host.GetRuntime().Handlers.HandlerFor(); - - var graph = _host.Services.GetRequiredService(); - var chain = graph.ChainFor(); - chain.ShouldNotBeNull(); - - _output.WriteLine("=== Generated Code for NsbSubmitOrder (NServiceBus IHandleMessages) ==="); - _output.WriteLine(chain.SourceCode); - } - - [Fact] - public void print_generated_code_for_cascaded_handler() - { - // Force code generation by resolving the handler - _host.GetRuntime().Handlers.HandlerFor(); - - var graph = _host.Services.GetRequiredService(); - var chain = graph.ChainFor(); - chain.ShouldNotBeNull(); - - _output.WriteLine("=== Generated Code for NsbOrderSubmitted cascade handler ==="); - _output.WriteLine(chain.SourceCode); - } -} - -// --- NServiceBus shim message types --- - -public record NsbSubmitOrder(string OrderId); - -public record NsbOrderSubmitted(string OrderId); - -// --- NServiceBus IHandleMessages handler --- - -public class NsbSubmitOrderHandler : IHandleMessages -{ - public static string? LastOrderId; - public static bool ReceivedContext; - - public static void Reset() - { - LastOrderId = null; - ReceivedContext = false; - } - - public async Task Handle(NsbSubmitOrder message, IMessageHandlerContext context) - { - LastOrderId = message.OrderId; - ReceivedContext = true; - - // Publish a cascading event via the IMessageHandlerContext - await context.Publish(new NsbOrderSubmitted(message.OrderId)); - } -} - -// --- Handler for the cascaded event --- - -public class NsbOrderSubmittedCascadeHandler -{ - public static string? LastOrderId; - - public static void Reset() - { - LastOrderId = null; - } - - public void Handle(NsbOrderSubmitted message) - { - LastOrderId = message.OrderId; - } -} diff --git a/src/Testing/CoreTests/Shims/nservicebus_shim_tests.cs b/src/Testing/CoreTests/Shims/nservicebus_shim_tests.cs deleted file mode 100644 index 33d2bf02c..000000000 --- a/src/Testing/CoreTests/Shims/nservicebus_shim_tests.cs +++ /dev/null @@ -1,470 +0,0 @@ -using NSubstitute; -using Wolverine.Shims.NServiceBus; -using Xunit; - -namespace CoreTests.Shims; - -public class nservicebus_options_tests -{ - [Fact] - public void send_options_sets_headers() - { - var options = new SendOptions(); - options.SetHeader("key1", "value1"); - options.SetHeader("key2", "value2"); - - var delivery = options.ToDeliveryOptions(); - - delivery.Headers["key1"].ShouldBe("value1"); - delivery.Headers["key2"].ShouldBe("value2"); - } - - [Fact] - public void send_options_sets_destination() - { - var options = new SendOptions(); - options.SetDestination("my-endpoint"); - - options.Destination.ShouldBe("my-endpoint"); - } - - [Fact] - public void send_options_delay_delivery() - { - var options = new SendOptions(); - options.DelayDeliveryWith(TimeSpan.FromMinutes(5)); - - var delivery = options.ToDeliveryOptions(); - - delivery.ScheduleDelay.ShouldBe(TimeSpan.FromMinutes(5)); - delivery.ScheduledTime.ShouldBeNull(); - } - - [Fact] - public void send_options_do_not_deliver_before() - { - var scheduledTime = DateTimeOffset.UtcNow.AddHours(1); - var options = new SendOptions(); - options.DoNotDeliverBefore(scheduledTime); - - var delivery = options.ToDeliveryOptions(); - - delivery.ScheduledTime.ShouldBe(scheduledTime); - delivery.ScheduleDelay.ShouldBeNull(); - } - - [Fact] - public void send_options_delay_clears_scheduled_time() - { - var options = new SendOptions(); - options.DoNotDeliverBefore(DateTimeOffset.UtcNow.AddHours(1)); - options.DelayDeliveryWith(TimeSpan.FromMinutes(5)); - - var delivery = options.ToDeliveryOptions(); - - delivery.ScheduleDelay.ShouldBe(TimeSpan.FromMinutes(5)); - delivery.ScheduledTime.ShouldBeNull(); - } - - [Fact] - public void publish_options_sets_headers() - { - var options = new PublishOptions(); - options.SetHeader("event-type", "created"); - - var delivery = options.ToDeliveryOptions(); - - delivery.Headers["event-type"].ShouldBe("created"); - } - - [Fact] - public void reply_options_sets_headers() - { - var options = new ReplyOptions(); - options.SetHeader("reply-key", "reply-value"); - - var delivery = options.ToDeliveryOptions(); - - delivery.Headers["reply-key"].ShouldBe("reply-value"); - } - - [Fact] - public void get_headers_returns_empty_when_none_set() - { - var options = new SendOptions(); - options.GetHeaders().Count.ShouldBe(0); - } -} - -public class wolverine_message_session_tests -{ - private readonly IMessageBus _bus; - private readonly WolverineMessageSession _session; - - public wolverine_message_session_tests() - { - _bus = Substitute.For(); - _session = new WolverineMessageSession(_bus); - } - - [Fact] - public async Task send_delegates_to_bus_send_async() - { - var message = new TestNsbCommand("hello"); - - await _session.Send(message); - - await _bus.Received(1).SendAsync(message, null); - } - - [Fact] - public async Task send_with_options_delegates_with_delivery_options() - { - var message = new TestNsbCommand("hello"); - var options = new SendOptions(); - options.SetHeader("key", "value"); - - await _session.Send(message, options); - - await _bus.Received(1).SendAsync(message, - Arg.Is(d => d.Headers["key"] == "value")); - } - - [Fact] - public async Task send_with_destination_uses_endpoint() - { - var message = new TestNsbCommand("hello"); - var options = new SendOptions(); - options.SetDestination("remote-endpoint"); - - var endpoint = Substitute.For(); - _bus.EndpointFor("remote-endpoint").Returns(endpoint); - - await _session.Send(message, options); - - await endpoint.Received(1).SendAsync(message, Arg.Any()); - await _bus.DidNotReceive().SendAsync(Arg.Any(), Arg.Any()); - } - - [Fact] - public async Task publish_delegates_to_bus_publish_async() - { - var message = new TestNsbEvent("created"); - - await _session.Publish(message); - - await _bus.Received(1).PublishAsync(message, null); - } - - [Fact] - public async Task publish_with_options_delegates_with_delivery_options() - { - var message = new TestNsbEvent("created"); - var options = new PublishOptions(); - options.SetHeader("event-source", "test"); - - await _session.Publish(message, options); - - await _bus.Received(1).PublishAsync(message, - Arg.Is(d => d.Headers["event-source"] == "test")); - } -} - -public class wolverine_endpoint_instance_tests -{ - private readonly IMessageBus _bus; - private readonly Microsoft.Extensions.Hosting.IHost _host; - private readonly WolverineEndpointInstance _instance; - - public wolverine_endpoint_instance_tests() - { - _bus = Substitute.For(); - _host = Substitute.For(); - _instance = new WolverineEndpointInstance(_bus, _host); - } - - [Fact] - public async Task send_delegates_to_bus() - { - var message = new TestNsbCommand("hello"); - - await _instance.Send(message); - - await _bus.Received(1).SendAsync(message, null); - } - - [Fact] - public async Task publish_delegates_to_bus() - { - var message = new TestNsbEvent("created"); - - await _instance.Publish(message); - - await _bus.Received(1).PublishAsync(message, null); - } - - [Fact] - public async Task stop_delegates_to_host() - { - await _instance.Stop(); - - await _host.Received(1).StopAsync(Arg.Any()); - } - - [Fact] - public async Task send_with_destination_uses_endpoint() - { - var message = new TestNsbCommand("hello"); - var options = new SendOptions(); - options.SetDestination("remote"); - - var endpoint = Substitute.For(); - _bus.EndpointFor("remote").Returns(endpoint); - - await _instance.Send(message, options); - - await endpoint.Received(1).SendAsync(message, Arg.Any()); - } -} - -public class wolverine_message_handler_context_tests -{ - private readonly IMessageContext _context; - private readonly WolverineMessageHandlerContext _handlerContext; - - public wolverine_message_handler_context_tests() - { - _context = Substitute.For(); - _handlerContext = new WolverineMessageHandlerContext(_context); - } - - [Fact] - public void message_id_returns_envelope_id() - { - var envelope = new Envelope { Id = Guid.Parse("12345678-1234-1234-1234-123456789012") }; - _context.Envelope.Returns(envelope); - - _handlerContext.MessageId.ShouldBe("12345678-1234-1234-1234-123456789012"); - } - - [Fact] - public void message_id_returns_empty_when_no_envelope() - { - _context.Envelope.Returns((Envelope?)null); - - _handlerContext.MessageId.ShouldBe(string.Empty); - } - - [Fact] - public void reply_to_address_returns_envelope_reply_uri() - { - var envelope = new Envelope { ReplyUri = new Uri("tcp://localhost:1234") }; - _context.Envelope.Returns(envelope); - - _handlerContext.ReplyToAddress.ShouldStartWith("tcp://localhost:1234"); - } - - [Fact] - public void reply_to_address_returns_null_when_no_reply_uri() - { - var envelope = new Envelope(); - _context.Envelope.Returns(envelope); - - _handlerContext.ReplyToAddress.ShouldBeNull(); - } - - [Fact] - public void message_headers_returns_envelope_headers() - { - var envelope = new Envelope(); - envelope.Headers["key1"] = "value1"; - _context.Envelope.Returns(envelope); - - _handlerContext.MessageHeaders["key1"].ShouldBe("value1"); - } - - [Fact] - public void message_headers_returns_empty_when_no_envelope() - { - _context.Envelope.Returns((Envelope?)null); - - _handlerContext.MessageHeaders.Count.ShouldBe(0); - } - - [Fact] - public void correlation_id_delegates_to_context() - { - _context.CorrelationId.Returns("my-correlation-id"); - - _handlerContext.CorrelationId.ShouldBe("my-correlation-id"); - } - - [Fact] - public async Task send_delegates_to_context_send_async() - { - var message = new TestNsbCommand("hello"); - - await _handlerContext.Send(message); - - await _context.Received(1).SendAsync(message, null); - } - - [Fact] - public async Task send_with_destination_uses_endpoint() - { - var message = new TestNsbCommand("hello"); - var options = new SendOptions(); - options.SetDestination("remote"); - - var endpoint = Substitute.For(); - _context.EndpointFor("remote").Returns(endpoint); - - await _handlerContext.Send(message, options); - - await endpoint.Received(1).SendAsync(message, Arg.Any()); - } - - [Fact] - public async Task publish_delegates_to_context_publish_async() - { - var message = new TestNsbEvent("created"); - - await _handlerContext.Publish(message); - - await _context.Received(1).PublishAsync(message, null); - } - - [Fact] - public async Task reply_delegates_to_respond_to_sender() - { - var message = new TestNsbResponse("ok"); - - await _handlerContext.Reply(message); - - await _context.Received(1).RespondToSenderAsync(message); - } - - [Fact] - public async Task forward_current_message_sends_to_destination() - { - var originalMessage = new TestNsbCommand("forward-me"); - var envelope = new Envelope(originalMessage); - _context.Envelope.Returns(envelope); - - var endpoint = Substitute.For(); - _context.EndpointFor("other-endpoint").Returns(endpoint); - - await _handlerContext.ForwardCurrentMessageTo("other-endpoint"); - - await endpoint.Received(1).SendAsync(originalMessage, Arg.Any()); - } - - [Fact] - public async Task forward_current_message_throws_when_no_envelope() - { - _context.Envelope.Returns((Envelope?)null); - - await Should.ThrowAsync(() => - _handlerContext.ForwardCurrentMessageTo("other-endpoint")); - } -} - -public class wolverine_uniform_session_tests -{ - private readonly IMessageBus _bus; - private readonly WolverineUniformSession _session; - - public wolverine_uniform_session_tests() - { - _bus = Substitute.For(); - _session = new WolverineUniformSession(_bus); - } - - [Fact] - public async Task send_delegates_to_bus() - { - var message = new TestNsbCommand("hello"); - - await _session.Send(message); - - await _bus.Received(1).SendAsync(message, null); - } - - [Fact] - public async Task publish_delegates_to_bus() - { - var message = new TestNsbEvent("created"); - - await _session.Publish(message); - - await _bus.Received(1).PublishAsync(message, null); - } - - [Fact] - public async Task send_with_destination_uses_endpoint() - { - var message = new TestNsbCommand("hello"); - var options = new SendOptions(); - options.SetDestination("target"); - - var endpoint = Substitute.For(); - _bus.EndpointFor("target").Returns(endpoint); - - await _session.Send(message, options); - - await endpoint.Received(1).SendAsync(message, Arg.Any()); - } -} - -public class wolverine_transactional_session_tests -{ - private readonly IMessageBus _bus; - private readonly WolverineTransactionalSession _session; - - public wolverine_transactional_session_tests() - { - _bus = Substitute.For(); - _session = new WolverineTransactionalSession(_bus); - } - - [Fact] - public async Task send_delegates_to_bus() - { - var message = new TestNsbCommand("hello"); - - await _session.Send(message); - - await _bus.Received(1).SendAsync(message, null); - } - - [Fact] - public async Task publish_delegates_to_bus() - { - var message = new TestNsbEvent("created"); - - await _session.Publish(message); - - await _bus.Received(1).PublishAsync(message, null); - } - - [Fact] - public async Task open_throws_not_supported() - { -#pragma warning disable CS0618 // Obsolete - await Should.ThrowAsync(() => _session.Open()); -#pragma warning restore CS0618 - } - - [Fact] - public async Task commit_throws_not_supported() - { -#pragma warning disable CS0618 // Obsolete - await Should.ThrowAsync(() => _session.Commit()); -#pragma warning restore CS0618 - } -} - -// Test message types -public record TestNsbCommand(string Data); -public record TestNsbEvent(string Data); -public record TestNsbResponse(string Data); diff --git a/src/Wolverine/Shims/NServiceBus/ExtendableOptions.cs b/src/Wolverine/Shims/NServiceBus/ExtendableOptions.cs deleted file mode 100644 index 3ced98eb3..000000000 --- a/src/Wolverine/Shims/NServiceBus/ExtendableOptions.cs +++ /dev/null @@ -1,50 +0,0 @@ -namespace Wolverine.Shims.NServiceBus; - -/// -/// Base class for NServiceBus-compatible message options. -/// Maps internally to Wolverine's . -/// -public abstract class ExtendableOptions -{ - private Dictionary? _headers; - - /// - /// Sets a header key/value pair on the outgoing message. - /// - public void SetHeader(string key, string value) - { - _headers ??= new Dictionary(); - _headers[key] = value; - } - - /// - /// Gets all headers set on this options instance. - /// - public IReadOnlyDictionary GetHeaders() - { - return _headers ?? (IReadOnlyDictionary)new Dictionary(); - } - - /// - /// Sets the message identity for this options instance. - /// - public string? MessageId { get; set; } - - /// - /// Converts these NServiceBus-compatible options to Wolverine's . - /// - internal virtual DeliveryOptions ToDeliveryOptions() - { - var options = new DeliveryOptions(); - - if (_headers is { Count: > 0 }) - { - foreach (var kvp in _headers) - { - options.Headers[kvp.Key] = kvp.Value; - } - } - - return options; - } -} diff --git a/src/Wolverine/Shims/NServiceBus/IEndpointInstance.cs b/src/Wolverine/Shims/NServiceBus/IEndpointInstance.cs deleted file mode 100644 index bd5df1725..000000000 --- a/src/Wolverine/Shims/NServiceBus/IEndpointInstance.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Wolverine.Shims.NServiceBus; - -/// -/// NServiceBus-compatible interface representing a running endpoint instance. -/// Extends with lifecycle management. -/// Delegates to Wolverine's . -/// -public interface IEndpointInstance : IMessageSession -{ - /// - /// Stops the endpoint instance. - /// Maps to stopping the underlying host. - /// - Task Stop(); -} diff --git a/src/Wolverine/Shims/NServiceBus/IHandleMessages.cs b/src/Wolverine/Shims/NServiceBus/IHandleMessages.cs deleted file mode 100644 index 1318be93b..000000000 --- a/src/Wolverine/Shims/NServiceBus/IHandleMessages.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Wolverine.Shims.NServiceBus; - -/// -/// NServiceBus-compatible message handler interface. -/// Implementing this interface marks the class for Wolverine's handler discovery -/// via . -/// -/// The message type to handle -public interface IHandleMessages : IWolverineHandler -{ - /// - /// Handles a message of type . - /// - /// The message to handle - /// The handler context providing access to message metadata and messaging operations - Task Handle(T message, IMessageHandlerContext context); -} diff --git a/src/Wolverine/Shims/NServiceBus/IMessageHandlerContext.cs b/src/Wolverine/Shims/NServiceBus/IMessageHandlerContext.cs deleted file mode 100644 index 4bffc0b92..000000000 --- a/src/Wolverine/Shims/NServiceBus/IMessageHandlerContext.cs +++ /dev/null @@ -1,57 +0,0 @@ -namespace Wolverine.Shims.NServiceBus; - -/// -/// NServiceBus-compatible interface available during message handling. -/// Provides access to message metadata and the ability to send, publish, and reply. -/// Delegates to Wolverine's . -/// -public interface IMessageHandlerContext -{ - /// - /// The unique identifier of the message currently being handled. - /// Maps to . - /// - string MessageId { get; } - - /// - /// The address to which replies should be sent. - /// Maps to . - /// - string? ReplyToAddress { get; } - - /// - /// The headers of the message currently being handled. - /// Maps to . - /// - IReadOnlyDictionary MessageHeaders { get; } - - /// - /// The correlation identifier for the current message workflow. - /// Maps to . - /// - string? CorrelationId { get; } - - /// - /// Sends a command message. - /// Maps to . - /// - Task Send(object message, SendOptions? options = null); - - /// - /// Publishes an event message. - /// Maps to . - /// - Task Publish(object message, PublishOptions? options = null); - - /// - /// Sends a reply back to the originator of the current message. - /// Maps to . - /// - Task Reply(object message, ReplyOptions? options = null); - - /// - /// Sends the current message to a different endpoint for processing. - /// Maps to sending the current message body to the specified destination. - /// - Task ForwardCurrentMessageTo(string destination); -} diff --git a/src/Wolverine/Shims/NServiceBus/IMessageSession.cs b/src/Wolverine/Shims/NServiceBus/IMessageSession.cs deleted file mode 100644 index 72823699f..000000000 --- a/src/Wolverine/Shims/NServiceBus/IMessageSession.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace Wolverine.Shims.NServiceBus; - -/// -/// NServiceBus-compatible interface for sending and publishing messages outside of a message handler. -/// Delegates to Wolverine's . -/// -public interface IMessageSession -{ - /// - /// Sends a command message. In NServiceBus, Send is for commands (point-to-point). - /// Maps to . - /// - Task Send(object message, SendOptions? options = null); - - /// - /// Publishes an event message. In NServiceBus, Publish is for events (pub-sub). - /// Maps to . - /// - Task Publish(object message, PublishOptions? options = null); -} diff --git a/src/Wolverine/Shims/NServiceBus/ITransactionalSession.cs b/src/Wolverine/Shims/NServiceBus/ITransactionalSession.cs deleted file mode 100644 index 865ed2f91..000000000 --- a/src/Wolverine/Shims/NServiceBus/ITransactionalSession.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace Wolverine.Shims.NServiceBus; - -/// -/// NServiceBus-compatible transactional session interface. -/// Extends with transaction lifecycle. -/// Wolverine handles transactional messaging automatically, so the Open/Commit -/// methods are obsolete and will throw . -/// -public interface ITransactionalSession : IUniformSession -{ - /// - /// Opens the transactional session. - /// - [Obsolete("Wolverine handles transactions automatically. Delete this usage.")] - Task Open(); - - /// - /// Commits the transactional session. - /// - [Obsolete("Wolverine handles transactions automatically. Delete this usage.")] - Task Commit(); -} diff --git a/src/Wolverine/Shims/NServiceBus/IUniformSession.cs b/src/Wolverine/Shims/NServiceBus/IUniformSession.cs deleted file mode 100644 index aa3969f24..000000000 --- a/src/Wolverine/Shims/NServiceBus/IUniformSession.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace Wolverine.Shims.NServiceBus; - -/// -/// NServiceBus-compatible unified interface for sending and publishing that works -/// both inside and outside of message handlers. -/// Delegates to Wolverine's . -/// -public interface IUniformSession -{ - /// - /// Sends a command message. - /// Maps to . - /// - Task Send(object message, SendOptions? options = null); - - /// - /// Publishes an event message. - /// Maps to . - /// - Task Publish(object message, PublishOptions? options = null); -} diff --git a/src/Wolverine/Shims/NServiceBus/MessageHandlerContextVariableSource.cs b/src/Wolverine/Shims/NServiceBus/MessageHandlerContextVariableSource.cs deleted file mode 100644 index f04273a6c..000000000 --- a/src/Wolverine/Shims/NServiceBus/MessageHandlerContextVariableSource.cs +++ /dev/null @@ -1,51 +0,0 @@ -using JasperFx.CodeGeneration; -using JasperFx.CodeGeneration.Frames; -using JasperFx.CodeGeneration.Model; -using JasperFx.Core.Reflection; - -namespace Wolverine.Shims.NServiceBus; - -/// -/// Code generation variable source that creates -/// instances from the current . -/// This eliminates the need for service location when resolving -/// in handler methods. -/// -internal class MessageHandlerContextVariableSource : IVariableSource -{ - public bool Matches(Type type) - { - return type == typeof(IMessageHandlerContext); - } - - public Variable Create(Type type) - { - return new MessageHandlerContextFrame().Variable; - } -} - -internal class MessageHandlerContextFrame : SyncFrame -{ - private Variable? _context; - - public MessageHandlerContextFrame() - { - Variable = new Variable(typeof(IMessageHandlerContext), this); - } - - public Variable Variable { get; } - - public override IEnumerable FindVariables(IMethodVariables chain) - { - _context = chain.FindVariable(typeof(IMessageContext)); - yield return _context; - } - - public override void GenerateCode(GeneratedMethod method, ISourceWriter writer) - { - writer.WriteLine( - $"var {Variable.Usage} = new {typeof(WolverineMessageHandlerContext).FullNameInCode()}({_context!.Usage});"); - - Next?.GenerateCode(method, writer); - } -} diff --git a/src/Wolverine/Shims/NServiceBus/NServiceBusShimExtensions.cs b/src/Wolverine/Shims/NServiceBus/NServiceBusShimExtensions.cs deleted file mode 100644 index a08e91cb9..000000000 --- a/src/Wolverine/Shims/NServiceBus/NServiceBusShimExtensions.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; - -namespace Wolverine.Shims.NServiceBus; - -/// -/// Extension methods to register NServiceBus shim interfaces with Wolverine. -/// -public static class NServiceBusShimExtensions -{ - /// - /// Registers NServiceBus shim DI services for constructor injection. - /// is automatically resolved in handler methods - /// via code generation and does not require this call. - /// This registers , , - /// , and for - /// constructor injection in services outside of message handlers. - /// - public static WolverineOptions UseNServiceBusShims(this WolverineOptions options) - { - options.Services.AddScoped(sp => - new WolverineMessageSession(sp.GetRequiredService())); - - options.Services.AddScoped(sp => - new WolverineEndpointInstance( - sp.GetRequiredService(), - sp.GetRequiredService())); - - options.Services.AddScoped(sp => - new WolverineUniformSession(sp.GetRequiredService())); - - options.Services.AddScoped(sp => - new WolverineTransactionalSession(sp.GetRequiredService())); - - return options; - } -} diff --git a/src/Wolverine/Shims/NServiceBus/PublishOptions.cs b/src/Wolverine/Shims/NServiceBus/PublishOptions.cs deleted file mode 100644 index 1419fd59e..000000000 --- a/src/Wolverine/Shims/NServiceBus/PublishOptions.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Wolverine.Shims.NServiceBus; - -/// -/// NServiceBus-compatible options for publishing an event message. -/// Maps internally to Wolverine's . -/// -public class PublishOptions : ExtendableOptions -{ -} diff --git a/src/Wolverine/Shims/NServiceBus/ReplyOptions.cs b/src/Wolverine/Shims/NServiceBus/ReplyOptions.cs deleted file mode 100644 index 03767627f..000000000 --- a/src/Wolverine/Shims/NServiceBus/ReplyOptions.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Wolverine.Shims.NServiceBus; - -/// -/// NServiceBus-compatible options for replying to the sender of the current message. -/// Maps internally to Wolverine's . -/// -public class ReplyOptions : ExtendableOptions -{ -} diff --git a/src/Wolverine/Shims/NServiceBus/SendOptions.cs b/src/Wolverine/Shims/NServiceBus/SendOptions.cs deleted file mode 100644 index 4009a0f3f..000000000 --- a/src/Wolverine/Shims/NServiceBus/SendOptions.cs +++ /dev/null @@ -1,62 +0,0 @@ -namespace Wolverine.Shims.NServiceBus; - -/// -/// NServiceBus-compatible options for sending a command message. -/// Maps internally to Wolverine's . -/// -public class SendOptions : ExtendableOptions -{ - /// - /// Sets the destination endpoint for this send operation. - /// Maps to Wolverine's . - /// - public string? Destination { get; set; } - - /// - /// Sets the destination endpoint for the send operation. - /// - public void SetDestination(string destination) - { - Destination = destination; - } - - /// - /// Delays the delivery of the message by the specified time span. - /// Maps to . - /// - public void DelayDeliveryWith(TimeSpan delay) - { - Delay = delay; - ScheduledTime = null; - } - - /// - /// Delays the delivery of the message until the specified time. - /// Maps to . - /// - public void DoNotDeliverBefore(DateTimeOffset at) - { - ScheduledTime = at; - Delay = null; - } - - internal TimeSpan? Delay { get; set; } - internal DateTimeOffset? ScheduledTime { get; set; } - - internal override DeliveryOptions ToDeliveryOptions() - { - var options = base.ToDeliveryOptions(); - - if (Delay.HasValue) - { - options.ScheduleDelay = Delay; - } - - if (ScheduledTime.HasValue) - { - options.ScheduledTime = ScheduledTime; - } - - return options; - } -} diff --git a/src/Wolverine/Shims/NServiceBus/WolverineEndpointInstance.cs b/src/Wolverine/Shims/NServiceBus/WolverineEndpointInstance.cs deleted file mode 100644 index 2ad8a82e6..000000000 --- a/src/Wolverine/Shims/NServiceBus/WolverineEndpointInstance.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Microsoft.Extensions.Hosting; - -namespace Wolverine.Shims.NServiceBus; - -/// -/// Wolverine-backed implementation of . -/// Delegates messaging to and lifecycle to . -/// -public class WolverineEndpointInstance : IEndpointInstance -{ - private readonly IMessageBus _bus; - private readonly IHost _host; - - public WolverineEndpointInstance(IMessageBus bus, IHost host) - { - _bus = bus; - _host = host; - } - - public async Task Send(object message, SendOptions? options = null) - { - var deliveryOptions = options?.ToDeliveryOptions(); - - if (options?.Destination != null) - { - var endpoint = _bus.EndpointFor(options.Destination); - await endpoint.SendAsync(message, deliveryOptions); - } - else - { - await _bus.SendAsync(message, deliveryOptions); - } - } - - public async Task Publish(object message, PublishOptions? options = null) - { - await _bus.PublishAsync(message, options?.ToDeliveryOptions()); - } - - public async Task Stop() - { - await _host.StopAsync(); - } -} diff --git a/src/Wolverine/Shims/NServiceBus/WolverineMessageHandlerContext.cs b/src/Wolverine/Shims/NServiceBus/WolverineMessageHandlerContext.cs deleted file mode 100644 index b1f705dab..000000000 --- a/src/Wolverine/Shims/NServiceBus/WolverineMessageHandlerContext.cs +++ /dev/null @@ -1,60 +0,0 @@ -namespace Wolverine.Shims.NServiceBus; - -/// -/// Wolverine-backed implementation of . -/// Delegates all operations to . -/// -public class WolverineMessageHandlerContext : IMessageHandlerContext -{ - private readonly IMessageContext _context; - - public WolverineMessageHandlerContext(IMessageContext context) - { - _context = context; - } - - public string MessageId => _context.Envelope?.Id.ToString() ?? string.Empty; - - public string? ReplyToAddress => _context.Envelope?.ReplyUri?.ToString(); - - public IReadOnlyDictionary MessageHeaders => - _context.Envelope?.Headers ?? (IReadOnlyDictionary)new Dictionary(); - - public string? CorrelationId => _context.CorrelationId; - - public async Task Send(object message, SendOptions? options = null) - { - var deliveryOptions = options?.ToDeliveryOptions(); - - if (options?.Destination != null) - { - var endpoint = _context.EndpointFor(options.Destination); - await endpoint.SendAsync(message, deliveryOptions); - } - else - { - await _context.SendAsync(message, deliveryOptions); - } - } - - public async Task Publish(object message, PublishOptions? options = null) - { - await _context.PublishAsync(message, options?.ToDeliveryOptions()); - } - - public async Task Reply(object message, ReplyOptions? options = null) - { - await _context.RespondToSenderAsync(message); - } - - public async Task ForwardCurrentMessageTo(string destination) - { - if (_context.Envelope?.Message == null) - { - throw new InvalidOperationException("No current message to forward."); - } - - var endpoint = _context.EndpointFor(destination); - await endpoint.SendAsync(_context.Envelope.Message); - } -} diff --git a/src/Wolverine/Shims/NServiceBus/WolverineMessageSession.cs b/src/Wolverine/Shims/NServiceBus/WolverineMessageSession.cs deleted file mode 100644 index 87610e330..000000000 --- a/src/Wolverine/Shims/NServiceBus/WolverineMessageSession.cs +++ /dev/null @@ -1,35 +0,0 @@ -namespace Wolverine.Shims.NServiceBus; - -/// -/// Wolverine-backed implementation of . -/// Delegates all operations to . -/// -public class WolverineMessageSession : IMessageSession -{ - private readonly IMessageBus _bus; - - public WolverineMessageSession(IMessageBus bus) - { - _bus = bus; - } - - public async Task Send(object message, SendOptions? options = null) - { - var deliveryOptions = options?.ToDeliveryOptions(); - - if (options?.Destination != null) - { - var endpoint = _bus.EndpointFor(options.Destination); - await endpoint.SendAsync(message, deliveryOptions); - } - else - { - await _bus.SendAsync(message, deliveryOptions); - } - } - - public async Task Publish(object message, PublishOptions? options = null) - { - await _bus.PublishAsync(message, options?.ToDeliveryOptions()); - } -} diff --git a/src/Wolverine/Shims/NServiceBus/WolverineTransactionalSession.cs b/src/Wolverine/Shims/NServiceBus/WolverineTransactionalSession.cs deleted file mode 100644 index 74ae3b3db..000000000 --- a/src/Wolverine/Shims/NServiceBus/WolverineTransactionalSession.cs +++ /dev/null @@ -1,50 +0,0 @@ -namespace Wolverine.Shims.NServiceBus; - -/// -/// Wolverine-backed implementation of . -/// Delegates messaging to . -/// Open/Commit are not supported because Wolverine handles transactions automatically. -/// -public class WolverineTransactionalSession : ITransactionalSession -{ - private readonly IMessageBus _bus; - - public WolverineTransactionalSession(IMessageBus bus) - { - _bus = bus; - } - - public async Task Send(object message, SendOptions? options = null) - { - var deliveryOptions = options?.ToDeliveryOptions(); - - if (options?.Destination != null) - { - var endpoint = _bus.EndpointFor(options.Destination); - await endpoint.SendAsync(message, deliveryOptions); - } - else - { - await _bus.SendAsync(message, deliveryOptions); - } - } - - public async Task Publish(object message, PublishOptions? options = null) - { - await _bus.PublishAsync(message, options?.ToDeliveryOptions()); - } - - [Obsolete("Wolverine handles transactions automatically. Delete this usage.")] - public Task Open() - { - throw new NotSupportedException( - "Wolverine handles transactions automatically. Remove calls to Open()."); - } - - [Obsolete("Wolverine handles transactions automatically. Delete this usage.")] - public Task Commit() - { - throw new NotSupportedException( - "Wolverine handles transactions automatically. Remove calls to Commit()."); - } -} diff --git a/src/Wolverine/Shims/NServiceBus/WolverineUniformSession.cs b/src/Wolverine/Shims/NServiceBus/WolverineUniformSession.cs deleted file mode 100644 index 353cd3ad9..000000000 --- a/src/Wolverine/Shims/NServiceBus/WolverineUniformSession.cs +++ /dev/null @@ -1,35 +0,0 @@ -namespace Wolverine.Shims.NServiceBus; - -/// -/// Wolverine-backed implementation of . -/// Delegates all operations to . -/// -public class WolverineUniformSession : IUniformSession -{ - private readonly IMessageBus _bus; - - public WolverineUniformSession(IMessageBus bus) - { - _bus = bus; - } - - public async Task Send(object message, SendOptions? options = null) - { - var deliveryOptions = options?.ToDeliveryOptions(); - - if (options?.Destination != null) - { - var endpoint = _bus.EndpointFor(options.Destination); - await endpoint.SendAsync(message, deliveryOptions); - } - else - { - await _bus.SendAsync(message, deliveryOptions); - } - } - - public async Task Publish(object message, PublishOptions? options = null) - { - await _bus.PublishAsync(message, options?.ToDeliveryOptions()); - } -} diff --git a/src/Wolverine/WolverineOptions.cs b/src/Wolverine/WolverineOptions.cs index 419aac741..b68dd59b4 100644 --- a/src/Wolverine/WolverineOptions.cs +++ b/src/Wolverine/WolverineOptions.cs @@ -122,9 +122,6 @@ public WolverineOptions(string? assemblyName) CodeGeneration.Sources.Add(new Shims.MassTransit.ConsumeContextVariableSource()); CodeGeneration.Sources.Add(new Shims.MassTransit.MassTransitInterfaceVariableSource()); - // NServiceBus shim variable sources - CodeGeneration.Sources.Add(new Shims.NServiceBus.MessageHandlerContextVariableSource()); - CodeGeneration.Assemblies.Add(GetType().Assembly); if (assemblyName != null)