Browse Source

use file-scoped namespacing for clientSmulation module

pull/10696/head
Ahmet Çotur 5 years ago
parent
commit
3bcb45c934
  1. 11
      modules/client-simulation/demo/Volo.ClientSimulation.Demo/BrandingProvider.cs
  2. 59
      modules/client-simulation/demo/Volo.ClientSimulation.Demo/ClientSimulationDemoModule.cs
  3. 11
      modules/client-simulation/demo/Volo.ClientSimulation.Demo/Controllers/HomeController.cs
  4. 67
      modules/client-simulation/demo/Volo.ClientSimulation.Demo/Program.cs
  5. 17
      modules/client-simulation/demo/Volo.ClientSimulation.Demo/Scenarios/DemoScenario.cs
  6. 19
      modules/client-simulation/demo/Volo.ClientSimulation.Demo/Startup.cs
  7. 25
      modules/client-simulation/src/Volo.ClientSimulation.Web/ClientSimulationWebModule.cs
  8. 13
      modules/client-simulation/src/Volo.ClientSimulation.Web/Pages/ClientSimulation/Index.cshtml.cs
  9. 49
      modules/client-simulation/src/Volo.ClientSimulation.Web/Pages/ClientSimulation/SimulationArea.cshtml.cs
  10. 27
      modules/client-simulation/src/Volo.ClientSimulation.Web/Properties/launchSettings.json
  11. 15
      modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/ClientSimulationModule.cs
  12. 15
      modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/ClientSimulationOptions.cs
  13. 120
      modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Clients/Client.cs
  14. 15
      modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Clients/ClientState.cs
  15. 21
      modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Clients/IClient.cs
  16. 25
      modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/ScenarioConfiguration.cs
  17. 131
      modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Scenarios/Scenario.cs
  18. 29
      modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Scenarios/ScenarioExecutionContext.cs
  19. 177
      modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Scenarios/ScenarioStep.cs
  20. 41
      modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Scenarios/SleepScenarioStep.cs
  21. 202
      modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Simulation.cs
  22. 15
      modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/SimulationState.cs
  23. 15
      modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Snapshot/ClientSnapshot.cs
  24. 17
      modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Snapshot/ScenarioSnapshot.cs
  25. 29
      modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Snapshot/ScenarioStepSnapshot.cs
  26. 27
      modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Snapshot/ScenarioStepSummarySnapshot.cs
  27. 15
      modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Snapshot/ScenarioSummarySnapshot.cs
  28. 91
      modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Snapshot/SimulationSnapshot.cs

11
modules/client-simulation/demo/Volo.ClientSimulation.Demo/BrandingProvider.cs

@ -1,11 +1,10 @@
using Volo.Abp.Ui.Branding; using Volo.Abp.Ui.Branding;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
namespace Volo.ClientSimulation.Demo namespace Volo.ClientSimulation.Demo;
[Dependency(ReplaceServices = true)]
public class BrandingProvider : DefaultBrandingProvider
{ {
[Dependency(ReplaceServices = true)] public override string AppName => "Client Simulation";
public class BrandingProvider : DefaultBrandingProvider
{
public override string AppName => "Client Simulation";
}
} }

59
modules/client-simulation/demo/Volo.ClientSimulation.Demo/ClientSimulationDemoModule.cs

@ -8,41 +8,40 @@ using Volo.Abp.Modularity;
using Volo.ClientSimulation.Demo.Scenarios; using Volo.ClientSimulation.Demo.Scenarios;
using Volo.ClientSimulation.Scenarios; using Volo.ClientSimulation.Scenarios;
namespace Volo.ClientSimulation.Demo namespace Volo.ClientSimulation.Demo;
[DependsOn(
typeof(AbpAspNetCoreMvcUiBasicThemeModule),
typeof(AbpAutofacModule),
typeof(ClientSimulationWebModule)
)]
public class ClientSimulationDemoModule : AbpModule
{ {
[DependsOn( public override void ConfigureServices(ServiceConfigurationContext context)
typeof(AbpAspNetCoreMvcUiBasicThemeModule),
typeof(AbpAutofacModule),
typeof(ClientSimulationWebModule)
)]
public class ClientSimulationDemoModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) Configure<ClientSimulationOptions>(options =>
{
Configure<ClientSimulationOptions>(options =>
{
options.Scenarios.Add(
new ScenarioConfiguration(
typeof(DemoScenario),
clientCount: 20
)
);
});
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{ {
var app = context.GetApplicationBuilder(); options.Scenarios.Add(
var env = context.GetEnvironment(); new ScenarioConfiguration(
typeof(DemoScenario),
clientCount: 20
)
);
});
}
if (env.IsDevelopment()) public override void OnApplicationInitialization(ApplicationInitializationContext context)
{ {
app.UseDeveloperExceptionPage(); var app = context.GetApplicationBuilder();
} var env = context.GetEnvironment();
app.UseStaticFiles(); if (env.IsDevelopment())
app.UseRouting(); {
app.UseConfiguredEndpoints(); app.UseDeveloperExceptionPage();
} }
app.UseStaticFiles();
app.UseRouting();
app.UseConfiguredEndpoints();
} }
} }

11
modules/client-simulation/demo/Volo.ClientSimulation.Demo/Controllers/HomeController.cs

@ -1,13 +1,12 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc;
namespace Volo.ClientSimulation.Demo.Controllers namespace Volo.ClientSimulation.Demo.Controllers;
public class HomeController : AbpController
{ {
public class HomeController : AbpController public ActionResult Index()
{ {
public ActionResult Index() return Redirect("/ClientSimulation");
{
return Redirect("/ClientSimulation");
}
} }
} }

67
modules/client-simulation/demo/Volo.ClientSimulation.Demo/Program.cs

@ -5,43 +5,42 @@ using Microsoft.Extensions.Hosting;
using Serilog; using Serilog;
using Serilog.Events; using Serilog.Events;
namespace Volo.ClientSimulation.Demo namespace Volo.ClientSimulation.Demo;
public class Program
{ {
public class Program public static int Main(string[] args)
{ {
public static int Main(string[] args) Log.Logger = new LoggerConfiguration()
{ .MinimumLevel.Debug()
Log.Logger = new LoggerConfiguration() .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.MinimumLevel.Debug() .Enrich.FromLogContext()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information) .WriteTo.File("Logs/logs.txt")
.Enrich.FromLogContext() .CreateLogger();
.WriteTo.File("Logs/logs.txt")
.CreateLogger();
try try
{ {
Log.Information("Starting web host."); Log.Information("Starting web host.");
CreateHostBuilder(args).Build().Run(); CreateHostBuilder(args).Build().Run();
return 0; return 0;
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.Fatal(ex, "Host terminated unexpectedly!"); Log.Fatal(ex, "Host terminated unexpectedly!");
return 1; return 1;
} }
finally finally
{ {
Log.CloseAndFlush(); Log.CloseAndFlush();
}
} }
internal static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseAutofac()
.UseSerilog();
} }
internal static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseAutofac()
.UseSerilog();
} }

17
modules/client-simulation/demo/Volo.ClientSimulation.Demo/Scenarios/DemoScenario.cs

@ -2,15 +2,14 @@
using Volo.Abp; using Volo.Abp;
using Volo.ClientSimulation.Scenarios; using Volo.ClientSimulation.Scenarios;
namespace Volo.ClientSimulation.Demo.Scenarios namespace Volo.ClientSimulation.Demo.Scenarios;
public class DemoScenario : Scenario
{ {
public class DemoScenario : Scenario public DemoScenario(IServiceProvider serviceProvider) :
base(serviceProvider)
{ {
public DemoScenario(IServiceProvider serviceProvider) : AddStep(new SleepScenarioStep("Wait1", RandomHelper.GetRandom(1000, 5000)));
base(serviceProvider) AddStep(new SleepScenarioStep("Wait2", RandomHelper.GetRandom(2000, 6000)));
{
AddStep(new SleepScenarioStep("Wait1", RandomHelper.GetRandom(1000, 5000)));
AddStep(new SleepScenarioStep("Wait2", RandomHelper.GetRandom(2000, 6000)));
}
} }
} }

19
modules/client-simulation/demo/Volo.ClientSimulation.Demo/Startup.cs

@ -3,18 +3,17 @@ using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp; using Volo.Abp;
namespace Volo.ClientSimulation.Demo namespace Volo.ClientSimulation.Demo;
public class Startup
{ {
public class Startup public void ConfigureServices(IServiceCollection services)
{ {
public void ConfigureServices(IServiceCollection services) services.AddApplication<ClientSimulationDemoModule>();
{ }
services.AddApplication<ClientSimulationDemoModule>();
}
public void Configure(IApplicationBuilder app) public void Configure(IApplicationBuilder app)
{ {
app.InitializeApplication(); app.InitializeApplication();
}
} }
} }

25
modules/client-simulation/src/Volo.ClientSimulation.Web/ClientSimulationWebModule.cs

@ -3,21 +3,20 @@ using Volo.Abp.Http.Client.IdentityModel.Web;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem; using Volo.Abp.VirtualFileSystem;
namespace Volo.ClientSimulation namespace Volo.ClientSimulation;
[DependsOn(
typeof(ClientSimulationModule),
typeof(AbpHttpClientIdentityModelWebModule),
typeof(AbpAspNetCoreMvcUiThemeSharedModule)
)]
public class ClientSimulationWebModule : AbpModule
{ {
[DependsOn( public override void ConfigureServices(ServiceConfigurationContext context)
typeof(ClientSimulationModule),
typeof(AbpHttpClientIdentityModelWebModule),
typeof(AbpAspNetCoreMvcUiThemeSharedModule)
)]
public class ClientSimulationWebModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) Configure<AbpVirtualFileSystemOptions>(options =>
{ {
Configure<AbpVirtualFileSystemOptions>(options => options.FileSets.AddEmbedded<ClientSimulationWebModule>("Volo.ClientSimulation");
{ });
options.FileSets.AddEmbedded<ClientSimulationWebModule>("Volo.ClientSimulation");
});
}
} }
} }

13
modules/client-simulation/src/Volo.ClientSimulation.Web/Pages/ClientSimulation/Index.cshtml.cs

@ -2,13 +2,12 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
namespace Volo.ClientSimulation.Pages.ClientSimulation namespace Volo.ClientSimulation.Pages.ClientSimulation;
public class IndexModel : PageModel
{ {
public class IndexModel : PageModel public virtual Task<IActionResult> OnGetAsync()
{ {
public virtual Task<IActionResult> OnGetAsync() return Task.FromResult<IActionResult>(Page());
{
return Task.FromResult<IActionResult>(Page());
}
} }
} }

49
modules/client-simulation/src/Volo.ClientSimulation.Web/Pages/ClientSimulation/SimulationArea.cshtml.cs

@ -3,35 +3,34 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
using Volo.ClientSimulation.Snapshot; using Volo.ClientSimulation.Snapshot;
namespace Volo.ClientSimulation.Pages.ClientSimulation namespace Volo.ClientSimulation.Pages.ClientSimulation;
public class SimulationAreaModel : PageModel
{ {
public class SimulationAreaModel : PageModel public SimulationSnapshot Snapshot { get; private set; }
{
public SimulationSnapshot Snapshot { get; private set; }
protected Simulation Simulation { get; } protected Simulation Simulation { get; }
public SimulationAreaModel(Simulation simulation) public SimulationAreaModel(Simulation simulation)
{ {
Simulation = simulation; Simulation = simulation;
} }
public virtual Task<IActionResult> OnGetAsync() public virtual Task<IActionResult> OnGetAsync()
{ {
Snapshot = Simulation.CreateSnapshot(); Snapshot = Simulation.CreateSnapshot();
return Task.FromResult<IActionResult>(Page()); return Task.FromResult<IActionResult>(Page());
} }
public virtual async Task<IActionResult> OnPostStartAsync() public virtual async Task<IActionResult> OnPostStartAsync()
{ {
Simulation.Start(); Simulation.Start();
return new NoContentResult(); return new NoContentResult();
} }
public virtual async Task<IActionResult> OnPostStopAsync() public virtual async Task<IActionResult> OnPostStopAsync()
{ {
Simulation.Stop(); Simulation.Stop();
return new NoContentResult(); return new NoContentResult();
}
} }
} }

27
modules/client-simulation/src/Volo.ClientSimulation.Web/Properties/launchSettings.json

@ -0,0 +1,27 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:50482/",
"sslPort": 44319
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Volo.ClientSimulation.Web": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:5001;http://localhost:5000"
}
}
}

15
modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/ClientSimulationModule.cs

@ -1,13 +1,12 @@
using Volo.Abp.Http.Client.IdentityModel; using Volo.Abp.Http.Client.IdentityModel;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
namespace Volo.ClientSimulation namespace Volo.ClientSimulation;
[DependsOn(
typeof(AbpHttpClientIdentityModelModule)
)]
public class ClientSimulationModule : AbpModule
{ {
[DependsOn(
typeof(AbpHttpClientIdentityModelModule)
)]
public class ClientSimulationModule : AbpModule
{
}
} }

15
modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/ClientSimulationOptions.cs

@ -1,14 +1,13 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace Volo.ClientSimulation namespace Volo.ClientSimulation;
public class ClientSimulationOptions
{ {
public class ClientSimulationOptions public List<ScenarioConfiguration> Scenarios { get; }
{
public List<ScenarioConfiguration> Scenarios { get; }
public ClientSimulationOptions() public ClientSimulationOptions()
{ {
Scenarios = new List<ScenarioConfiguration>(); Scenarios = new List<ScenarioConfiguration>();
}
} }
} }

120
modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Clients/Client.cs

@ -6,96 +6,94 @@ using Volo.Abp.Threading;
using Volo.ClientSimulation.Scenarios; using Volo.ClientSimulation.Scenarios;
using Volo.ClientSimulation.Snapshot; using Volo.ClientSimulation.Snapshot;
namespace Volo.ClientSimulation.Clients namespace Volo.ClientSimulation.Clients;
public class Client : IClient, ITransientDependency
{ {
public class Client : IClient, ITransientDependency public event EventHandler Stopped;
{
public event EventHandler Stopped;
public ClientState State public ClientState State {
{ get => _state;
get => _state; private set => _state = value;
private set => _state = value; }
} private volatile ClientState _state;
private volatile ClientState _state;
protected Scenario Scenario { get; private set; } protected Scenario Scenario { get; private set; }
protected object SyncLock { get; } = new object(); protected object SyncLock { get; } = new object();
protected Thread ClientThread; protected Thread ClientThread;
public void Initialize(Scenario scenario) public void Initialize(Scenario scenario)
{
lock (SyncLock)
{ {
lock (SyncLock) if (State != ClientState.Stopped)
{ {
if (State != ClientState.Stopped) throw new UserFriendlyException($"Client should be stopped to be able to initialize it. Current state is '{State}'.");
{
throw new UserFriendlyException($"Client should be stopped to be able to initialize it. Current state is '{State}'.");
}
Scenario = scenario;
} }
Scenario = scenario;
} }
}
public void Start() public void Start()
{
lock (SyncLock)
{ {
lock (SyncLock) if (State != ClientState.Stopped)
{ {
if (State != ClientState.Stopped) throw new UserFriendlyException($"Client should be stopped to be able to start it. Current state is '{State}'.");
{ }
throw new UserFriendlyException($"Client should be stopped to be able to start it. Current state is '{State}'.");
}
State = ClientState.Running; State = ClientState.Running;
Scenario.Reset(); Scenario.Reset();
ClientThread = new Thread(Run); ClientThread = new Thread(Run);
ClientThread.Start(); ClientThread.Start();
}
} }
}
public void Stop() public void Stop()
{
lock (SyncLock)
{ {
lock (SyncLock) if (State != ClientState.Running)
{ {
if (State != ClientState.Running) return;
{
return;
}
State = ClientState.Stopping;
} }
State = ClientState.Stopping;
} }
}
public ClientSnapshot CreateSnapshot() public ClientSnapshot CreateSnapshot()
{
lock (SyncLock)
{ {
lock (SyncLock) return new ClientSnapshot
{ {
return new ClientSnapshot State = State,
{ Scenario = Scenario.CreateSnapshot()
State = State, };
Scenario = Scenario.CreateSnapshot()
};
}
} }
}
private void Run() private void Run()
{
while (true)
{ {
while (true) lock (SyncLock)
{ {
lock (SyncLock) if (State != ClientState.Running)
{ {
if (State != ClientState.Running) State = ClientState.Stopped;
{ ClientThread = null;
State = ClientState.Stopped; Stopped.InvokeSafely(this);
ClientThread = null; break;
Stopped.InvokeSafely(this);
break;
}
} }
AsyncHelper.RunSync(() => Scenario.ProceedAsync());
} }
AsyncHelper.RunSync(() => Scenario.ProceedAsync());
} }
} }
} }

15
modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Clients/ClientState.cs

@ -1,9 +1,8 @@
namespace Volo.ClientSimulation.Clients namespace Volo.ClientSimulation.Clients;
public enum ClientState
{ {
public enum ClientState Stopped,
{ Running,
Stopped, Stopping
Running, }
Stopping
}
}

21
modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Clients/IClient.cs

@ -2,20 +2,19 @@
using Volo.ClientSimulation.Scenarios; using Volo.ClientSimulation.Scenarios;
using Volo.ClientSimulation.Snapshot; using Volo.ClientSimulation.Snapshot;
namespace Volo.ClientSimulation.Clients namespace Volo.ClientSimulation.Clients;
public interface IClient
{ {
public interface IClient event EventHandler Stopped;
{
event EventHandler Stopped;
ClientState State { get; } ClientState State { get; }
void Initialize(Scenario scenario); void Initialize(Scenario scenario);
void Start(); void Start();
void Stop(); void Stop();
ClientSnapshot CreateSnapshot(); ClientSnapshot CreateSnapshot();
} }
}

25
modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/ScenarioConfiguration.cs

@ -1,19 +1,18 @@
using System; using System;
namespace Volo.ClientSimulation namespace Volo.ClientSimulation;
public class ScenarioConfiguration
{ {
public class ScenarioConfiguration public Type ScenarioType { get; }
{
public Type ScenarioType { get; }
public int ClientCount { get; } public int ClientCount { get; }
public ScenarioConfiguration( public ScenarioConfiguration(
Type scenarioType, Type scenarioType,
int clientCount = 1) int clientCount = 1)
{ {
ScenarioType = scenarioType; ScenarioType = scenarioType;
ClientCount = clientCount; ClientCount = clientCount;
}
} }
} }

131
modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Scenarios/Scenario.cs

@ -6,97 +6,94 @@ using System.Threading.Tasks;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.ClientSimulation.Snapshot; using Volo.ClientSimulation.Snapshot;
namespace Volo.ClientSimulation.Scenarios namespace Volo.ClientSimulation.Scenarios;
public abstract class Scenario : ITransientDependency
{ {
public abstract class Scenario : ITransientDependency protected List<ScenarioStep> Steps { get; }
{
protected List<ScenarioStep> Steps { get; }
protected ScenarioStep CurrentStep protected ScenarioStep CurrentStep {
{ get {
get CheckStepCount();
{ return Steps[CurrentStepIndex];
CheckStepCount();
return Steps[CurrentStepIndex];
}
} }
}
protected int CurrentStepIndex { get; set; } protected int CurrentStepIndex { get; set; }
protected ScenarioExecutionContext ExecutionContext { get; } protected ScenarioExecutionContext ExecutionContext { get; }
protected Scenario(IServiceProvider serviceProvider) protected Scenario(IServiceProvider serviceProvider)
{ {
ExecutionContext = new ScenarioExecutionContext(serviceProvider); ExecutionContext = new ScenarioExecutionContext(serviceProvider);
Steps = new List<ScenarioStep>(); Steps = new List<ScenarioStep>();
} }
public virtual string GetDisplayText()
{
var displayNameAttr = GetType()
.GetCustomAttributes(true)
.OfType<DisplayNameAttribute>()
.FirstOrDefault();
public virtual string GetDisplayText() if (displayNameAttr != null)
{ {
var displayNameAttr = GetType() return displayNameAttr.DisplayName;
.GetCustomAttributes(true)
.OfType<DisplayNameAttribute>()
.FirstOrDefault();
if (displayNameAttr != null)
{
return displayNameAttr.DisplayName;
}
return GetType()
.Name
.RemovePostFix(nameof(Scenario));
} }
public virtual async Task ProceedAsync() return GetType()
{ .Name
CheckStepCount(); .RemovePostFix(nameof(Scenario));
}
await Steps[CurrentStepIndex].RunAsync(ExecutionContext); public virtual async Task ProceedAsync()
{
CheckStepCount();
CurrentStepIndex++; await Steps[CurrentStepIndex].RunAsync(ExecutionContext);
if (CurrentStepIndex >= Steps.Count) CurrentStepIndex++;
{
CurrentStepIndex = 0;
}
}
public void Reset() if (CurrentStepIndex >= Steps.Count)
{ {
CurrentStepIndex = 0; CurrentStepIndex = 0;
foreach (var step in Steps)
{
step.Reset();
}
ExecutionContext.Reset();
} }
}
public ScenarioSnapshot CreateSnapshot() public void Reset()
{
CurrentStepIndex = 0;
foreach (var step in Steps)
{ {
return new ScenarioSnapshot step.Reset();
{
DisplayText = GetDisplayText(),
Steps = Steps.Select(s => s.CreateSnapshot()).ToList(),
CurrentStep = CurrentStep.CreateSnapshot()
};
} }
protected void AddStep(ScenarioStep step) ExecutionContext.Reset();
}
public ScenarioSnapshot CreateSnapshot()
{
return new ScenarioSnapshot
{ {
Steps.Add(step); DisplayText = GetDisplayText(),
} Steps = Steps.Select(s => s.CreateSnapshot()).ToList(),
CurrentStep = CurrentStep.CreateSnapshot()
};
}
private void CheckStepCount() protected void AddStep(ScenarioStep step)
{
Steps.Add(step);
}
private void CheckStepCount()
{
if (Steps.Count <= 0)
{ {
if (Steps.Count <= 0) throw new ApplicationException(
{ $"No Steps added to the scenario '{GetDisplayText()}'"
throw new ApplicationException( );
$"No Steps added to the scenario '{GetDisplayText()}'"
);
}
} }
} }
} }

29
modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Scenarios/ScenarioExecutionContext.cs

@ -1,23 +1,22 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Volo.ClientSimulation.Scenarios namespace Volo.ClientSimulation.Scenarios;
public class ScenarioExecutionContext
{ {
public class ScenarioExecutionContext public IServiceProvider ServiceProvider { get; }
{
public IServiceProvider ServiceProvider { get; }
public Dictionary<string, object> Properties { get; } public Dictionary<string, object> Properties { get; }
public ScenarioExecutionContext(IServiceProvider serviceProvider) public ScenarioExecutionContext(IServiceProvider serviceProvider)
{ {
ServiceProvider = serviceProvider; ServiceProvider = serviceProvider;
Properties = new Dictionary<string, object>(); Properties = new Dictionary<string, object>();
} }
public virtual void Reset() public virtual void Reset()
{ {
Properties.Clear(); Properties.Clear();
}
} }
} }

177
modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Scenarios/ScenarioStep.cs

@ -7,119 +7,118 @@ using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.ClientSimulation.Snapshot; using Volo.ClientSimulation.Snapshot;
namespace Volo.ClientSimulation.Scenarios namespace Volo.ClientSimulation.Scenarios;
public abstract class ScenarioStep
{ {
public abstract class ScenarioStep protected int ExecutionCount;
protected int SuccessCount;
protected int FailCount;
protected double TotalExecutionDuration;
protected double MinExecutionDuration;
protected double MaxExecutionDuration;
protected double LastExecutionDuration;
public async Task RunAsync(ScenarioExecutionContext context)
{ {
protected int ExecutionCount; await BeforeExecuteAsync(context);
protected int SuccessCount;
protected int FailCount;
protected double TotalExecutionDuration;
protected double MinExecutionDuration;
protected double MaxExecutionDuration;
protected double LastExecutionDuration;
public async Task RunAsync(ScenarioExecutionContext context)
{
await BeforeExecuteAsync(context);
var stopwatch = Stopwatch.StartNew(); var stopwatch = Stopwatch.StartNew();
try try
{ {
await ExecuteAsync(context); await ExecuteAsync(context);
SuccessCount++;
LastExecutionDuration = stopwatch.Elapsed.TotalMilliseconds; SuccessCount++;
TotalExecutionDuration += LastExecutionDuration; LastExecutionDuration = stopwatch.Elapsed.TotalMilliseconds;
if (MinExecutionDuration > LastExecutionDuration) TotalExecutionDuration += LastExecutionDuration;
{
MinExecutionDuration = LastExecutionDuration;
}
if (MaxExecutionDuration < LastExecutionDuration) if (MinExecutionDuration > LastExecutionDuration)
{
MaxExecutionDuration = LastExecutionDuration;
}
}
catch(Exception ex)
{ {
FailCount++; MinExecutionDuration = LastExecutionDuration;
context
.ServiceProvider
.GetService<ILogger<ScenarioStep>>()
.LogException(ex);
} }
finally
{
stopwatch.Stop();
ExecutionCount++; if (MaxExecutionDuration < LastExecutionDuration)
{
MaxExecutionDuration = LastExecutionDuration;
} }
await AfterExecuteAsync(context);
} }
catch (Exception ex)
{
FailCount++;
protected virtual Task BeforeExecuteAsync(ScenarioExecutionContext context) context
.ServiceProvider
.GetService<ILogger<ScenarioStep>>()
.LogException(ex);
}
finally
{ {
return Task.CompletedTask; stopwatch.Stop();
ExecutionCount++;
} }
protected abstract Task ExecuteAsync(ScenarioExecutionContext context); await AfterExecuteAsync(context);
}
protected virtual Task AfterExecuteAsync(ScenarioExecutionContext context) protected virtual Task BeforeExecuteAsync(ScenarioExecutionContext context)
{ {
return Task.CompletedTask; return Task.CompletedTask;
} }
public virtual string GetDisplayText() protected abstract Task ExecuteAsync(ScenarioExecutionContext context);
{
var displayNameAttr = GetType()
.GetCustomAttributes(true)
.OfType<DisplayNameAttribute>()
.FirstOrDefault();
if (displayNameAttr != null) protected virtual Task AfterExecuteAsync(ScenarioExecutionContext context)
{ {
return displayNameAttr.DisplayName; return Task.CompletedTask;
} }
return GetType() public virtual string GetDisplayText()
.Name {
.RemovePostFix(nameof(ScenarioStep)); var displayNameAttr = GetType()
} .GetCustomAttributes(true)
.OfType<DisplayNameAttribute>()
.FirstOrDefault();
public ScenarioStepSnapshot CreateSnapshot() if (displayNameAttr != null)
{ {
return new ScenarioStepSnapshot return displayNameAttr.DisplayName;
{
DisplayText = GetDisplayText(),
ExecutionCount = ExecutionCount,
LastExecutionDuration = LastExecutionDuration,
MaxExecutionDuration = MaxExecutionDuration,
MinExecutionDuration = MinExecutionDuration,
TotalExecutionDuration = TotalExecutionDuration,
AvgExecutionDuration = SuccessCount == 0
? 0.0
: TotalExecutionDuration / SuccessCount,
FailCount = FailCount,
SuccessCount = SuccessCount
};
} }
public virtual void Reset() return GetType()
.Name
.RemovePostFix(nameof(ScenarioStep));
}
public ScenarioStepSnapshot CreateSnapshot()
{
return new ScenarioStepSnapshot
{ {
ExecutionCount = 0; DisplayText = GetDisplayText(),
FailCount = 0; ExecutionCount = ExecutionCount,
SuccessCount = 0; LastExecutionDuration = LastExecutionDuration,
TotalExecutionDuration = 0; MaxExecutionDuration = MaxExecutionDuration,
MinExecutionDuration = 0.0; MinExecutionDuration = MinExecutionDuration,
MaxExecutionDuration = 0.0; TotalExecutionDuration = TotalExecutionDuration,
LastExecutionDuration = 0.0; AvgExecutionDuration = SuccessCount == 0
} ? 0.0
: TotalExecutionDuration / SuccessCount,
FailCount = FailCount,
SuccessCount = SuccessCount
};
}
public virtual void Reset()
{
ExecutionCount = 0;
FailCount = 0;
SuccessCount = 0;
TotalExecutionDuration = 0;
MinExecutionDuration = 0.0;
MaxExecutionDuration = 0.0;
LastExecutionDuration = 0.0;
} }
} }

41
modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Scenarios/SleepScenarioStep.cs

@ -1,29 +1,28 @@
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Volo.ClientSimulation.Scenarios namespace Volo.ClientSimulation.Scenarios;
public class SleepScenarioStep : ScenarioStep
{ {
public class SleepScenarioStep : ScenarioStep public string Name { get; }
{
public string Name { get; }
public int Duration { get; } public int Duration { get; }
public SleepScenarioStep( public SleepScenarioStep(
string name, string name,
int duration = 1000) int duration = 1000)
{ {
Name = name; Name = name;
Duration = duration; Duration = duration;
} }
protected override Task ExecuteAsync(ScenarioExecutionContext context) protected override Task ExecuteAsync(ScenarioExecutionContext context)
{ {
return Task.Delay(Duration); return Task.Delay(Duration);
} }
public override string GetDisplayText() public override string GetDisplayText()
{ {
return base.GetDisplayText() + $" ({Name})"; return base.GetDisplayText() + $" ({Name})";
}
} }
} }

202
modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Simulation.cs

@ -11,147 +11,145 @@ using Volo.ClientSimulation.Clients;
using Volo.ClientSimulation.Scenarios; using Volo.ClientSimulation.Scenarios;
using Volo.ClientSimulation.Snapshot; using Volo.ClientSimulation.Snapshot;
namespace Volo.ClientSimulation namespace Volo.ClientSimulation;
public class Simulation : ISingletonDependency, IDisposable
{ {
public class Simulation : ISingletonDependency, IDisposable public ILogger<Simulation> Logger { get; set; }
{
public ILogger<Simulation> Logger { get; set; }
public SimulationState State public SimulationState State {
{ get => _state;
get => _state; private set => _state = value;
private set => _state = value; }
} private volatile SimulationState _state;
private volatile SimulationState _state;
public List<IClient> Clients { get; } public List<IClient> Clients { get; }
protected ClientSimulationOptions Options { get; } protected ClientSimulationOptions Options { get; }
protected IServiceScopeFactory ServiceScopeFactory { get; } protected IServiceScopeFactory ServiceScopeFactory { get; }
protected IServiceScope ServiceScope { get; private set; } protected IServiceScope ServiceScope { get; private set; }
protected object SyncObj { get; } = new object(); protected object SyncObj { get; } = new object();
public Simulation( public Simulation(
IServiceScopeFactory serviceScopeFactory, IServiceScopeFactory serviceScopeFactory,
IOptions<ClientSimulationOptions> options) IOptions<ClientSimulationOptions> options)
{ {
ServiceScopeFactory = serviceScopeFactory; ServiceScopeFactory = serviceScopeFactory;
Options = options.Value; Options = options.Value;
Logger = NullLogger<Simulation>.Instance; Logger = NullLogger<Simulation>.Instance;
Clients = new List<IClient>(); Clients = new List<IClient>();
} }
public virtual void Start() public virtual void Start()
{
lock (SyncObj)
{ {
lock (SyncObj) if (State != SimulationState.Stopped)
{ {
if (State != SimulationState.Stopped) throw new UserFriendlyException($"Simulation should be stopped to be able to start. Current state is '{State}'.");
{ }
throw new UserFriendlyException($"Simulation should be stopped to be able to start. Current state is '{State}'.");
}
State = SimulationState.Starting;
try State = SimulationState.Starting;
{
DisposeResources();
ServiceScope = ServiceScopeFactory.CreateScope();
foreach (var scenarioConfiguration in Options.Scenarios) try
{ {
for (int i = 0; i < scenarioConfiguration.ClientCount; i++) DisposeResources();
{ ServiceScope = ServiceScopeFactory.CreateScope();
var scenario = (Scenario)ServiceScope.ServiceProvider.GetRequiredService(
scenarioConfiguration.ScenarioType
);
var client = ServiceScope.ServiceProvider.GetRequiredService<IClient>();
client.Stopped += Client_OnStopped;
client.Initialize(scenario);
Clients.Add(client);
}
}
foreach (var client in Clients) foreach (var scenarioConfiguration in Options.Scenarios)
{
for (int i = 0; i < scenarioConfiguration.ClientCount; i++)
{ {
client.Start(); var scenario = (Scenario)ServiceScope.ServiceProvider.GetRequiredService(
scenarioConfiguration.ScenarioType
);
var client = ServiceScope.ServiceProvider.GetRequiredService<IClient>();
client.Stopped += Client_OnStopped;
client.Initialize(scenario);
Clients.Add(client);
} }
State = SimulationState.Started;
} }
catch(Exception ex)
foreach (var client in Clients)
{ {
Logger.LogException(ex); client.Start();
State = SimulationState.Stopped;
} }
State = SimulationState.Started;
}
catch (Exception ex)
{
Logger.LogException(ex);
State = SimulationState.Stopped;
} }
} }
}
public virtual void Stop() public virtual void Stop()
{
lock (SyncObj)
{ {
lock (SyncObj) if (State != SimulationState.Started)
{ {
if (State != SimulationState.Started) throw new UserFriendlyException($"Simulation should be started to be able to stop. Current state is '{State}'.");
{ }
throw new UserFriendlyException($"Simulation should be started to be able to stop. Current state is '{State}'.");
}
State = SimulationState.Stopping; State = SimulationState.Stopping;
foreach (var client in Clients) foreach (var client in Clients)
{ {
client.Stop(); client.Stop();
}
} }
} }
}
public virtual SimulationSnapshot CreateSnapshot() public virtual SimulationSnapshot CreateSnapshot()
{ {
SimulationSnapshot snapshot; SimulationSnapshot snapshot;
lock (SyncObj) lock (SyncObj)
{
snapshot = new SimulationSnapshot
{ {
snapshot = new SimulationSnapshot State = State,
{ Clients = Clients
State = State, .Select(c => c.CreateSnapshot())
Clients = Clients .ToList()
.Select(c => c.CreateSnapshot()) };
.ToList() }
};
}
snapshot.CreateSummaries(); snapshot.CreateSummaries();
return snapshot; return snapshot;
} }
public virtual void Dispose() public virtual void Dispose()
{ {
DisposeResources(); DisposeResources();
} }
protected virtual void Client_OnStopped(object sender, EventArgs e) protected virtual void Client_OnStopped(object sender, EventArgs e)
{
lock (SyncObj)
{ {
lock (SyncObj) if (Clients.All(c => c.State == ClientState.Stopped))
{ {
if (Clients.All(c => c.State == ClientState.Stopped)) OnStopped();
{
OnStopped();
}
} }
} }
}
private void OnStopped() private void OnStopped()
{ {
State = SimulationState.Stopped; State = SimulationState.Stopped;
} }
private void DisposeResources() private void DisposeResources()
{ {
Clients.Clear(); Clients.Clear();
ServiceScope?.Dispose(); ServiceScope?.Dispose();
}
} }
} }

15
modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/SimulationState.cs

@ -1,10 +1,9 @@
namespace Volo.ClientSimulation namespace Volo.ClientSimulation;
public enum SimulationState
{ {
public enum SimulationState Stopped,
{ Starting,
Stopped, Started,
Starting, Stopping
Started,
Stopping
}
} }

15
modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Snapshot/ClientSnapshot.cs

@ -1,13 +1,12 @@
using System; using System;
using Volo.ClientSimulation.Clients; using Volo.ClientSimulation.Clients;
namespace Volo.ClientSimulation.Snapshot namespace Volo.ClientSimulation.Snapshot;
[Serializable]
public class ClientSnapshot
{ {
[Serializable] public ClientState State { get; set; }
public class ClientSnapshot
{
public ClientState State { get; set; }
public ScenarioSnapshot Scenario { get; set; } public ScenarioSnapshot Scenario { get; set; }
} }
}

17
modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Snapshot/ScenarioSnapshot.cs

@ -1,15 +1,14 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Volo.ClientSimulation.Snapshot namespace Volo.ClientSimulation.Snapshot;
[Serializable]
public class ScenarioSnapshot
{ {
[Serializable] public string DisplayText { get; set; }
public class ScenarioSnapshot
{
public string DisplayText { get; set; }
public List<ScenarioStepSnapshot> Steps { get; set; } public List<ScenarioStepSnapshot> Steps { get; set; }
public ScenarioStepSnapshot CurrentStep { get; set; } public ScenarioStepSnapshot CurrentStep { get; set; }
} }
}

29
modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Snapshot/ScenarioStepSnapshot.cs

@ -1,26 +1,25 @@
using System; using System;
namespace Volo.ClientSimulation.Snapshot namespace Volo.ClientSimulation.Snapshot;
[Serializable]
public class ScenarioStepSnapshot
{ {
[Serializable] public string DisplayText { get; set; }
public class ScenarioStepSnapshot
{
public string DisplayText { get; set; }
public int ExecutionCount { get; set; } public int ExecutionCount { get; set; }
public int SuccessCount { get; set; } public int SuccessCount { get; set; }
public int FailCount { get; set; } public int FailCount { get; set; }
public double AvgExecutionDuration { get; set; } public double AvgExecutionDuration { get; set; }
public double TotalExecutionDuration { get; set; } public double TotalExecutionDuration { get; set; }
public double MinExecutionDuration { get; set; } public double MinExecutionDuration { get; set; }
public double MaxExecutionDuration { get; set; } public double MaxExecutionDuration { get; set; }
public double LastExecutionDuration { get; set; } public double LastExecutionDuration { get; set; }
} }
}

27
modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Snapshot/ScenarioStepSummarySnapshot.cs

@ -1,24 +1,23 @@
using System; using System;
namespace Volo.ClientSimulation.Snapshot namespace Volo.ClientSimulation.Snapshot;
[Serializable]
public class ScenarioStepSummarySnapshot
{ {
[Serializable] public string DisplayText { get; set; }
public class ScenarioStepSummarySnapshot
{
public string DisplayText { get; set; }
public int ExecutionCount { get; set; } public int ExecutionCount { get; set; }
public int SuccessCount { get; set; } public int SuccessCount { get; set; }
public int FailCount { get; set; } public int FailCount { get; set; }
public double AvgExecutionDuration { get; set; } public double AvgExecutionDuration { get; set; }
public double TotalExecutionDuration { get; set; } public double TotalExecutionDuration { get; set; }
public double MinExecutionDuration { get; set; } public double MinExecutionDuration { get; set; }
public double MaxExecutionDuration { get; set; } public double MaxExecutionDuration { get; set; }
} }
}

15
modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Snapshot/ScenarioSummarySnapshot.cs

@ -1,13 +1,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Volo.ClientSimulation.Snapshot namespace Volo.ClientSimulation.Snapshot;
[Serializable]
public class ScenarioSummarySnapshot
{ {
[Serializable] public string DisplayText { get; set; }
public class ScenarioSummarySnapshot
{
public string DisplayText { get; set; }
public List<ScenarioStepSummarySnapshot> Steps { get; set; } public List<ScenarioStepSummarySnapshot> Steps { get; set; }
} }
}

91
modules/client-simulation/src/Volo.ClientSimulation/Volo/ClientSimulation/Snapshot/SimulationSnapshot.cs

@ -2,67 +2,66 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace Volo.ClientSimulation.Snapshot namespace Volo.ClientSimulation.Snapshot;
[Serializable]
public class SimulationSnapshot
{ {
[Serializable] public SimulationState State { get; set; }
public class SimulationSnapshot
{
public SimulationState State { get; set; }
public List<ClientSnapshot> Clients { get; set; } public List<ClientSnapshot> Clients { get; set; }
public List<ScenarioSummarySnapshot> Scenarios { get; set; } public List<ScenarioSummarySnapshot> Scenarios { get; set; }
public void CreateSummaries() public void CreateSummaries()
{
var scenarioDictionary = new Dictionary<string, ScenarioSummarySnapshot>();
foreach (var client in Clients)
{ {
var scenarioDictionary = new Dictionary<string, ScenarioSummarySnapshot>(); var scenarioSummary = scenarioDictionary.GetOrAdd(
client.Scenario.DisplayText,
() => new ScenarioSummarySnapshot
{
DisplayText = client.Scenario.DisplayText,
Steps = new List<ScenarioStepSummarySnapshot>()
}
);
foreach (var client in Clients) foreach (var scenarioStep in client.Scenario.Steps)
{ {
var scenarioSummary = scenarioDictionary.GetOrAdd( var scenarioStepSummary = scenarioSummary.Steps.FirstOrDefault(s => s.DisplayText == scenarioStep.DisplayText);
client.Scenario.DisplayText, if (scenarioStepSummary == null)
() => new ScenarioSummarySnapshot
{
DisplayText = client.Scenario.DisplayText,
Steps = new List<ScenarioStepSummarySnapshot>()
}
);
foreach (var scenarioStep in client.Scenario.Steps)
{ {
var scenarioStepSummary = scenarioSummary.Steps.FirstOrDefault(s => s.DisplayText == scenarioStep.DisplayText); scenarioStepSummary = new ScenarioStepSummarySnapshot
if (scenarioStepSummary == null)
{ {
scenarioStepSummary = new ScenarioStepSummarySnapshot DisplayText = scenarioStep.DisplayText
{ };
DisplayText = scenarioStep.DisplayText
};
scenarioSummary.Steps.Add(scenarioStepSummary);
}
scenarioStepSummary.ExecutionCount += scenarioStep.ExecutionCount; scenarioSummary.Steps.Add(scenarioStepSummary);
scenarioStepSummary.SuccessCount += scenarioStep.SuccessCount; }
scenarioStepSummary.FailCount += scenarioStep.FailCount;
scenarioStepSummary.TotalExecutionDuration += scenarioStep.TotalExecutionDuration;
if (scenarioStepSummary.MinExecutionDuration > scenarioStep.MinExecutionDuration) scenarioStepSummary.ExecutionCount += scenarioStep.ExecutionCount;
{ scenarioStepSummary.SuccessCount += scenarioStep.SuccessCount;
scenarioStepSummary.MinExecutionDuration = scenarioStep.MinExecutionDuration; scenarioStepSummary.FailCount += scenarioStep.FailCount;
} scenarioStepSummary.TotalExecutionDuration += scenarioStep.TotalExecutionDuration;
if (scenarioStepSummary.MaxExecutionDuration < scenarioStep.MaxExecutionDuration) if (scenarioStepSummary.MinExecutionDuration > scenarioStep.MinExecutionDuration)
{ {
scenarioStepSummary.MaxExecutionDuration = scenarioStep.MaxExecutionDuration; scenarioStepSummary.MinExecutionDuration = scenarioStep.MinExecutionDuration;
} }
scenarioStepSummary.AvgExecutionDuration = scenarioStepSummary.SuccessCount == 0 if (scenarioStepSummary.MaxExecutionDuration < scenarioStep.MaxExecutionDuration)
? 0.0 {
: scenarioStepSummary.TotalExecutionDuration / scenarioStepSummary.SuccessCount; scenarioStepSummary.MaxExecutionDuration = scenarioStep.MaxExecutionDuration;
} }
}
Scenarios = scenarioDictionary.Values.ToList(); scenarioStepSummary.AvgExecutionDuration = scenarioStepSummary.SuccessCount == 0
? 0.0
: scenarioStepSummary.TotalExecutionDuration / scenarioStepSummary.SuccessCount;
}
} }
Scenarios = scenarioDictionary.Values.ToList();
} }
} }

Loading…
Cancel
Save