-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from Particular/add-clientui
Add Main UI projects
- Loading branch information
Showing
31 changed files
with
801 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/binaries/**/* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[*.cs] | ||
|
||
# Justification: Test project | ||
dotnet_diagnostic.CA2007.severity = none | ||
|
||
# Justification: Tests don't support cancellation and don't need to forward IMessageHandlerContext.CancellationToken | ||
dotnet_diagnostic.NSB0002.severity = suggestion |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<OutputType>Exe</OutputType> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
<OutputPath>..\binaries\Billing\</OutputPath> | ||
<ApplicationIcon>failures.ico</ApplicationIcon> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\Messages\Messages.csproj" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="MassTransit.RabbitMQ" Version="8.2.3" /> | ||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> | ||
</ItemGroup> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
namespace Billing; | ||
|
||
using System.Threading.Tasks; | ||
using MassTransit; | ||
using Messages; | ||
|
||
public class OrderPlacedHandler(SimulationEffects simulationEffects) : IConsumer<OrderPlaced> | ||
{ | ||
public async Task Consume(ConsumeContext<OrderPlaced> context) | ||
{ | ||
await simulationEffects.SimulatedMessageProcessing(context.CancellationToken); | ||
|
||
var orderBilled = new OrderBilled | ||
{ | ||
OrderId = context.Message.OrderId | ||
}; | ||
|
||
await context.Publish(orderBilled); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
#pragma warning disable IDE0010 | ||
namespace Billing; | ||
|
||
using Microsoft.Extensions.Hosting; | ||
using MassTransit; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using System.Reflection; | ||
|
||
class Program | ||
{ | ||
public static IHostBuilder CreateHostBuilder(string[] args) | ||
{ | ||
var host = Host.CreateDefaultBuilder(args) | ||
.ConfigureServices((hostContext, services) => | ||
{ | ||
services.AddMassTransit(x => | ||
{ | ||
x.UsingRabbitMq((context, cfg) => | ||
{ | ||
cfg.Host("localhost", "/", h => | ||
{ | ||
h.Username("guest"); | ||
h.Password("guest"); | ||
}); | ||
|
||
cfg.ConfigureEndpoints(context); | ||
}); | ||
|
||
x.AddConfigureEndpointsCallback((name, cfg) => | ||
{ | ||
if (cfg is IRabbitMqReceiveEndpointConfigurator rmq) | ||
{ | ||
rmq.SetQuorumQueue(); | ||
} | ||
}); | ||
|
||
x.AddConsumers(Assembly.GetExecutingAssembly()); | ||
}); | ||
|
||
services.AddSingleton<SimulationEffects>(); | ||
}); | ||
|
||
return host; | ||
} | ||
|
||
static async Task Main(string[] args) | ||
{ | ||
Console.Title = "Failure rate (Billing)"; | ||
Console.SetWindowSize(65, 15); | ||
|
||
var host = CreateHostBuilder(args).Build(); | ||
await host.StartAsync(); | ||
|
||
var state = host.Services.GetRequiredService<SimulationEffects>(); | ||
await RunUserInterfaceLoop(state); | ||
} | ||
|
||
static Task RunUserInterfaceLoop(SimulationEffects state) | ||
{ | ||
while (true) | ||
{ | ||
Console.Clear(); | ||
Console.WriteLine("Billing Endpoint"); | ||
Console.WriteLine("Press F to increase the simulated failure rate"); | ||
Console.WriteLine("Press S to decrease the simulated failure rate"); | ||
Console.WriteLine("Press ESC to quit"); | ||
Console.WriteLine(); | ||
|
||
state.WriteState(Console.Out); | ||
|
||
var input = Console.ReadKey(true); | ||
|
||
switch (input.Key) | ||
{ | ||
case ConsoleKey.F: | ||
state.IncreaseFailureRate(); | ||
break; | ||
case ConsoleKey.S: | ||
state.DecreaseFailureRate(); | ||
break; | ||
case ConsoleKey.Escape: | ||
return Task.CompletedTask; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
namespace Billing; | ||
|
||
public class SimulationEffects | ||
{ | ||
public void IncreaseFailureRate() => failureRate = Math.Min(1, failureRate + FailureRateIncrement); | ||
|
||
public void DecreaseFailureRate() => failureRate = Math.Max(0, failureRate - FailureRateIncrement); | ||
|
||
public void WriteState(TextWriter output) => output.WriteLine("Failure rate: {0:P0}", failureRate); | ||
|
||
public async Task SimulatedMessageProcessing(CancellationToken cancellationToken = default) | ||
{ | ||
await Task.Delay(200, cancellationToken); | ||
|
||
if (Random.Shared.NextDouble() < failureRate) | ||
{ | ||
throw new Exception("BOOM! A failure occurred"); | ||
} | ||
} | ||
|
||
double failureRate; | ||
const double FailureRateIncrement = 0.1; | ||
} |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[*.cs] | ||
|
||
# Justification: Test project | ||
dotnet_diagnostic.CA2007.severity = none | ||
|
||
# Justification: Tests don't support cancellation and don't need to forward IMessageHandlerContext.CancellationToken | ||
dotnet_diagnostic.NSB0002.severity = suggestion |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<OutputType>Exe</OutputType> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
<OutputPath>..\binaries\ClientUI\</OutputPath> | ||
<ApplicationIcon>traffic.ico</ApplicationIcon> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="MassTransit.RabbitMQ" Version="8.2.3" /> | ||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\Messages\Messages.csproj" /> | ||
</ItemGroup> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
#pragma warning disable IDE0010 | ||
namespace ClientUI; | ||
|
||
using Microsoft.Extensions.Hosting; | ||
using MassTransit; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using System.Reflection; | ||
|
||
class Program | ||
{ | ||
public static IHostBuilder CreateHostBuilder(string[] args) | ||
{ | ||
var host = Host.CreateDefaultBuilder(args) | ||
.ConfigureServices((_, services) => | ||
{ | ||
services.AddMassTransit(x => | ||
{ | ||
x.UsingRabbitMq((context, cfg) => | ||
{ | ||
cfg.Host("localhost", "/", h => | ||
{ | ||
h.Username("guest"); | ||
h.Password("guest"); | ||
}); | ||
|
||
cfg.ConfigureEndpoints(context); | ||
}); | ||
|
||
x.AddConfigureEndpointsCallback((name, cfg) => | ||
{ | ||
if (cfg is IRabbitMqReceiveEndpointConfigurator rmq) | ||
{ | ||
rmq.SetQuorumQueue(); | ||
} | ||
}); | ||
|
||
x.AddConsumers(Assembly.GetExecutingAssembly()); | ||
}); | ||
|
||
services.AddSingleton<SimulatedCustomers>(); | ||
services.AddHostedService(p => p.GetRequiredService<SimulatedCustomers>()); | ||
}); | ||
|
||
return host; | ||
} | ||
|
||
static async Task Main(string[] args) | ||
{ | ||
Console.Title = "Load (ClientUI)"; | ||
Console.SetWindowSize(65, 15); | ||
|
||
var host = CreateHostBuilder(args).Build(); | ||
await host.StartAsync(); | ||
|
||
var customers = host.Services.GetRequiredService<SimulatedCustomers>(); | ||
|
||
await RunUserInterfaceLoop(customers); | ||
} | ||
|
||
static Task RunUserInterfaceLoop(SimulatedCustomers simulatedCustomers) | ||
{ | ||
while (true) | ||
{ | ||
Console.Clear(); | ||
Console.WriteLine("Simulating customers placing orders on a website"); | ||
Console.WriteLine("Press T to toggle High/Low traffic mode"); | ||
Console.WriteLine("Press ESC to quit"); | ||
Console.WriteLine(); | ||
|
||
simulatedCustomers.WriteState(Console.Out); | ||
|
||
var input = Console.ReadKey(true); | ||
|
||
switch (input.Key) | ||
{ | ||
case ConsoleKey.T: | ||
simulatedCustomers.ToggleTrafficMode(); | ||
break; | ||
case ConsoleKey.Escape: | ||
return Task.CompletedTask; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
namespace ClientUI; | ||
|
||
using MassTransit; | ||
using Messages; | ||
using Microsoft.Extensions.Hosting; | ||
|
||
class SimulatedCustomers(IBus _bus) : BackgroundService | ||
{ | ||
public void WriteState(TextWriter output) | ||
{ | ||
var trafficMode = highTrafficMode ? "High" : "Low"; | ||
output.WriteLine($"{trafficMode} traffic mode - sending {rate} orders / second"); | ||
} | ||
|
||
public void ToggleTrafficMode() | ||
{ | ||
highTrafficMode = !highTrafficMode; | ||
rate = highTrafficMode ? HightTrafficRate : LowTrafficRate; | ||
} | ||
|
||
Task PlaceSingleOrder(CancellationToken cancellationToken) | ||
{ | ||
var placeOrderCommand = new PlaceOrder | ||
{ | ||
OrderId = Guid.NewGuid().ToString() | ||
}; | ||
|
||
return _bus.Publish(placeOrderCommand, cancellationToken); | ||
} | ||
|
||
protected override async Task ExecuteAsync(CancellationToken cancellationToken) | ||
{ | ||
nextReset = DateTime.UtcNow.AddSeconds(1); | ||
currentIntervalCount = 0; | ||
|
||
while (!cancellationToken.IsCancellationRequested) | ||
{ | ||
var now = DateTime.UtcNow; | ||
if (now > nextReset) | ||
{ | ||
currentIntervalCount = 0; | ||
nextReset = now.AddSeconds(1); | ||
} | ||
|
||
await PlaceSingleOrder(cancellationToken); | ||
currentIntervalCount++; | ||
|
||
try | ||
{ | ||
if (currentIntervalCount >= rate) | ||
{ | ||
var delay = nextReset - DateTime.UtcNow; | ||
if (delay > TimeSpan.Zero) | ||
{ | ||
await Task.Delay(delay, cancellationToken); | ||
} | ||
} | ||
} | ||
catch (TaskCanceledException) | ||
{ | ||
break; | ||
} | ||
} | ||
} | ||
|
||
bool highTrafficMode; | ||
|
||
DateTime nextReset; | ||
int currentIntervalCount; | ||
int rate = LowTrafficRate; | ||
|
||
const int HightTrafficRate = 8; | ||
const int LowTrafficRate = 1; | ||
} |
Binary file not shown.
Oops, something went wrong.