Finally removed the old mess of a test project, all functionality should be covered by the examples
Added SpeedTest example
This commit is contained in:
parent
84ee6f090d
commit
23f86b3597
19
Examples/05-SpeedTest/05-SpeedTest.csproj
Normal file
19
Examples/05-SpeedTest/05-SpeedTest.csproj
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||||
|
<RootNamespace>_05_SpeedTest</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="SimpleInjector" Version="4.6.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Tapeti.SimpleInjector\Tapeti.SimpleInjector.csproj" />
|
||||||
|
<ProjectReference Include="..\ExampleLib\ExampleLib.csproj" />
|
||||||
|
<ProjectReference Include="..\Messaging.TapetiExample\Messaging.TapetiExample.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
7
Examples/05-SpeedTest/IMessageCounter.cs
Normal file
7
Examples/05-SpeedTest/IMessageCounter.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace _05_SpeedTest
|
||||||
|
{
|
||||||
|
public interface IMessageCounter
|
||||||
|
{
|
||||||
|
void Add();
|
||||||
|
}
|
||||||
|
}
|
140
Examples/05-SpeedTest/Program.cs
Normal file
140
Examples/05-SpeedTest/Program.cs
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using ExampleLib;
|
||||||
|
using Messaging.TapetiExample;
|
||||||
|
using SimpleInjector;
|
||||||
|
using Tapeti;
|
||||||
|
using Tapeti.Default;
|
||||||
|
using Tapeti.SimpleInjector;
|
||||||
|
|
||||||
|
namespace _05_SpeedTest
|
||||||
|
{
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
private const int MessageCount = 20000;
|
||||||
|
|
||||||
|
// This does not make a massive difference, since internally Tapeti uses a single thread
|
||||||
|
// to perform all channel operations as recommended by the RabbitMQ .NET client library.
|
||||||
|
private const int ConcurrentTasks = 20;
|
||||||
|
|
||||||
|
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
var container = new Container();
|
||||||
|
var dependencyResolver = new SimpleInjectorDependencyResolver(container);
|
||||||
|
|
||||||
|
container.Register<ILogger, ConsoleLogger>();
|
||||||
|
|
||||||
|
var helper = new ExampleConsoleApp(dependencyResolver);
|
||||||
|
helper.Run(MainAsync);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal static async Task MainAsync(IDependencyResolver dependencyResolver, Func<Task> waitForDone)
|
||||||
|
{
|
||||||
|
var container = (IDependencyContainer)dependencyResolver;
|
||||||
|
container.RegisterDefaultSingleton<IMessageCounter>(new MessageCounter(MessageCount, () =>
|
||||||
|
{
|
||||||
|
var exampleState = dependencyResolver.Resolve<IExampleState>();
|
||||||
|
exampleState.Done();
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var config = new TapetiConfig(dependencyResolver)
|
||||||
|
// On a developer test machine, this makes the difference between 2200 messages/sec and 3000 messages/sec published.
|
||||||
|
// Interesting, but only if speed is more important than guaranteed delivery.
|
||||||
|
//.DisablePublisherConfirms()
|
||||||
|
.RegisterAllControllers()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
|
||||||
|
using (var connection = new TapetiConnection(config))
|
||||||
|
{
|
||||||
|
var subscriber = await connection.Subscribe(false);
|
||||||
|
|
||||||
|
|
||||||
|
var publisher = dependencyResolver.Resolve<IPublisher>();
|
||||||
|
Console.WriteLine($"Publishing {MessageCount} messages...");
|
||||||
|
|
||||||
|
var stopwatch = new Stopwatch();
|
||||||
|
stopwatch.Start();
|
||||||
|
|
||||||
|
await PublishMessages(publisher);
|
||||||
|
|
||||||
|
stopwatch.Stop();
|
||||||
|
Console.WriteLine($"Took {stopwatch.ElapsedMilliseconds} ms, {MessageCount / (stopwatch.ElapsedMilliseconds / 1000F):F0} messages/sec");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Console.WriteLine("Consuming messages...");
|
||||||
|
await subscriber.Resume();
|
||||||
|
|
||||||
|
stopwatch.Restart();
|
||||||
|
|
||||||
|
await waitForDone();
|
||||||
|
|
||||||
|
stopwatch.Stop();
|
||||||
|
Console.WriteLine($"Took {stopwatch.ElapsedMilliseconds} ms, {MessageCount / (stopwatch.ElapsedMilliseconds / 1000F):F0} messages/sec");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal static async Task PublishMessages(IPublisher publisher)
|
||||||
|
{
|
||||||
|
var semaphore = new SemaphoreSlim(ConcurrentTasks);
|
||||||
|
var tasks = new List<Task>();
|
||||||
|
|
||||||
|
for (var i = 0; i < MessageCount; i++)
|
||||||
|
{
|
||||||
|
var item = i;
|
||||||
|
var task = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await semaphore.WaitAsync();
|
||||||
|
await publisher.Publish(new SpeedTestMessage
|
||||||
|
{
|
||||||
|
PublishCount = item
|
||||||
|
});
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
semaphore.Release();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
tasks.Add(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.WhenAll(tasks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal class MessageCounter : IMessageCounter
|
||||||
|
{
|
||||||
|
private readonly int max;
|
||||||
|
private readonly Action done;
|
||||||
|
private int count;
|
||||||
|
|
||||||
|
|
||||||
|
public MessageCounter(int max, Action done)
|
||||||
|
{
|
||||||
|
this.max = max;
|
||||||
|
this.done = done;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Add()
|
||||||
|
{
|
||||||
|
// With a prefetchcount > 1 the consumers are running in multiple threads,
|
||||||
|
// beware of this when using singletons.
|
||||||
|
if (Interlocked.Increment(ref count) == max)
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
Examples/05-SpeedTest/SpeedMessageController.cs
Normal file
23
Examples/05-SpeedTest/SpeedMessageController.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using Messaging.TapetiExample;
|
||||||
|
using Tapeti.Annotations;
|
||||||
|
|
||||||
|
namespace _05_SpeedTest
|
||||||
|
{
|
||||||
|
[MessageController]
|
||||||
|
[DynamicQueue("tapeti.example.05")]
|
||||||
|
public class SpeedMessageController
|
||||||
|
{
|
||||||
|
private readonly IMessageCounter messageCounter;
|
||||||
|
|
||||||
|
public SpeedMessageController(IMessageCounter messageCounter)
|
||||||
|
{
|
||||||
|
this.messageCounter = messageCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void HandleSpeedTestMessage(SpeedTestMessage message)
|
||||||
|
{
|
||||||
|
messageCounter.Add();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
9
Examples/Messaging.TapetiExample/SpeedTestMessage.cs
Normal file
9
Examples/Messaging.TapetiExample/SpeedTestMessage.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Messaging.TapetiExample
|
||||||
|
{
|
||||||
|
public class SpeedTestMessage
|
||||||
|
{
|
||||||
|
public int PublishCount { get; set; }
|
||||||
|
}
|
||||||
|
}
|
15
Tapeti.sln
15
Tapeti.sln
@ -15,8 +15,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tapeti.Flow.SQL", "Tapeti.F
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tapeti.SimpleInjector", "Tapeti.SimpleInjector\Tapeti.SimpleInjector.csproj", "{A190C736-E95A-4BDA-AA80-6211226DFCAD}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tapeti.SimpleInjector", "Tapeti.SimpleInjector\Tapeti.SimpleInjector.csproj", "{A190C736-E95A-4BDA-AA80-6211226DFCAD}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "Test\Test.csproj", "{1A4B7136-B7DF-41EA-BEA2-E87B4607D420}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tapeti.Tests", "Tapeti.Tests\Tapeti.Tests.csproj", "{334F3715-63CF-4D13-B09A-38E2A616D4F5}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tapeti.Tests", "Tapeti.Tests\Tapeti.Tests.csproj", "{334F3715-63CF-4D13-B09A-38E2A616D4F5}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tapeti.Serilog", "Tapeti.Serilog\Tapeti.Serilog.csproj", "{43AA5DF3-49D5-4795-A290-D6511502B564}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tapeti.Serilog", "Tapeti.Serilog\Tapeti.Serilog.csproj", "{43AA5DF3-49D5-4795-A290-D6511502B564}"
|
||||||
@ -37,7 +35,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02-DeclareDurableQueues", "
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "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
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "04-Transient", "Examples\04-Transient\04-Transient.csproj", "{46DFC131-A398-435F-A7DF-3C41B656BF11}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "04-Transient", "Examples\04-Transient\04-Transient.csproj", "{46DFC131-A398-435F-A7DF-3C41B656BF11}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "05-SpeedTest", "Examples\05-SpeedTest\05-SpeedTest.csproj", "{330D05CE-5321-4C7D-8017-2070B891289E}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@ -69,10 +69,6 @@ Global
|
|||||||
{A190C736-E95A-4BDA-AA80-6211226DFCAD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{A190C736-E95A-4BDA-AA80-6211226DFCAD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{A190C736-E95A-4BDA-AA80-6211226DFCAD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{A190C736-E95A-4BDA-AA80-6211226DFCAD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{A190C736-E95A-4BDA-AA80-6211226DFCAD}.Release|Any CPU.Build.0 = Release|Any CPU
|
{A190C736-E95A-4BDA-AA80-6211226DFCAD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{1A4B7136-B7DF-41EA-BEA2-E87B4607D420}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{1A4B7136-B7DF-41EA-BEA2-E87B4607D420}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{1A4B7136-B7DF-41EA-BEA2-E87B4607D420}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{1A4B7136-B7DF-41EA-BEA2-E87B4607D420}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{334F3715-63CF-4D13-B09A-38E2A616D4F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{334F3715-63CF-4D13-B09A-38E2A616D4F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{334F3715-63CF-4D13-B09A-38E2A616D4F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{334F3715-63CF-4D13-B09A-38E2A616D4F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{334F3715-63CF-4D13-B09A-38E2A616D4F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{334F3715-63CF-4D13-B09A-38E2A616D4F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
@ -113,6 +109,10 @@ Global
|
|||||||
{46DFC131-A398-435F-A7DF-3C41B656BF11}.Debug|Any CPU.Build.0 = 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.ActiveCfg = Release|Any CPU
|
||||||
{46DFC131-A398-435F-A7DF-3C41B656BF11}.Release|Any CPU.Build.0 = Release|Any CPU
|
{46DFC131-A398-435F-A7DF-3C41B656BF11}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{330D05CE-5321-4C7D-8017-2070B891289E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{330D05CE-5321-4C7D-8017-2070B891289E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{330D05CE-5321-4C7D-8017-2070B891289E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{330D05CE-5321-4C7D-8017-2070B891289E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -124,6 +124,7 @@ Global
|
|||||||
{85511282-EF91-4B56-B7DC-9E8706556D6E} = {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}
|
{463A12CE-E221-450D-ADEA-91A599612DFA} = {266B9B94-A4D2-41C2-860C-24A7C3B63B56}
|
||||||
{46DFC131-A398-435F-A7DF-3C41B656BF11} = {266B9B94-A4D2-41C2-860C-24A7C3B63B56}
|
{46DFC131-A398-435F-A7DF-3C41B656BF11} = {266B9B94-A4D2-41C2-860C-24A7C3B63B56}
|
||||||
|
{330D05CE-5321-4C7D-8017-2070B891289E} = {266B9B94-A4D2-41C2-860C-24A7C3B63B56}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {B09CC2BF-B2AF-4CB6-8728-5D1D8E5C50FA}
|
SolutionGuid = {B09CC2BF-B2AF-4CB6-8728-5D1D8E5C50FA}
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
|
||||||
<configuration>
|
|
||||||
<appSettings>
|
|
||||||
<add key="rabbitmq:hostname" value="localhost" />
|
|
||||||
</appSettings>
|
|
||||||
</configuration>
|
|
@ -1,81 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Tapeti.Annotations;
|
|
||||||
using Tapeti.Flow;
|
|
||||||
using Tapeti.Flow.Annotations;
|
|
||||||
|
|
||||||
// ReSharper disable UnusedMember.Global
|
|
||||||
|
|
||||||
namespace Test
|
|
||||||
{
|
|
||||||
[MessageController]
|
|
||||||
[DynamicQueue]
|
|
||||||
public class FlowEndController
|
|
||||||
{
|
|
||||||
private readonly IFlowProvider flowProvider;
|
|
||||||
|
|
||||||
public FlowEndController(IFlowProvider flowProvider)
|
|
||||||
{
|
|
||||||
this.flowProvider = flowProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Start]
|
|
||||||
public IYieldPoint StartFlow(PingMessage message)
|
|
||||||
{
|
|
||||||
Console.WriteLine("PingMessage received, calling flowProvider.End() directly");
|
|
||||||
|
|
||||||
if (DateTime.Now < new DateTime(2000, 1, 1))
|
|
||||||
{
|
|
||||||
//never true
|
|
||||||
return flowProvider
|
|
||||||
.YieldWithRequestSync<PingConfirmationRequestMessage, PingConfirmationResponseMessage>
|
|
||||||
(new PingConfirmationRequestMessage { StoredInState = "Ping:" },
|
|
||||||
HandlePingConfirmationResponse);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Continuation]
|
|
||||||
public IYieldPoint HandlePingConfirmationResponse(PingConfirmationResponseMessage msg)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Ending ping flow: " + msg.Answer);
|
|
||||||
return Finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private IYieldPoint Finish()
|
|
||||||
{
|
|
||||||
return flowProvider.End();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public class PingMessage
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
[Request(Response = typeof(PingConfirmationResponseMessage))]
|
|
||||||
public class PingConfirmationRequestMessage
|
|
||||||
{
|
|
||||||
public string StoredInState { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public class PingConfirmationResponseMessage
|
|
||||||
{
|
|
||||||
public string Answer { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public PingConfirmationResponseMessage PingConfirmation(PingConfirmationRequestMessage message)
|
|
||||||
{
|
|
||||||
Console.WriteLine(">> receive Ping (returning pong)");
|
|
||||||
|
|
||||||
return new PingConfirmationResponseMessage
|
|
||||||
{
|
|
||||||
Answer = message.StoredInState + " Pong!"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,188 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Tapeti.Annotations;
|
|
||||||
using Tapeti.Flow;
|
|
||||||
using Tapeti.Flow.Annotations;
|
|
||||||
|
|
||||||
// ReSharper disable UnusedMember.Global
|
|
||||||
|
|
||||||
namespace Test
|
|
||||||
{
|
|
||||||
[MessageController]
|
|
||||||
[DynamicQueue]
|
|
||||||
public class MarcoController
|
|
||||||
{
|
|
||||||
//private readonly IPublisher publisher;
|
|
||||||
private readonly IFlowProvider flowProvider;
|
|
||||||
//private readonly Visualizer visualizer;
|
|
||||||
|
|
||||||
// Public properties are automatically stored and retrieved while in a flow
|
|
||||||
public Guid StateTestGuid { get; set; }
|
|
||||||
|
|
||||||
public int Phase;
|
|
||||||
|
|
||||||
public MarcoController(/*IPublisher publisher, */IFlowProvider flowProvider/*, Visualizer visualizer*/)
|
|
||||||
{
|
|
||||||
//this.publisher = publisher;
|
|
||||||
this.flowProvider = flowProvider;
|
|
||||||
//this.visualizer = visualizer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Start]
|
|
||||||
public async Task<IYieldPoint> StartFlow(bool go)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Phase = " + Phase + " Starting stand-alone flow");
|
|
||||||
await Task.Delay(10);
|
|
||||||
|
|
||||||
Phase = 1;
|
|
||||||
|
|
||||||
if (go)
|
|
||||||
return flowProvider.YieldWithRequestSync<PoloConfirmationRequestMessage, PoloConfirmationResponseMessage>
|
|
||||||
(new PoloConfirmationRequestMessage(),
|
|
||||||
HandlePoloConfirmationResponse);
|
|
||||||
|
|
||||||
Console.WriteLine("Phase = " + Phase + " Ending stand-alone flow prematurely");
|
|
||||||
return flowProvider.End();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Continuation]
|
|
||||||
public IYieldPoint HandlePoloConfirmationResponse(PoloConfirmationResponseMessage msg)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Phase = " + Phase + " Handling the first response and sending the second...");
|
|
||||||
|
|
||||||
Phase = 2;
|
|
||||||
|
|
||||||
return flowProvider.YieldWithRequestSync<PoloConfirmationRequestMessage, PoloConfirmationResponseMessage>
|
|
||||||
(new PoloConfirmationRequestMessage(),
|
|
||||||
HandlePoloConfirmationResponseEnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Continuation]
|
|
||||||
public IYieldPoint HandlePoloConfirmationResponseEnd(PoloConfirmationResponseMessage msg)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Phase = " + Phase + " Handling the second response and Ending stand-alone flow");
|
|
||||||
return flowProvider.End();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Start]
|
|
||||||
public IYieldPoint TestParallelRequest()
|
|
||||||
{
|
|
||||||
Console.WriteLine(">> Marco (yielding with request)");
|
|
||||||
|
|
||||||
StateTestGuid = Guid.NewGuid();
|
|
||||||
Console.WriteLine($"Starting parallel request with StateTestGuid {StateTestGuid}");
|
|
||||||
|
|
||||||
return flowProvider.YieldWithParallelRequest()
|
|
||||||
.AddRequestSync<PoloConfirmationRequestMessage, PoloConfirmationResponseMessage>(new PoloConfirmationRequestMessage
|
|
||||||
{
|
|
||||||
StoredInState = StateTestGuid,
|
|
||||||
EnumValue = TestEnum.Value1
|
|
||||||
|
|
||||||
}, HandlePoloConfirmationResponse1)
|
|
||||||
|
|
||||||
.AddRequestSync<PoloConfirmationRequestMessage, PoloConfirmationResponseMessage>(new PoloConfirmationRequestMessage
|
|
||||||
{
|
|
||||||
StoredInState = StateTestGuid,
|
|
||||||
EnumValue = TestEnum.Value2,
|
|
||||||
OptionalEnumValue = TestEnum.Value1
|
|
||||||
}, HandlePoloConfirmationResponse2)
|
|
||||||
|
|
||||||
.YieldSync(ContinuePoloConfirmation);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Continuation]
|
|
||||||
public void HandlePoloConfirmationResponse1(PoloConfirmationResponseMessage message)
|
|
||||||
{
|
|
||||||
Console.WriteLine(">> HandlePoloConfirmationResponse1");
|
|
||||||
Console.WriteLine(message.ShouldMatchState.Equals(StateTestGuid) ? "Confirmed!" : "Oops! Mismatch!");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Continuation]
|
|
||||||
public void HandlePoloConfirmationResponse2(PoloConfirmationResponseMessage message)
|
|
||||||
{
|
|
||||||
Console.WriteLine(">> HandlePoloConfirmationResponse2");
|
|
||||||
Console.WriteLine(message.ShouldMatchState.Equals(StateTestGuid) ? "Confirmed!" : "Oops! Mismatch!");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private IYieldPoint ContinuePoloConfirmation()
|
|
||||||
{
|
|
||||||
Console.WriteLine("> ConvergePoloConfirmation (ending flow)");
|
|
||||||
return flowProvider.End();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For simple request response patterns, the return type can be used.
|
|
||||||
* This will automatically include the correlationId in the response and
|
|
||||||
* use the replyTo header of the request if provided.
|
|
||||||
*/
|
|
||||||
[DurableQueue("tapeti.test.durable")]
|
|
||||||
public async Task<PoloConfirmationResponseMessage> PoloConfirmation(PoloConfirmationRequestMessage message)
|
|
||||||
{
|
|
||||||
Console.WriteLine(">> PoloConfirmation (returning confirmation)");
|
|
||||||
await Task.Delay(100);
|
|
||||||
|
|
||||||
return new PoloConfirmationResponseMessage
|
|
||||||
{
|
|
||||||
ShouldMatchState = message.StoredInState,
|
|
||||||
EnumValue = message.EnumValue,
|
|
||||||
OptionalEnumValue = message.OptionalEnumValue
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[DynamicQueue("custom.prefix")]
|
|
||||||
public void Polo(PoloMessage message)
|
|
||||||
{
|
|
||||||
Console.WriteLine(">> Polo");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public enum TestEnum
|
|
||||||
{
|
|
||||||
Value1,
|
|
||||||
Value2
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Request(Response = typeof(PoloMessage))]
|
|
||||||
public class MarcoMessage
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public class PoloMessage
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Request(Response = typeof(PoloConfirmationResponseMessage))]
|
|
||||||
public class PoloConfirmationRequestMessage
|
|
||||||
{
|
|
||||||
[Required]
|
|
||||||
public Guid StoredInState { get; set; }
|
|
||||||
|
|
||||||
public TestEnum EnumValue;
|
|
||||||
public TestEnum? OptionalEnumValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public class PoloConfirmationResponseMessage
|
|
||||||
{
|
|
||||||
[Required]
|
|
||||||
public Guid ShouldMatchState { get; set; }
|
|
||||||
|
|
||||||
public TestEnum EnumValue;
|
|
||||||
public TestEnum? OptionalEnumValue;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
// ReSharper disable UnusedMember.Global
|
|
||||||
|
|
||||||
namespace Test
|
|
||||||
{
|
|
||||||
public class MarcoEmitter
|
|
||||||
{
|
|
||||||
//private readonly IPublisher publisher;
|
|
||||||
|
|
||||||
|
|
||||||
/*public MarcoEmitter(IPublisher publisher)
|
|
||||||
{
|
|
||||||
this.publisher = publisher;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
public async Task Run()
|
|
||||||
{
|
|
||||||
//await publisher.Publish(new MarcoMessage());
|
|
||||||
|
|
||||||
/*
|
|
||||||
var concurrent = new SemaphoreSlim(20);
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
for (var x = 0; x < 200; x++)
|
|
||||||
{
|
|
||||||
await concurrent.WaitAsync();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await publisher.Publish(new MarcoMessage());
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
concurrent.Release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await Task.Delay(200);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
await Task.Delay(1000);
|
|
||||||
}
|
|
||||||
// ReSharper disable once FunctionNeverReturns
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,89 +0,0 @@
|
|||||||
using System;
|
|
||||||
using SimpleInjector;
|
|
||||||
using Tapeti;
|
|
||||||
using Tapeti.DataAnnotations;
|
|
||||||
using Tapeti.Flow;
|
|
||||||
using Tapeti.SimpleInjector;
|
|
||||||
using System.Threading;
|
|
||||||
using Tapeti.Transient;
|
|
||||||
|
|
||||||
namespace Test
|
|
||||||
{
|
|
||||||
internal class Program
|
|
||||||
{
|
|
||||||
private static void Main()
|
|
||||||
{
|
|
||||||
// TODO logging
|
|
||||||
//try
|
|
||||||
{
|
|
||||||
var container = new Container();
|
|
||||||
container.Register<MarcoEmitter>();
|
|
||||||
container.Register<Visualizer>();
|
|
||||||
container.Register<ILogger, Tapeti.Default.ConsoleLogger>();
|
|
||||||
|
|
||||||
var config = new TapetiConfig(new SimpleInjectorDependencyResolver(container))
|
|
||||||
//.WithFlowSqlRepository("Server=localhost;Database=TapetiTest;Integrated Security=true")
|
|
||||||
.WithFlow()
|
|
||||||
.WithDataAnnotations()
|
|
||||||
.WithTransient(TimeSpan.FromSeconds(30))
|
|
||||||
.EnableDeclareDurableQueues()
|
|
||||||
.RegisterAllControllers()
|
|
||||||
//.DisablePublisherConfirms() -> you probably never want to do this if you're using Flow or want requeues when a publish fails
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
using (var connection = new TapetiConnection(config)
|
|
||||||
{
|
|
||||||
Params = new TapetiAppSettingsConnectionParams()
|
|
||||||
})
|
|
||||||
{
|
|
||||||
var flowStore = container.GetInstance<IFlowStore>();
|
|
||||||
var flowStore2 = container.GetInstance<IFlowStore>();
|
|
||||||
Console.WriteLine("IFlowHandler is singleton = " + (flowStore == flowStore2));
|
|
||||||
|
|
||||||
flowStore.Load().Wait();
|
|
||||||
|
|
||||||
connection.Connected += (sender, e) => { Console.WriteLine("Event Connected"); };
|
|
||||||
connection.Disconnected += (sender, e) => { Console.WriteLine("Event Disconnected"); };
|
|
||||||
connection.Reconnected += (sender, e) => { Console.WriteLine("Event Reconnected"); };
|
|
||||||
|
|
||||||
Console.WriteLine("Subscribing...");
|
|
||||||
var subscriber = connection.Subscribe(false).Result;
|
|
||||||
|
|
||||||
Console.WriteLine("Consuming...");
|
|
||||||
subscriber.Resume().Wait();
|
|
||||||
|
|
||||||
Console.WriteLine("Done!");
|
|
||||||
|
|
||||||
/*
|
|
||||||
var response = container.GetInstance<ITransientPublisher>()
|
|
||||||
.RequestResponse<PoloConfirmationRequestMessage, PoloConfirmationResponseMessage>(
|
|
||||||
new PoloConfirmationRequestMessage
|
|
||||||
{
|
|
||||||
StoredInState = new Guid("309088d8-9906-4ef3-bc64-56976538d3ab")
|
|
||||||
}).Result;
|
|
||||||
|
|
||||||
Console.WriteLine(response.ShouldMatchState);
|
|
||||||
*/
|
|
||||||
|
|
||||||
//connection.GetPublisher().Publish(new FlowEndController.PingMessage());
|
|
||||||
|
|
||||||
container.GetInstance<IFlowStarter>().Start<MarcoController, bool>(c => c.StartFlow, true).Wait();
|
|
||||||
container.GetInstance<IFlowStarter>().Start<MarcoController>(c => c.TestParallelRequest).Wait();
|
|
||||||
|
|
||||||
Thread.Sleep(1000);
|
|
||||||
|
|
||||||
//var emitter = container.GetInstance<MarcoEmitter>();
|
|
||||||
//emitter.Run().Wait();
|
|
||||||
|
|
||||||
Console.WriteLine("Press any Enter to continue");
|
|
||||||
Console.ReadLine();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//catch (Exception e)
|
|
||||||
{
|
|
||||||
// Console.WriteLine(e.ToString());
|
|
||||||
// Console.ReadKey();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutputType>Exe</OutputType>
|
|
||||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\Tapeti.Annotations\Tapeti.Annotations.csproj" />
|
|
||||||
<ProjectReference Include="..\Tapeti.DataAnnotations\Tapeti.DataAnnotations.csproj" />
|
|
||||||
<ProjectReference Include="..\Tapeti.Flow.SQL\Tapeti.Flow.SQL.csproj" />
|
|
||||||
<ProjectReference Include="..\Tapeti.Flow\Tapeti.Flow.csproj" />
|
|
||||||
<ProjectReference Include="..\Tapeti.SimpleInjector\Tapeti.SimpleInjector.csproj" />
|
|
||||||
<ProjectReference Include="..\Tapeti.Transient\Tapeti.Transient.csproj" />
|
|
||||||
<ProjectReference Include="..\Tapeti\Tapeti.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
@ -1,22 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
// ReSharper disable UnusedMember.Global
|
|
||||||
|
|
||||||
namespace Test
|
|
||||||
{
|
|
||||||
public class Visualizer
|
|
||||||
{
|
|
||||||
public Task VisualizeMarco()
|
|
||||||
{
|
|
||||||
Console.WriteLine("Marco!");
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task VisualizePolo()
|
|
||||||
{
|
|
||||||
Console.WriteLine("Polo!");
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user