diff --git a/Examples/03-FlowRequestResponse/ParallelFlowController.cs b/Examples/03-FlowRequestResponse/ParallelFlowController.cs new file mode 100644 index 0000000..2193302 --- /dev/null +++ b/Examples/03-FlowRequestResponse/ParallelFlowController.cs @@ -0,0 +1,73 @@ +using System; +using ExampleLib; +using Messaging.TapetiExample; +using Tapeti.Annotations; +using Tapeti.Flow; +using Tapeti.Flow.Annotations; + +namespace _03_FlowRequestResponse +{ + [MessageController] + [DynamicQueue("tapeti.example.03")] + public class ParallelFlowController + { + private readonly IFlowProvider flowProvider; + private readonly IExampleState exampleState; + + public string FirstQuote; + public string SecondQuote; + + + public ParallelFlowController(IFlowProvider flowProvider, IExampleState exampleState) + { + this.flowProvider = flowProvider; + this.exampleState = exampleState; + } + + + [Start] + public IYieldPoint StartFlow() + { + return flowProvider.YieldWithParallelRequest() + .AddRequestSync( + new QuoteRequestMessage + { + Amount = 1 + }, + HandleFirstQuoteResponse) + .AddRequestSync( + new QuoteRequestMessage + { + Amount = 2 + }, + HandleSecondQuoteResponse) + .YieldSync(AllQuotesReceived); + } + + + [Continuation] + public void HandleFirstQuoteResponse(QuoteResponseMessage message) + { + Console.WriteLine("[ParallelFlowController] First quote response received"); + FirstQuote = message.Quote; + } + + + [Continuation] + public void HandleSecondQuoteResponse(QuoteResponseMessage message) + { + Console.WriteLine("[ParallelFlowController] Second quote response received"); + SecondQuote = message.Quote; + } + + + private IYieldPoint AllQuotesReceived() + { + Console.WriteLine("[ParallelFlowController] First quote: " + FirstQuote); + Console.WriteLine("[ParallelFlowController] Second quote: " + SecondQuote); + + exampleState.Done(); + return flowProvider.End(); + } + } +} diff --git a/Examples/03-FlowRequestResponse/Program.cs b/Examples/03-FlowRequestResponse/Program.cs index 48d0938..edac429 100644 --- a/Examples/03-FlowRequestResponse/Program.cs +++ b/Examples/03-FlowRequestResponse/Program.cs @@ -42,20 +42,20 @@ namespace _03_FlowRequestResponse await dependencyResolver.Resolve().Load(); - // This creates or updates the durable queue await connection.Subscribe(); var flowStarter = dependencyResolver.Resolve(); - var startData = new SendingFlowController.StartData + var startData = new SimpleFlowController.StartData { RequestStartTime = DateTime.Now, Amount = 1 }; - await flowStarter.Start(c => c.StartFlow, startData); + await flowStarter.Start(c => c.StartFlow, startData); + await flowStarter.Start(c => c.StartFlow); // Wait for the controller to signal that the message has been received diff --git a/Examples/03-FlowRequestResponse/SendingFlowController.cs b/Examples/03-FlowRequestResponse/SimpleFlowController.cs similarity index 72% rename from Examples/03-FlowRequestResponse/SendingFlowController.cs rename to Examples/03-FlowRequestResponse/SimpleFlowController.cs index 0678915..1726e40 100644 --- a/Examples/03-FlowRequestResponse/SendingFlowController.cs +++ b/Examples/03-FlowRequestResponse/SimpleFlowController.cs @@ -9,7 +9,7 @@ namespace _03_FlowRequestResponse { [MessageController] [DynamicQueue("tapeti.example.03")] - public class SendingFlowController + public class SimpleFlowController { private readonly IFlowProvider flowProvider; private readonly IExampleState exampleState; @@ -32,7 +32,7 @@ namespace _03_FlowRequestResponse public DateTime RequestStartTime; - public SendingFlowController(IFlowProvider flowProvider, IExampleState exampleState) + public SimpleFlowController(IFlowProvider flowProvider, IExampleState exampleState) { this.flowProvider = flowProvider; this.exampleState = exampleState; @@ -58,11 +58,11 @@ namespace _03_FlowRequestResponse public IYieldPoint HandleQuoteResponse(QuoteResponseMessage message) { if (nonPersistentState) - Console.WriteLine("This is not supposed to show. NonPersistentState should not be retained. Someone please check http://www.hasthelargehadroncolliderdestroyedtheworldyet.com."); + Console.WriteLine("[SimpleFlowController] This is not supposed to show. NonPersistentState should not be retained. Someone please check http://www.hasthelargehadroncolliderdestroyedtheworldyet.com."); - Console.WriteLine("Request start: " + RequestStartTime.ToLongTimeString()); - Console.WriteLine("Response time: " + DateTime.Now.ToLongTimeString()); - Console.WriteLine("Quote: " + message.Quote); + Console.WriteLine("[SimpleFlowController] Request start: " + RequestStartTime.ToLongTimeString()); + Console.WriteLine("[SimpleFlowController] Response time: " + DateTime.Now.ToLongTimeString()); + Console.WriteLine("[SimpleFlowController] Quote: " + message.Quote); exampleState.Done(); diff --git a/Examples/04-Transient/04-Transient.csproj b/Examples/04-Transient/04-Transient.csproj new file mode 100644 index 0000000..bb077b6 --- /dev/null +++ b/Examples/04-Transient/04-Transient.csproj @@ -0,0 +1,22 @@ + + + + Exe + netcoreapp2.1 + _04_Transient + + + + + + + + + + + + + + + + diff --git a/Examples/04-Transient/Program.cs b/Examples/04-Transient/Program.cs new file mode 100644 index 0000000..18b84f9 --- /dev/null +++ b/Examples/04-Transient/Program.cs @@ -0,0 +1,55 @@ +using System; +using System.Threading.Tasks; +using ExampleLib; +using Messaging.TapetiExample; +using SimpleInjector; +using Tapeti; +using Tapeti.DataAnnotations; +using Tapeti.Default; +using Tapeti.SimpleInjector; +using Tapeti.Transient; + +namespace _04_Transient +{ + public class Program + { + public static void Main(string[] args) + { + var container = new Container(); + var dependencyResolver = new SimpleInjectorDependencyResolver(container); + + container.Register(); + + var helper = new ExampleConsoleApp(dependencyResolver); + helper.Run(MainAsync); + } + + + internal static async Task MainAsync(IDependencyResolver dependencyResolver, Func waitForDone) + { + var config = new TapetiConfig(dependencyResolver) + .WithDataAnnotations() + .WithTransient(TimeSpan.FromSeconds(5), "tapeti.example.04.transient") + .RegisterAllControllers() + .Build(); + + + using (var connection = new TapetiConnection(config)) + { + await connection.Subscribe(); + + + Console.WriteLine("Sending request..."); + + var transientPublisher = dependencyResolver.Resolve(); + var response = await transientPublisher.RequestResponse( + new LoggedInUsersRequestMessage()); + + Console.WriteLine("Response: " + response.Count); + + + // Unlike the other example, there is no need to call waitForDone, once we're here the response has been handled. + } + } + } +} diff --git a/Examples/04-Transient/UsersMessageController.cs b/Examples/04-Transient/UsersMessageController.cs new file mode 100644 index 0000000..5565c49 --- /dev/null +++ b/Examples/04-Transient/UsersMessageController.cs @@ -0,0 +1,24 @@ +using System; +using System.Threading.Tasks; +using Messaging.TapetiExample; +using Tapeti.Annotations; + +namespace _04_Transient +{ + [MessageController] + [DynamicQueue("tapeti.example.04")] + public class UsersMessageController + { + // No publisher required, responses can simply be returned + public async Task HandleQuoteRequest(LoggedInUsersRequestMessage message) + { + // Simulate the response taking some time + await Task.Delay(1000); + + return new LoggedInUsersResponseMessage + { + Count = new Random().Next(0, 100) + }; + } + } +} diff --git a/Examples/Messaging.TapetiExample/LoggedInUsersRequestMessage.cs b/Examples/Messaging.TapetiExample/LoggedInUsersRequestMessage.cs new file mode 100644 index 0000000..5fe285d --- /dev/null +++ b/Examples/Messaging.TapetiExample/LoggedInUsersRequestMessage.cs @@ -0,0 +1,15 @@ +using Tapeti.Annotations; + +namespace Messaging.TapetiExample +{ + [Request(Response = typeof(LoggedInUsersResponseMessage))] + public class LoggedInUsersRequestMessage + { + } + + + public class LoggedInUsersResponseMessage + { + public int Count { get; set; } + } +} diff --git a/Tapeti.sln b/Tapeti.sln index be24534..de43216 100644 --- a/Tapeti.sln +++ b/Tapeti.sln @@ -27,15 +27,17 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tapeti.DataAnnotations.Exte EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{266B9B94-A4D2-41C2-860C-24A7C3B63B56}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "01-PublishSubscribe", "Examples\01-PublishSubscribe\01-PublishSubscribe.csproj", "{8350A0AB-F0EE-48CF-9CA6-6019467101CF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "01-PublishSubscribe", "Examples\01-PublishSubscribe\01-PublishSubscribe.csproj", "{8350A0AB-F0EE-48CF-9CA6-6019467101CF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExampleLib", "Examples\ExampleLib\ExampleLib.csproj", "{F3B38753-06B4-4932-84B4-A07692AD802D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExampleLib", "Examples\ExampleLib\ExampleLib.csproj", "{F3B38753-06B4-4932-84B4-A07692AD802D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Messaging.TapetiExample", "Examples\Messaging.TapetiExample\Messaging.TapetiExample.csproj", "{D24120D4-50A2-44B6-A4EA-6ADAAEBABA84}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Messaging.TapetiExample", "Examples\Messaging.TapetiExample\Messaging.TapetiExample.csproj", "{D24120D4-50A2-44B6-A4EA-6ADAAEBABA84}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "02-DeclareDurableQueues", "Examples\02-DeclareDurableQueues\02-DeclareDurableQueues.csproj", "{85511282-EF91-4B56-B7DC-9E8706556D6E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02-DeclareDurableQueues", "Examples\02-DeclareDurableQueues\02-DeclareDurableQueues.csproj", "{85511282-EF91-4B56-B7DC-9E8706556D6E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "03-FlowRequestResponse", "Examples\03-FlowRequestResponse\03-FlowRequestResponse.csproj", "{463A12CE-E221-450D-ADEA-91A599612DFA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "03-FlowRequestResponse", "Examples\03-FlowRequestResponse\03-FlowRequestResponse.csproj", "{463A12CE-E221-450D-ADEA-91A599612DFA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "04-Transient", "Examples\04-Transient\04-Transient.csproj", "{46DFC131-A398-435F-A7DF-3C41B656BF11}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -107,6 +109,10 @@ Global {463A12CE-E221-450D-ADEA-91A599612DFA}.Debug|Any CPU.Build.0 = Debug|Any CPU {463A12CE-E221-450D-ADEA-91A599612DFA}.Release|Any CPU.ActiveCfg = Release|Any CPU {463A12CE-E221-450D-ADEA-91A599612DFA}.Release|Any CPU.Build.0 = Release|Any CPU + {46DFC131-A398-435F-A7DF-3C41B656BF11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {46DFC131-A398-435F-A7DF-3C41B656BF11}.Debug|Any CPU.Build.0 = Debug|Any CPU + {46DFC131-A398-435F-A7DF-3C41B656BF11}.Release|Any CPU.ActiveCfg = Release|Any CPU + {46DFC131-A398-435F-A7DF-3C41B656BF11}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -117,6 +123,7 @@ Global {D24120D4-50A2-44B6-A4EA-6ADAAEBABA84} = {266B9B94-A4D2-41C2-860C-24A7C3B63B56} {85511282-EF91-4B56-B7DC-9E8706556D6E} = {266B9B94-A4D2-41C2-860C-24A7C3B63B56} {463A12CE-E221-450D-ADEA-91A599612DFA} = {266B9B94-A4D2-41C2-860C-24A7C3B63B56} + {46DFC131-A398-435F-A7DF-3C41B656BF11} = {266B9B94-A4D2-41C2-860C-24A7C3B63B56} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {B09CC2BF-B2AF-4CB6-8728-5D1D8E5C50FA}