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.DependencyInjection;
namespace Volo.ClientSimulation.Demo
namespace Volo.ClientSimulation.Demo;
[Dependency(ReplaceServices = true)]
public class BrandingProvider : DefaultBrandingProvider
{
[Dependency(ReplaceServices = true)]
public class BrandingProvider : DefaultBrandingProvider
{
public override string AppName => "Client Simulation";
}
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.Scenarios;
namespace Volo.ClientSimulation.Demo
namespace Volo.ClientSimulation.Demo;
[DependsOn(
typeof(AbpAspNetCoreMvcUiBasicThemeModule),
typeof(AbpAutofacModule),
typeof(ClientSimulationWebModule)
)]
public class ClientSimulationDemoModule : AbpModule
{
[DependsOn(
typeof(AbpAspNetCoreMvcUiBasicThemeModule),
typeof(AbpAutofacModule),
typeof(ClientSimulationWebModule)
)]
public class ClientSimulationDemoModule : AbpModule
public override void ConfigureServices(ServiceConfigurationContext context)
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<ClientSimulationOptions>(options =>
{
options.Scenarios.Add(
new ScenarioConfiguration(
typeof(DemoScenario),
clientCount: 20
)
);
});
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
Configure<ClientSimulationOptions>(options =>
{
var app = context.GetApplicationBuilder();
var env = context.GetEnvironment();
options.Scenarios.Add(
new ScenarioConfiguration(
typeof(DemoScenario),
clientCount: 20
)
);
});
}
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var env = context.GetEnvironment();
app.UseStaticFiles();
app.UseRouting();
app.UseConfiguredEndpoints();
if (env.IsDevelopment())
{
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 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.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()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.File("Logs/logs.txt")
.CreateLogger();
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.File("Logs/logs.txt")
.CreateLogger();
try
{
Log.Information("Starting web host.");
CreateHostBuilder(args).Build().Run();
return 0;
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly!");
return 1;
}
finally
{
Log.CloseAndFlush();
}
try
{
Log.Information("Starting web host.");
CreateHostBuilder(args).Build().Run();
return 0;
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly!");
return 1;
}
finally
{
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.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) :
base(serviceProvider)
{
AddStep(new SleepScenarioStep("Wait1", RandomHelper.GetRandom(1000, 5000)));
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 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)
{
app.InitializeApplication();
}
public void Configure(IApplicationBuilder app)
{
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.VirtualFileSystem;
namespace Volo.ClientSimulation
namespace Volo.ClientSimulation;
[DependsOn(
typeof(ClientSimulationModule),
typeof(AbpHttpClientIdentityModelWebModule),
typeof(AbpAspNetCoreMvcUiThemeSharedModule)
)]
public class ClientSimulationWebModule : AbpModule
{
[DependsOn(
typeof(ClientSimulationModule),
typeof(AbpHttpClientIdentityModelWebModule),
typeof(AbpAspNetCoreMvcUiThemeSharedModule)
)]
public class ClientSimulationWebModule : AbpModule
public override void ConfigureServices(ServiceConfigurationContext context)
{
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.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 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)
{
Simulation = simulation;
}
public SimulationAreaModel(Simulation simulation)
{
Simulation = simulation;
}
public virtual Task<IActionResult> OnGetAsync()
{
Snapshot = Simulation.CreateSnapshot();
return Task.FromResult<IActionResult>(Page());
}
public virtual Task<IActionResult> OnGetAsync()
{
Snapshot = Simulation.CreateSnapshot();
return Task.FromResult<IActionResult>(Page());
}
public virtual async Task<IActionResult> OnPostStartAsync()
{
Simulation.Start();
return new NoContentResult();
}
public virtual async Task<IActionResult> OnPostStartAsync()
{
Simulation.Start();
return new NoContentResult();
}
public virtual async Task<IActionResult> OnPostStopAsync()
{
Simulation.Stop();
return new NoContentResult();
}
public virtual async Task<IActionResult> OnPostStopAsync()
{
Simulation.Stop();
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.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;
namespace Volo.ClientSimulation
namespace Volo.ClientSimulation;
public class ClientSimulationOptions
{
public class ClientSimulationOptions
{
public List<ScenarioConfiguration> Scenarios { get; }
public List<ScenarioConfiguration> Scenarios { get; }
public ClientSimulationOptions()
{
Scenarios = new List<ScenarioConfiguration>();
}
public ClientSimulationOptions()
{
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.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
{
get => _state;
private set => _state = value;
}
private volatile ClientState _state;
public ClientState State {
get => _state;
private set => _state = value;
}
private volatile ClientState _state;
protected Scenario Scenario { get; private set; }
protected object SyncLock { get; } = new object();
protected Scenario Scenario { get; private set; }
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}'.");
}
Scenario = scenario;
throw new UserFriendlyException($"Client should be stopped to be able to initialize it. Current state is '{State}'.");
}
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();
ClientThread = new Thread(Run);
ClientThread.Start();
}
Scenario.Reset();
ClientThread = new Thread(Run);
ClientThread.Start();
}
}
public void Stop()
public void Stop()
{
lock (SyncLock)
{
lock (SyncLock)
if (State != ClientState.Running)
{
if (State != ClientState.Running)
{
return;
}
State = ClientState.Stopping;
return;
}
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;
Stopped.InvokeSafely(this);
break;
}
State = ClientState.Stopped;
ClientThread = null;
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,
Stopping
}
}
Stopped,
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.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;
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(
Type scenarioType,
int clientCount = 1)
{
ScenarioType = scenarioType;
ClientCount = clientCount;
}
public ScenarioConfiguration(
Type scenarioType,
int clientCount = 1)
{
ScenarioType = scenarioType;
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.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
{
get
{
CheckStepCount();
return Steps[CurrentStepIndex];
}
protected ScenarioStep CurrentStep {
get {
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)
{
ExecutionContext = new ScenarioExecutionContext(serviceProvider);
Steps = new List<ScenarioStep>();
}
protected Scenario(IServiceProvider serviceProvider)
{
ExecutionContext = new ScenarioExecutionContext(serviceProvider);
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()
.GetCustomAttributes(true)
.OfType<DisplayNameAttribute>()
.FirstOrDefault();
if (displayNameAttr != null)
{
return displayNameAttr.DisplayName;
}
return GetType()
.Name
.RemovePostFix(nameof(Scenario));
return displayNameAttr.DisplayName;
}
public virtual async Task ProceedAsync()
{
CheckStepCount();
return GetType()
.Name
.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 = 0;
}
}
CurrentStepIndex++;
public void Reset()
if (CurrentStepIndex >= Steps.Count)
{
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
{
DisplayText = GetDisplayText(),
Steps = Steps.Select(s => s.CreateSnapshot()).ToList(),
CurrentStep = CurrentStep.CreateSnapshot()
};
step.Reset();
}
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.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)
{
ServiceProvider = serviceProvider;
Properties = new Dictionary<string, object>();
}
public ScenarioExecutionContext(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
Properties = new Dictionary<string, object>();
}
public virtual void Reset()
{
Properties.Clear();
}
public virtual void Reset()
{
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 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;
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);
await BeforeExecuteAsync(context);
var stopwatch = Stopwatch.StartNew();
var stopwatch = Stopwatch.StartNew();
try
{
await ExecuteAsync(context);
SuccessCount++;
try
{
await ExecuteAsync(context);
LastExecutionDuration = stopwatch.Elapsed.TotalMilliseconds;
SuccessCount++;
TotalExecutionDuration += LastExecutionDuration;
LastExecutionDuration = stopwatch.Elapsed.TotalMilliseconds;
if (MinExecutionDuration > LastExecutionDuration)
{
MinExecutionDuration = LastExecutionDuration;
}
TotalExecutionDuration += LastExecutionDuration;
if (MaxExecutionDuration < LastExecutionDuration)
{
MaxExecutionDuration = LastExecutionDuration;
}
}
catch(Exception ex)
if (MinExecutionDuration > LastExecutionDuration)
{
FailCount++;
context
.ServiceProvider
.GetService<ILogger<ScenarioStep>>()
.LogException(ex);
MinExecutionDuration = LastExecutionDuration;
}
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)
{
return Task.CompletedTask;
}
protected virtual Task BeforeExecuteAsync(ScenarioExecutionContext context)
{
return Task.CompletedTask;
}
public virtual string GetDisplayText()
{
var displayNameAttr = GetType()
.GetCustomAttributes(true)
.OfType<DisplayNameAttribute>()
.FirstOrDefault();
protected abstract Task ExecuteAsync(ScenarioExecutionContext context);
if (displayNameAttr != null)
{
return displayNameAttr.DisplayName;
}
protected virtual Task AfterExecuteAsync(ScenarioExecutionContext context)
{
return Task.CompletedTask;
}
return GetType()
.Name
.RemovePostFix(nameof(ScenarioStep));
}
public virtual string GetDisplayText()
{
var displayNameAttr = GetType()
.GetCustomAttributes(true)
.OfType<DisplayNameAttribute>()
.FirstOrDefault();
public ScenarioStepSnapshot CreateSnapshot()
if (displayNameAttr != null)
{
return new ScenarioStepSnapshot
{
DisplayText = GetDisplayText(),
ExecutionCount = ExecutionCount,
LastExecutionDuration = LastExecutionDuration,
MaxExecutionDuration = MaxExecutionDuration,
MinExecutionDuration = MinExecutionDuration,
TotalExecutionDuration = TotalExecutionDuration,
AvgExecutionDuration = SuccessCount == 0
? 0.0
: TotalExecutionDuration / SuccessCount,
FailCount = FailCount,
SuccessCount = SuccessCount
};
return displayNameAttr.DisplayName;
}
public virtual void Reset()
return GetType()
.Name
.RemovePostFix(nameof(ScenarioStep));
}
public ScenarioStepSnapshot CreateSnapshot()
{
return new ScenarioStepSnapshot
{
ExecutionCount = 0;
FailCount = 0;
SuccessCount = 0;
TotalExecutionDuration = 0;
MinExecutionDuration = 0.0;
MaxExecutionDuration = 0.0;
LastExecutionDuration = 0.0;
}
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()
{
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;
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(
string name,
int duration = 1000)
{
Name = name;
Duration = duration;
}
public SleepScenarioStep(
string name,
int duration = 1000)
{
Name = name;
Duration = duration;
}
protected override Task ExecuteAsync(ScenarioExecutionContext context)
{
return Task.Delay(Duration);
}
protected override Task ExecuteAsync(ScenarioExecutionContext context)
{
return Task.Delay(Duration);
}
public override string GetDisplayText()
{
return base.GetDisplayText() + $" ({Name})";
}
public override string GetDisplayText()
{
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.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
{
get => _state;
private set => _state = value;
}
private volatile SimulationState _state;
public SimulationState State {
get => _state;
private set => _state = value;
}
private volatile SimulationState _state;
public List<IClient> Clients { get; }
public List<IClient> Clients { get; }
protected ClientSimulationOptions Options { get; }
protected IServiceScopeFactory ServiceScopeFactory { get; }
protected IServiceScope ServiceScope { get; private set; }
protected object SyncObj { get; } = new object();
protected ClientSimulationOptions Options { get; }
protected IServiceScopeFactory ServiceScopeFactory { get; }
protected IServiceScope ServiceScope { get; private set; }
protected object SyncObj { get; } = new object();
public Simulation(
IServiceScopeFactory serviceScopeFactory,
IOptions<ClientSimulationOptions> options)
{
ServiceScopeFactory = serviceScopeFactory;
Options = options.Value;
public Simulation(
IServiceScopeFactory serviceScopeFactory,
IOptions<ClientSimulationOptions> options)
{
ServiceScopeFactory = serviceScopeFactory;
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}'.");
}
State = SimulationState.Starting;
throw new UserFriendlyException($"Simulation should be stopped to be able to start. Current state is '{State}'.");
}
try
{
DisposeResources();
ServiceScope = ServiceScopeFactory.CreateScope();
State = SimulationState.Starting;
foreach (var scenarioConfiguration in Options.Scenarios)
{
for (int i = 0; i < scenarioConfiguration.ClientCount; i++)
{
var scenario = (Scenario)ServiceScope.ServiceProvider.GetRequiredService(
scenarioConfiguration.ScenarioType
);
var client = ServiceScope.ServiceProvider.GetRequiredService<IClient>();
client.Stopped += Client_OnStopped;
client.Initialize(scenario);
Clients.Add(client);
}
}
try
{
DisposeResources();
ServiceScope = ServiceScopeFactory.CreateScope();
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);
State = SimulationState.Stopped;
client.Start();
}
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)
{
client.Stop();
}
foreach (var client in Clients)
{
client.Stop();
}
}
}
public virtual SimulationSnapshot CreateSnapshot()
{
SimulationSnapshot snapshot;
public virtual SimulationSnapshot CreateSnapshot()
{
SimulationSnapshot snapshot;
lock (SyncObj)
lock (SyncObj)
{
snapshot = new SimulationSnapshot
{
snapshot = new SimulationSnapshot
{
State = State,
Clients = Clients
.Select(c => c.CreateSnapshot())
.ToList()
};
}
State = State,
Clients = Clients
.Select(c => c.CreateSnapshot())
.ToList()
};
}
snapshot.CreateSummaries();
snapshot.CreateSummaries();
return snapshot;
}
return snapshot;
}
public virtual void Dispose()
{
DisposeResources();
}
public virtual void Dispose()
{
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()
{
State = SimulationState.Stopped;
}
private void OnStopped()
{
State = SimulationState.Stopped;
}
private void DisposeResources()
{
Clients.Clear();
ServiceScope?.Dispose();
}
private void DisposeResources()
{
Clients.Clear();
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,
Started,
Stopping
}
Stopped,
Starting,
Started,
Stopping
}

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

@ -1,13 +1,12 @@
using System;
using Volo.ClientSimulation.Clients;
namespace Volo.ClientSimulation.Snapshot
namespace Volo.ClientSimulation.Snapshot;
[Serializable]
public class ClientSnapshot
{
[Serializable]
public class ClientSnapshot
{
public ClientState State { get; set; }
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.Collections.Generic;
namespace Volo.ClientSimulation.Snapshot
namespace Volo.ClientSimulation.Snapshot;
[Serializable]
public class ScenarioSnapshot
{
[Serializable]
public class ScenarioSnapshot
{
public string DisplayText { get; set; }
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;
namespace Volo.ClientSimulation.Snapshot
namespace Volo.ClientSimulation.Snapshot;
[Serializable]
public class ScenarioStepSnapshot
{
[Serializable]
public class ScenarioStepSnapshot
{
public string DisplayText { get; set; }
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;
namespace Volo.ClientSimulation.Snapshot
namespace Volo.ClientSimulation.Snapshot;
[Serializable]
public class ScenarioStepSummarySnapshot
{
[Serializable]
public class ScenarioStepSummarySnapshot
{
public string DisplayText { get; set; }
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.Collections.Generic;
namespace Volo.ClientSimulation.Snapshot
namespace Volo.ClientSimulation.Snapshot;
[Serializable]
public class ScenarioSummarySnapshot
{
[Serializable]
public class ScenarioSummarySnapshot
{
public string DisplayText { get; set; }
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.Linq;
namespace Volo.ClientSimulation.Snapshot
namespace Volo.ClientSimulation.Snapshot;
[Serializable]
public class SimulationSnapshot
{
[Serializable]
public class SimulationSnapshot
{
public SimulationState State { get; set; }
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(
client.Scenario.DisplayText,
() => 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);
if (scenarioStepSummary == null)
{
var scenarioStepSummary = scenarioSummary.Steps.FirstOrDefault(s => s.DisplayText == scenarioStep.DisplayText);
if (scenarioStepSummary == null)
scenarioStepSummary = new ScenarioStepSummarySnapshot
{
scenarioStepSummary = new ScenarioStepSummarySnapshot
{
DisplayText = scenarioStep.DisplayText
};
scenarioSummary.Steps.Add(scenarioStepSummary);
}
DisplayText = scenarioStep.DisplayText
};
scenarioStepSummary.ExecutionCount += scenarioStep.ExecutionCount;
scenarioStepSummary.SuccessCount += scenarioStep.SuccessCount;
scenarioStepSummary.FailCount += scenarioStep.FailCount;
scenarioStepSummary.TotalExecutionDuration += scenarioStep.TotalExecutionDuration;
scenarioSummary.Steps.Add(scenarioStepSummary);
}
if (scenarioStepSummary.MinExecutionDuration > scenarioStep.MinExecutionDuration)
{
scenarioStepSummary.MinExecutionDuration = scenarioStep.MinExecutionDuration;
}
scenarioStepSummary.ExecutionCount += scenarioStep.ExecutionCount;
scenarioStepSummary.SuccessCount += scenarioStep.SuccessCount;
scenarioStepSummary.FailCount += scenarioStep.FailCount;
scenarioStepSummary.TotalExecutionDuration += scenarioStep.TotalExecutionDuration;
if (scenarioStepSummary.MaxExecutionDuration < scenarioStep.MaxExecutionDuration)
{
scenarioStepSummary.MaxExecutionDuration = scenarioStep.MaxExecutionDuration;
}
if (scenarioStepSummary.MinExecutionDuration > scenarioStep.MinExecutionDuration)
{
scenarioStepSummary.MinExecutionDuration = scenarioStep.MinExecutionDuration;
}
scenarioStepSummary.AvgExecutionDuration = scenarioStepSummary.SuccessCount == 0
? 0.0
: scenarioStepSummary.TotalExecutionDuration / scenarioStepSummary.SuccessCount;
if (scenarioStepSummary.MaxExecutionDuration < scenarioStep.MaxExecutionDuration)
{
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