From bb5a9266e71f2ec8b12d7d8b9c9ec274f30312b9 Mon Sep 17 00:00:00 2001 From: stidsborg Date: Sun, 18 Aug 2024 11:22:42 +0200 Subject: [PATCH] Added Wolverine service-bus sample --- Cleipnir.Flows.sln | 17 +++++ .../Cleipnir.Flows.Wolverine.Console.csproj | 19 ++++++ .../MyMessage.cs | 3 + .../Program.cs | 49 ++++++++++++++ .../SimpleFlow.cs | 25 +++++++ .../Cleipnir.Flows.Wolverine.Tests.csproj | 31 +++++++++ .../IntegrationTests.cs | 66 +++++++++++++++++++ .../TestFlowHandler.cs | 6 ++ 8 files changed, 216 insertions(+) create mode 100644 ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Console/Cleipnir.Flows.Wolverine.Console.csproj create mode 100644 ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Console/MyMessage.cs create mode 100644 ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Console/Program.cs create mode 100644 ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Console/SimpleFlow.cs create mode 100644 ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Tests/Cleipnir.Flows.Wolverine.Tests.csproj create mode 100644 ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Tests/IntegrationTests.cs create mode 100644 ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Tests/TestFlowHandler.cs diff --git a/Cleipnir.Flows.sln b/Cleipnir.Flows.sln index b619fd5..026be33 100644 --- a/Cleipnir.Flows.sln +++ b/Cleipnir.Flows.sln @@ -65,6 +65,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cleipnir.Flows.MassTransit. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cleipnir.Flows.MassTransit.Tests", "ServiceBuses\MassTransit\Cleipnir.Flows.MassTransit.Tests\Cleipnir.Flows.MassTransit.Tests.csproj", "{55263D9D-8024-49A5-9F22-336B3F5901AF}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Wolverine", "Wolverine", "{5E80C9B0-3EBD-4D8A-BBED-3D1CCB1A6756}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cleipnir.Flows.Wolverine.Console", "ServiceBuses\Wolverine\Cleipnir.Flows.Wolverine.Console\Cleipnir.Flows.Wolverine.Console.csproj", "{D627AC0C-A012-4EB5-A1F6-79A217636D11}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cleipnir.Flows.Wolverine.Tests", "ServiceBuses\Wolverine\Cleipnir.Flows.Wolverine.Tests\Cleipnir.Flows.Wolverine.Tests.csproj", "{F71833DB-A6DB-4EE5-911A-FF1B8EDABEBC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -162,6 +168,14 @@ Global {55263D9D-8024-49A5-9F22-336B3F5901AF}.Debug|Any CPU.Build.0 = Debug|Any CPU {55263D9D-8024-49A5-9F22-336B3F5901AF}.Release|Any CPU.ActiveCfg = Release|Any CPU {55263D9D-8024-49A5-9F22-336B3F5901AF}.Release|Any CPU.Build.0 = Release|Any CPU + {D627AC0C-A012-4EB5-A1F6-79A217636D11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D627AC0C-A012-4EB5-A1F6-79A217636D11}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D627AC0C-A012-4EB5-A1F6-79A217636D11}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D627AC0C-A012-4EB5-A1F6-79A217636D11}.Release|Any CPU.Build.0 = Release|Any CPU + {F71833DB-A6DB-4EE5-911A-FF1B8EDABEBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F71833DB-A6DB-4EE5-911A-FF1B8EDABEBC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F71833DB-A6DB-4EE5-911A-FF1B8EDABEBC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F71833DB-A6DB-4EE5-911A-FF1B8EDABEBC}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {BC470FDE-839E-4B2C-8C56-8B20DEEF2CCD} = {EAD350F1-8EF2-48AC-98EE-A5E739F15787} @@ -187,5 +201,8 @@ Global {339E2C3B-13B4-4A10-B162-511E3F0C1B52} = {43DF25B8-E678-48DC-8F8D-142F76F22300} {45A3D239-1736-443B-9B0E-0FE0D830B63B} = {43DF25B8-E678-48DC-8F8D-142F76F22300} {55263D9D-8024-49A5-9F22-336B3F5901AF} = {43DF25B8-E678-48DC-8F8D-142F76F22300} + {5E80C9B0-3EBD-4D8A-BBED-3D1CCB1A6756} = {0872461B-3FC1-4659-AE2D-80109CDA3F5E} + {D627AC0C-A012-4EB5-A1F6-79A217636D11} = {5E80C9B0-3EBD-4D8A-BBED-3D1CCB1A6756} + {F71833DB-A6DB-4EE5-911A-FF1B8EDABEBC} = {5E80C9B0-3EBD-4D8A-BBED-3D1CCB1A6756} EndGlobalSection EndGlobal diff --git a/ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Console/Cleipnir.Flows.Wolverine.Console.csproj b/ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Console/Cleipnir.Flows.Wolverine.Console.csproj new file mode 100644 index 0000000..3348201 --- /dev/null +++ b/ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Console/Cleipnir.Flows.Wolverine.Console.csproj @@ -0,0 +1,19 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + + + + + diff --git a/ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Console/MyMessage.cs b/ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Console/MyMessage.cs new file mode 100644 index 0000000..fed28d9 --- /dev/null +++ b/ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Console/MyMessage.cs @@ -0,0 +1,3 @@ +namespace Cleipnir.Flows.MassTransit.Console; + +public record MyMessage(string Value); \ No newline at end of file diff --git a/ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Console/Program.cs b/ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Console/Program.cs new file mode 100644 index 0000000..919bf4d --- /dev/null +++ b/ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Console/Program.cs @@ -0,0 +1,49 @@ +using Cleipnir.Flows.AspNet; +using Cleipnir.Flows.MassTransit.Console; +using Cleipnir.ResilientFunctions.Helpers; +using Cleipnir.ResilientFunctions.Storage; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Wolverine; + +namespace Cleipnir.Flows.Wolverine.Console; + +internal static class Program +{ + public static async Task Main(string[] args) + { + var host = await CreateHostBuilder([]).StartAsync(); + var bus = host.Services.GetRequiredService(); + var store = host.Services.GetRequiredService(); + + var testSize = 1_000; + for (var i = 0; i < testSize; i++) + await bus.PublishAsync(new MyMessage(i.ToString())); + + while (true) + { + var succeeded = await store.GetSucceededFunctions( + nameof(SimpleFlow), + DateTime.UtcNow.Ticks + 1_000_000 + ).SelectAsync(f => f.Count); + if (succeeded == testSize) + break; + + await Task.Delay(250); + } + + System.Console.WriteLine("All completed"); + } + + private static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureServices((_, services) => + { + services.AddFlows(c => c + .UseInMemoryStore() + .RegisterFlow() + //.RegisterFlowsAutomatically() + ); + }) + .UseWolverine(); +} diff --git a/ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Console/SimpleFlow.cs b/ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Console/SimpleFlow.cs new file mode 100644 index 0000000..9ea3025 --- /dev/null +++ b/ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Console/SimpleFlow.cs @@ -0,0 +1,25 @@ +using Cleipnir.Flows.MassTransit.Console; +using Cleipnir.ResilientFunctions.Reactive.Extensions; + +namespace Cleipnir.Flows.Wolverine.Console; + +public class SimpleFlow : Flow +{ + public override async Task Run() + { + var msg = await Messages.FirstOfType(); + System.Console.WriteLine($"SimpleFlow({msg}) executed"); + } +} + +public class SimpleFlows : Flows +{ + public SimpleFlows(FlowsContainer flowsContainer) + : base("SimpleFlow", flowsContainer, options: null) { } +} + +public class SimpleFlowsHandler(SimpleFlows flows) +{ + public Task Handle(MyMessage myMessage) + => flows.SendMessage(myMessage.Value, myMessage); +} \ No newline at end of file diff --git a/ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Tests/Cleipnir.Flows.Wolverine.Tests.csproj b/ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Tests/Cleipnir.Flows.Wolverine.Tests.csproj new file mode 100644 index 0000000..d020fe3 --- /dev/null +++ b/ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Tests/Cleipnir.Flows.Wolverine.Tests.csproj @@ -0,0 +1,31 @@ + + + net8.0 + enable + enable + + false + true + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + + + diff --git a/ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Tests/IntegrationTests.cs b/ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Tests/IntegrationTests.cs new file mode 100644 index 0000000..d5c796c --- /dev/null +++ b/ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Tests/IntegrationTests.cs @@ -0,0 +1,66 @@ +using Cleipnir.Flows.AspNet; +using Cleipnir.ResilientFunctions.Helpers; +using Cleipnir.ResilientFunctions.Reactive.Extensions; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Shouldly; +using Wolverine; + +namespace Cleipnir.Flows.Wolverine.Tests; + +[TestClass] +public class IntegrationTests +{ + public record MyMessage(string Value); + + public class TestFlow : Flow + { + public static volatile MyMessage? ReceivedMyMessage; + + public override async Task Run() + { + ReceivedMyMessage = await Messages.FirstOfType(); + } + } + + public class TestFlows : Flows + { + public TestFlows(FlowsContainer flowsContainer) : base(flowName: "RebusTestFlow", flowsContainer) { } + } + + private class TestHostedService : IHostedService + { + public static IServiceProvider? ServiceProvider { get; set; } + + public TestHostedService(IServiceProvider serviceProvider) => ServiceProvider = serviceProvider; + + public async Task StartAsync(CancellationToken cancellationToken) + { + await ServiceProvider!.GetRequiredService().SendAsync(new MyMessage("SomeMessage")); + } + public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; + } + + [TestMethod] + public async Task SunshineScenario() + { + var host = await Host + .CreateDefaultBuilder([]) + .UseWolverine() + .ConfigureServices((_, services) => + { + services.AddHostedService(); + + services.AddFlows(c => c + .UseInMemoryStore() + .RegisterFlow() + ); + }) + .StartAsync(); + + await BusyWait.Until(() => TestFlow.ReceivedMyMessage is not null, maxWait: TimeSpan.FromSeconds(5)); + TestFlow.ReceivedMyMessage!.Value.ShouldBe("SomeMessage"); + + host.Dispose(); + } +} \ No newline at end of file diff --git a/ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Tests/TestFlowHandler.cs b/ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Tests/TestFlowHandler.cs new file mode 100644 index 0000000..7335f3a --- /dev/null +++ b/ServiceBuses/Wolverine/Cleipnir.Flows.Wolverine.Tests/TestFlowHandler.cs @@ -0,0 +1,6 @@ +namespace Cleipnir.Flows.Wolverine.Tests; + +public class TestFlowHandler(IntegrationTests.TestFlows flows) +{ + public Task Handle(IntegrationTests.MyMessage message) => flows.SendMessage(message.Value, message); +} \ No newline at end of file