Open Source Web Application Framework for ASP.NET Core
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

155 lines
4.1 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
using Volo.ClientSimulation.Clients;
using Volo.ClientSimulation.Scenarios;
using Volo.ClientSimulation.Snapshot;
namespace Volo.ClientSimulation;
public class Simulation : ISingletonDependency, IDisposable
{
public ILogger<Simulation> Logger { get; set; }
public SimulationState State {
get => _state;
private set => _state = value;
}
private volatile SimulationState _state;
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();
public Simulation(
IServiceScopeFactory serviceScopeFactory,
IOptions<ClientSimulationOptions> options)
{
ServiceScopeFactory = serviceScopeFactory;
Options = options.Value;
Logger = NullLogger<Simulation>.Instance;
Clients = new List<IClient>();
}
public virtual void Start()
{
lock (SyncObj)
{
if (State != SimulationState.Stopped)
{
throw new UserFriendlyException($"Simulation should be stopped to be able to start. Current state is '{State}'.");
}
State = SimulationState.Starting;
try
{
DisposeResources();
ServiceScope = ServiceScopeFactory.CreateScope();
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);
}
}
foreach (var client in Clients)
{
client.Start();
}
State = SimulationState.Started;
}
catch (Exception ex)
{
Logger.LogException(ex);
State = SimulationState.Stopped;
}
}
}
public virtual void Stop()
{
lock (SyncObj)
{
if (State != SimulationState.Started)
{
throw new UserFriendlyException($"Simulation should be started to be able to stop. Current state is '{State}'.");
}
State = SimulationState.Stopping;
foreach (var client in Clients)
{
client.Stop();
}
}
}
public virtual SimulationSnapshot CreateSnapshot()
{
SimulationSnapshot snapshot;
lock (SyncObj)
{
snapshot = new SimulationSnapshot
{
State = State,
Clients = Clients
.Select(c => c.CreateSnapshot())
.ToList()
};
}
snapshot.CreateSummaries();
return snapshot;
}
public virtual void Dispose()
{
DisposeResources();
}
protected virtual void Client_OnStopped(object sender, EventArgs e)
{
lock (SyncObj)
{
if (Clients.All(c => c.State == ClientState.Stopped))
{
OnStopped();
}
}
}
private void OnStopped()
{
State = SimulationState.Stopped;
}
private void DisposeResources()
{
Clients.Clear();
ServiceScope?.Dispose();
}
}