Files
Servers/MoonlightServers.Daemon/ServerSystem/Server.Power.cs

163 lines
5.5 KiB
C#

namespace MoonlightServers.Daemon.ServerSystem;
public partial class Server
{
public async Task StartAsync()
{
await Lock.WaitAsync();
try
{
if (State != ServerState.Offline)
throw new InvalidOperationException("Server is not offline");
// Check for any pre-existing runtime environment, if we don't have a reference already
RuntimeEnvironment ??= await RuntimeEnvironmentService.FindAsync(Uuid);
RuntimeStorage ??= await RuntimeStorageService.FindAsync(Uuid);
// Remove any pre-existing environment
if (RuntimeEnvironment != null)
{
Logger.LogTrace("Destroying pre-existing runtime environment");
if (await RuntimeEnvironment.IsRunningAsync())
{
Logger.LogTrace("Pre-existing runtime environment is still running, killing it");
await RuntimeEnvironment.KillAsync();
}
// Make sure no event handler is there anymore
RuntimeEnvironment.Console.OnOutput -= OnConsoleMessageAsync;
RuntimeEnvironment.Statistics.OnStatisticsReceived -= OnStatisticsReceivedAsync;
RuntimeEnvironment.OnExited -= OnRuntimeExitedAsync;
// Finally remove it
await RuntimeEnvironmentService.DeleteAsync(RuntimeEnvironment);
RuntimeEnvironment = null;
Logger.LogTrace("Pre-existing runtime environment destroyed");
}
// Fetch the latest config
Logger.LogTrace("Fetching latest configuration");
RuntimeConfiguration = await ConfigurationService.GetRuntimeConfigurationAsync(Uuid);
// Ensure runtime storage
if (RuntimeStorage == null)
{
Logger.LogTrace("Creating runtime storage");
RuntimeStorage = await RuntimeStorageService.CreateAsync(Uuid, RuntimeConfiguration);
}
else
{
Logger.LogTrace("Updating runtime storage");
await RuntimeStorageService.UpdateAsync(RuntimeStorage, RuntimeConfiguration);
}
// Create the environment
Logger.LogTrace("Creating runtime environment");
RuntimeEnvironment = await RuntimeEnvironmentService.CreateAsync(Uuid, RuntimeConfiguration, RuntimeStorage);
// Set event handlers
Logger.LogTrace("Attaching to runtime environment");
RuntimeEnvironment.Console.OnOutput += OnConsoleMessageAsync;
RuntimeEnvironment.Statistics.OnStatisticsReceived += OnStatisticsReceivedAsync;
RuntimeEnvironment.OnExited += OnRuntimeExitedAsync;
// Attach console & statistics
await RuntimeEnvironment.Console.AttachAsync();
await RuntimeEnvironment.Statistics.AttachAsync();
// Start up
Logger.LogTrace("Starting runtime environment");
await RuntimeEnvironment.StartAsync();
await ChangeStateAsync(ServerState.Starting);
}
finally
{
Lock.Release();
}
}
public async Task StopAsync()
{
await Lock.WaitAsync();
try
{
if (State is not (ServerState.Starting or ServerState.Online))
throw new InvalidOperationException("Server is not starting or online");
if (RuntimeEnvironment == null)
throw new InvalidOperationException("Runtime environment is not set");
Logger.LogTrace("Sending stop command to runtime environment");
await RuntimeEnvironment.Console.WriteInputAsync("stop\n\r");
await ChangeStateAsync(ServerState.Stopping);
}
finally
{
Lock.Release();
}
}
public async Task KillAsync()
{
await Lock.WaitAsync();
try
{
if (State is not (ServerState.Starting or ServerState.Online or ServerState.Stopping))
throw new InvalidOperationException("Server is not starting, stopping or online");
if (RuntimeEnvironment == null)
throw new InvalidOperationException("Runtime environment is not set");
Logger.LogTrace("Killing runtime environment");
await RuntimeEnvironment.KillAsync();
await ChangeStateAsync(ServerState.Stopping);
}
finally
{
Lock.Release();
}
}
private async Task OnRuntimeExitedAsync()
{
Logger.LogTrace("Runtime environment exited, checking result and cleaning up");
await Lock.WaitAsync();
try
{
// TODO: Handle crash
if (RuntimeEnvironment == null)
throw new InvalidOperationException("Runtime environment is not set");
// Make sure no event handler is there anymore
RuntimeEnvironment.Console.OnOutput -= OnConsoleMessageAsync;
RuntimeEnvironment.Statistics.OnStatisticsReceived -= OnStatisticsReceivedAsync;
RuntimeEnvironment.OnExited -= OnRuntimeExitedAsync;
// Finally remove it
await RuntimeEnvironmentService.DeleteAsync(RuntimeEnvironment);
RuntimeEnvironment = null;
Logger.LogTrace("Runtime environment cleaned up");
}
finally
{
Lock.Release();
}
await ChangeStateAsync(ServerState.Offline);
}
}