diff --git a/samples/bridge/simple/Bridge_4/Bridge.sln b/samples/bridge/simple/Bridge_4/Bridge.sln new file mode 100644 index 00000000000..7c95799815e --- /dev/null +++ b/samples/bridge/simple/Bridge_4/Bridge.sln @@ -0,0 +1,35 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29728.190 +MinimumVisualStudioVersion = 15.0.26730.12 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shared", "Shared\Shared.csproj", "{5686FE6C-A5E3-40D1-A6BD-25F94DA612F8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LeftSender", "LeftSender\LeftSender.csproj", "{7036A49B-359F-4BC7-AFBA-DE3C7AB41986}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LeftReceiver", "LeftReceiver\LeftReceiver.csproj", "{6A699A4E-F2FD-4B71-AF73-199B499482BD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RightReceiver", "RightReceiver\RightReceiver.csproj", "{96028F4C-6B27-4CBE-95EB-A39F1EDCE045}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bridge", "Bridge\Bridge.csproj", "{355C998A-AAC0-4BAB-87B3-C5D34DE9C0B1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5686FE6C-A5E3-40D1-A6BD-25F94DA612F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5686FE6C-A5E3-40D1-A6BD-25F94DA612F8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7036A49B-359F-4BC7-AFBA-DE3C7AB41986}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7036A49B-359F-4BC7-AFBA-DE3C7AB41986}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6A699A4E-F2FD-4B71-AF73-199B499482BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6A699A4E-F2FD-4B71-AF73-199B499482BD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {96028F4C-6B27-4CBE-95EB-A39F1EDCE045}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {96028F4C-6B27-4CBE-95EB-A39F1EDCE045}.Debug|Any CPU.Build.0 = Debug|Any CPU + {355C998A-AAC0-4BAB-87B3-C5D34DE9C0B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {355C998A-AAC0-4BAB-87B3-C5D34DE9C0B1}.Debug|Any CPU.Build.0 = Debug|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/samples/bridge/simple/Bridge_4/Bridge/Bridge.csproj b/samples/bridge/simple/Bridge_4/Bridge/Bridge.csproj new file mode 100644 index 00000000000..2110fa9e3b0 --- /dev/null +++ b/samples/bridge/simple/Bridge_4/Bridge/Bridge.csproj @@ -0,0 +1,19 @@ + + + + net10.0 + Exe + preview + + + + + + + + + + + + + diff --git a/samples/bridge/simple/Bridge_4/Bridge/Program.cs b/samples/bridge/simple/Bridge_4/Bridge/Program.cs new file mode 100644 index 00000000000..5332640fc00 --- /dev/null +++ b/samples/bridge/simple/Bridge_4/Bridge/Program.cs @@ -0,0 +1,62 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using NServiceBus; + +static class Program +{ + static async Task Main() + { + Console.Title = "Bridge"; + + var builder = Host.CreateApplicationBuilder(); + var bridgeConfiguration = new BridgeConfiguration(); + + #region endpoint-adding-simple + + var learningLeft = new BridgeTransport(new LearningTransport()); + learningLeft.HasEndpoint("Samples.Bridge.LeftSender"); + + #endregion + + var learningTransport = new LearningTransport + { + // Set storage directory and add the character '2' to simulate a different transport. + StorageDirectory = $"{LearningTransportInfrastructure.FindStoragePath()}2" + }; + var learningRight = new BridgeTransport(learningTransport) + { + // A different name is required if transports are used twice. + Name = "right-side" + }; + + #region endpoint-adding-register-publisher-by-string + + var rightReceiver = new BridgeEndpoint("Samples.Bridge.RightReceiver"); + rightReceiver.RegisterPublisher("OrderReceived", "Samples.Bridge.LeftSender"); + + #endregion + learningRight.HasEndpoint(rightReceiver); + + #region add-transports-to-bridge + + bridgeConfiguration.AddTransport(learningLeft); + bridgeConfiguration.AddTransport(learningRight); + + #endregion + + builder.Logging.ClearProviders(); + builder.Logging.AddSimpleConsole(options => + { + options.IncludeScopes = false; + options.SingleLine = true; + options.TimestampFormat = "hh:mm:ss "; + }); + + builder.UseNServiceBusBridge(bridgeConfiguration); + + var host = builder.Build(); + await host.RunAsync(); + } +} \ No newline at end of file diff --git a/samples/bridge/simple/Bridge_4/LeftReceiver/LeftReceiver.csproj b/samples/bridge/simple/Bridge_4/LeftReceiver/LeftReceiver.csproj new file mode 100644 index 00000000000..adb24c4279b --- /dev/null +++ b/samples/bridge/simple/Bridge_4/LeftReceiver/LeftReceiver.csproj @@ -0,0 +1,19 @@ + + + + net10.0 + Exe + preview + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/bridge/simple/Bridge_4/LeftReceiver/OrderReceivedHandler.cs b/samples/bridge/simple/Bridge_4/LeftReceiver/OrderReceivedHandler.cs new file mode 100644 index 00000000000..a25a6d453f7 --- /dev/null +++ b/samples/bridge/simple/Bridge_4/LeftReceiver/OrderReceivedHandler.cs @@ -0,0 +1,13 @@ +using System.Threading.Tasks; +using NServiceBus; +using Microsoft.Extensions.Logging; + +public class OrderReceivedHandler(ILogger logger) : + IHandleMessages +{ + public Task Handle(OrderReceived message, IMessageHandlerContext context) + { + logger.LogInformation("Subscriber has received OrderReceived event with OrderId {OrderId}.", message.OrderId); + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/samples/bridge/simple/Bridge_4/LeftReceiver/Program.cs b/samples/bridge/simple/Bridge_4/LeftReceiver/Program.cs new file mode 100644 index 00000000000..90f5de4967b --- /dev/null +++ b/samples/bridge/simple/Bridge_4/LeftReceiver/Program.cs @@ -0,0 +1,27 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.Hosting; +using NServiceBus; + +Console.Title = "LeftReceiver"; + +var builder = Host.CreateApplicationBuilder(args); + +var endpointConfiguration = new EndpointConfiguration("Samples.Bridge.LeftReceiver"); +endpointConfiguration.UsePersistence(); +endpointConfiguration.UseSerialization(); +endpointConfiguration.UseTransport(new LearningTransport()); + +endpointConfiguration.Conventions().DefiningMessagesAs(t => t.Name == "OrderResponse"); +endpointConfiguration.Conventions().DefiningEventsAs(t => t.Name == "OrderReceived"); + +endpointConfiguration.SendFailedMessagesTo("error"); +endpointConfiguration.EnableInstallers(); + + +Console.WriteLine("Press any key, the application is starting"); +Console.ReadKey(); +Console.WriteLine("Starting..."); + +builder.UseNServiceBus(endpointConfiguration); +await builder.Build().RunAsync(); diff --git a/samples/bridge/simple/Bridge_4/LeftSender/LeftSender.csproj b/samples/bridge/simple/Bridge_4/LeftSender/LeftSender.csproj new file mode 100644 index 00000000000..f7f660478f6 --- /dev/null +++ b/samples/bridge/simple/Bridge_4/LeftSender/LeftSender.csproj @@ -0,0 +1,16 @@ + + + net10.0 + Exe + preview + + + + + + + + + + + \ No newline at end of file diff --git a/samples/bridge/simple/Bridge_4/LeftSender/OrderResponseHandler.cs b/samples/bridge/simple/Bridge_4/LeftSender/OrderResponseHandler.cs new file mode 100644 index 00000000000..bf765b9f958 --- /dev/null +++ b/samples/bridge/simple/Bridge_4/LeftSender/OrderResponseHandler.cs @@ -0,0 +1,13 @@ +using System; +using System.Threading.Tasks; +using NServiceBus; + +public class OrderResponseHandler : IHandleMessages +{ + public Task Handle(OrderResponse message, IMessageHandlerContext context) + { + Console.WriteLine($"OrderResponse Reply received with Id {message.OrderId}"); + + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/samples/bridge/simple/Bridge_4/LeftSender/Program.cs b/samples/bridge/simple/Bridge_4/LeftSender/Program.cs new file mode 100644 index 00000000000..fe0ddb20959 --- /dev/null +++ b/samples/bridge/simple/Bridge_4/LeftSender/Program.cs @@ -0,0 +1,66 @@ +using System; +using System.Threading.Tasks; +using NServiceBus; + +static class Program +{ + static async Task Main() + { + Console.Title = "LeftSender"; + var endpointConfiguration = new EndpointConfiguration("Samples.Bridge.LeftSender"); + endpointConfiguration.UsePersistence(); + + endpointConfiguration.Conventions().DefiningCommandsAs(t => t.Name == "PlaceOrder"); + endpointConfiguration.Conventions().DefiningMessagesAs(t => t.Name == "OrderResponse"); + endpointConfiguration.Conventions().DefiningEventsAs(t => t.Name == "OrderReceived"); + + endpointConfiguration.UseSerialization(); + var routing = endpointConfiguration.UseTransport(new LearningTransport()); + routing.RouteToEndpoint(typeof(PlaceOrder), "Samples.Bridge.RightReceiver"); + + endpointConfiguration.SendFailedMessagesTo("error"); + endpointConfiguration.EnableInstallers(); + + var endpointInstance = await Endpoint.Start(endpointConfiguration); + await Start(endpointInstance); + await endpointInstance.Stop(); + } + + static async Task Start(IEndpointInstance endpointInstance) + { + Console.WriteLine("Press '1' to send the PlaceOrder command"); + Console.WriteLine("Press '2' to publish the OrderReceived event"); + Console.WriteLine("Press 'esc' other key to exit"); + + while (true) + { + var key = Console.ReadKey(); + Console.WriteLine(); + + var orderId = Guid.NewGuid(); + switch (key.Key) + { + case ConsoleKey.D1: + case ConsoleKey.NumPad1: + var placeOrder = new PlaceOrder + { + OrderId = orderId + }; + await endpointInstance.Send(placeOrder); + Console.WriteLine($"Send PlaceOrder Command with Id {orderId}"); + break; + case ConsoleKey.D2: + case ConsoleKey.NumPad2: + var orderReceived = new OrderReceived + { + OrderId = orderId + }; + await endpointInstance.Publish(orderReceived); + Console.WriteLine($"Published OrderReceived Event with Id {orderId}."); + break; + case ConsoleKey.Escape: + return; + } + } + } +} diff --git a/samples/bridge/simple/Bridge_4/RightReceiver/OrderReceivedHandler.cs b/samples/bridge/simple/Bridge_4/RightReceiver/OrderReceivedHandler.cs new file mode 100644 index 00000000000..a25a6d453f7 --- /dev/null +++ b/samples/bridge/simple/Bridge_4/RightReceiver/OrderReceivedHandler.cs @@ -0,0 +1,13 @@ +using System.Threading.Tasks; +using NServiceBus; +using Microsoft.Extensions.Logging; + +public class OrderReceivedHandler(ILogger logger) : + IHandleMessages +{ + public Task Handle(OrderReceived message, IMessageHandlerContext context) + { + logger.LogInformation("Subscriber has received OrderReceived event with OrderId {OrderId}.", message.OrderId); + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/samples/bridge/simple/Bridge_4/RightReceiver/PlaceOrderHandler.cs b/samples/bridge/simple/Bridge_4/RightReceiver/PlaceOrderHandler.cs new file mode 100644 index 00000000000..37df72cbded --- /dev/null +++ b/samples/bridge/simple/Bridge_4/RightReceiver/PlaceOrderHandler.cs @@ -0,0 +1,14 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using NServiceBus; + +public class PlaceOrderHandler(ILogger logger) : IHandleMessages +{ + public async Task Handle(PlaceOrder message, IMessageHandlerContext context) + { + logger.LogInformation("Received PlaceOrder Command with Id {OrderId}", message.OrderId); + + await context.Reply(new OrderResponse { OrderId = message.OrderId }); + } +} \ No newline at end of file diff --git a/samples/bridge/simple/Bridge_4/RightReceiver/Program.cs b/samples/bridge/simple/Bridge_4/RightReceiver/Program.cs new file mode 100644 index 00000000000..d7beb7322b2 --- /dev/null +++ b/samples/bridge/simple/Bridge_4/RightReceiver/Program.cs @@ -0,0 +1,38 @@ +using System; +using System.IO; +using System.Threading.Tasks; +using Microsoft.Extensions.Hosting; +using NServiceBus; + +Console.Title = "RightReceiver"; + +var builder = Host.CreateApplicationBuilder(args); + +var endpointConfiguration = new EndpointConfiguration("Samples.Bridge.RightReceiver"); +endpointConfiguration.UsePersistence(); + +endpointConfiguration.Conventions().DefiningCommandsAs(t => t.Name == "PlaceOrder"); +endpointConfiguration.Conventions().DefiningMessagesAs(t => t.Name == "OrderResponse"); +endpointConfiguration.Conventions().DefiningEventsAs(t => t.Name == "OrderReceived"); + +#region alternative-learning-transport +var learningTransportDefinition = new LearningTransport +{ + // Set storage directory and add the character '2' to simulate a different transport. + StorageDirectory = $"{LearningTransportInfrastructure.FindStoragePath()}2" +}; +endpointConfiguration.UseTransport(learningTransportDefinition); +#endregion + +endpointConfiguration.UseSerialization(); + +endpointConfiguration.SendFailedMessagesTo("error"); +endpointConfiguration.EnableInstallers(); + + +Console.WriteLine("Press any key, the application is starting"); +Console.ReadKey(); +Console.WriteLine("Starting..."); + +builder.UseNServiceBus(endpointConfiguration); +await builder.Build().RunAsync(); diff --git a/samples/bridge/simple/Bridge_4/RightReceiver/RightReceiver.csproj b/samples/bridge/simple/Bridge_4/RightReceiver/RightReceiver.csproj new file mode 100644 index 00000000000..adb24c4279b --- /dev/null +++ b/samples/bridge/simple/Bridge_4/RightReceiver/RightReceiver.csproj @@ -0,0 +1,19 @@ + + + + net10.0 + Exe + preview + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/bridge/simple/Bridge_4/Shared/LearningTransportInfrastructure.cs b/samples/bridge/simple/Bridge_4/Shared/LearningTransportInfrastructure.cs new file mode 100644 index 00000000000..164b1fb4cf2 --- /dev/null +++ b/samples/bridge/simple/Bridge_4/Shared/LearningTransportInfrastructure.cs @@ -0,0 +1,42 @@ +using System; +using System.IO; +using System.Reflection; + +public static class LearningTransportInfrastructure +{ + public static string FindStoragePath() + { + var directory = AppDomain.CurrentDomain.BaseDirectory; + var assemblyName = Assembly.GetCallingAssembly().GetName().Name.ToLowerInvariant(); + + while (true) + { + + + var learningTransportDirectory = Path.Combine(directory, DefaultLearningTransportDirectory); + if (Directory.Exists(learningTransportDirectory)) + { + return learningTransportDirectory; + } + + // This works for samples + if (directory.ToLowerInvariant().EndsWith(assemblyName)) + { + var solutionFolder = Directory.GetParent(directory); + if (solutionFolder != null) + return Path.Combine(solutionFolder.FullName, DefaultLearningTransportDirectory); + } + + var parent = Directory.GetParent(directory); + + if (parent == null) + { + throw new Exception($"Unable to determine the storage directory path for the learning transport. Either create a '{DefaultLearningTransportDirectory}2' directory in one of this project’s parent directories, or specify the path explicitly using the 'StorageDirectory' property in the API."); + } + + directory = parent.FullName; + } + } + + const string DefaultLearningTransportDirectory = ".learningtransport"; +} \ No newline at end of file diff --git a/samples/bridge/simple/Bridge_4/Shared/OrderReceived.cs b/samples/bridge/simple/Bridge_4/Shared/OrderReceived.cs new file mode 100644 index 00000000000..06b6ade7f04 --- /dev/null +++ b/samples/bridge/simple/Bridge_4/Shared/OrderReceived.cs @@ -0,0 +1,6 @@ +using System; + +public class OrderReceived +{ + public required Guid OrderId { get; set; } +} \ No newline at end of file diff --git a/samples/bridge/simple/Bridge_4/Shared/OrderResponse.cs b/samples/bridge/simple/Bridge_4/Shared/OrderResponse.cs new file mode 100644 index 00000000000..e191d7fbaf3 --- /dev/null +++ b/samples/bridge/simple/Bridge_4/Shared/OrderResponse.cs @@ -0,0 +1,6 @@ +using System; + +public class OrderResponse +{ + public required Guid OrderId { get; set; } +} \ No newline at end of file diff --git a/samples/bridge/simple/Bridge_4/Shared/PlaceOrder.cs b/samples/bridge/simple/Bridge_4/Shared/PlaceOrder.cs new file mode 100644 index 00000000000..53b081cdfad --- /dev/null +++ b/samples/bridge/simple/Bridge_4/Shared/PlaceOrder.cs @@ -0,0 +1,6 @@ +using System; + +public class PlaceOrder +{ + public required Guid OrderId { get; set; } +} \ No newline at end of file diff --git a/samples/bridge/simple/Bridge_4/Shared/Shared.csproj b/samples/bridge/simple/Bridge_4/Shared/Shared.csproj new file mode 100644 index 00000000000..3e44602cd21 --- /dev/null +++ b/samples/bridge/simple/Bridge_4/Shared/Shared.csproj @@ -0,0 +1,8 @@ + + + + net10.0 + preview + + + \ No newline at end of file diff --git a/samples/bridge/simple/Bridge_4/prerelease.txt b/samples/bridge/simple/Bridge_4/prerelease.txt new file mode 100644 index 00000000000..e69de29bb2d