Added online detection handler

This commit is contained in:
2025-09-09 23:08:01 +02:00
parent b90100d250
commit 160446eed0
4 changed files with 92 additions and 14 deletions

View File

@@ -0,0 +1,85 @@
using MoonlightServers.Daemon.ServerSystem.Enums;
using MoonlightServers.Daemon.ServerSystem.Interfaces;
using MoonlightServers.Daemon.ServerSystem.Models;
using Stateless;
namespace MoonlightServers.Daemon.ServerSystem.Handlers;
public class OnlineDetectionHandler : IServerStateHandler
{
private readonly ServerContext Context;
private IOnlineDetector OnlineDetector => Context.Server.OnlineDetector;
private ILogger Logger => Context.Logger;
private IAsyncDisposable? ConsoleSubscription;
private bool IsActive = false;
public OnlineDetectionHandler(ServerContext context)
{
Context = context;
}
public async Task ExecuteAsync(StateMachine<ServerState, ServerTrigger>.Transition transition)
{
if (
transition is
{ Source: ServerState.Offline, Destination: ServerState.Starting, Trigger: ServerTrigger.Start } && !IsActive
)
{
await StartAsync();
}
else if (transition is { Source: not ServerState.Installing, Destination: ServerState.Offline } && IsActive)
{
await StopAsync();
}
}
private async Task StartAsync()
{
IsActive = true;
await OnlineDetector.CreateAsync();
ConsoleSubscription = await Context.Server.Console.SubscribeStdOutAsync(OnHandleOutput);
Logger.LogTrace("Created online detector. Created console subscription");
}
private async ValueTask OnHandleOutput(string line)
{
if(!IsActive)
return;
if(!await OnlineDetector.HandleOutputAsync(line))
return;
if(!Context.Server.StateMachine.CanFire(ServerTrigger.DetectOnline))
return;
Logger.LogTrace("Detected server as online. Destroying online detector");
await Context.Server.StateMachine.FireAsync(ServerTrigger.DetectOnline);
await StopAsync();
}
private async Task StopAsync()
{
IsActive = false;
if (ConsoleSubscription != null)
{
await ConsoleSubscription.DisposeAsync();
ConsoleSubscription = null;
}
await OnlineDetector.DestroyAsync();
Logger.LogTrace("Destroyed online detector. Revoked console subscription");
}
public async ValueTask DisposeAsync()
{
if (ConsoleSubscription != null)
await ConsoleSubscription.DisposeAsync();
}
}

View File

@@ -21,7 +21,7 @@ public class ShutdownHandler : IServerStateHandler
{
Destination: ServerState.Offline,
Source: not ServerState.Installing,
Trigger: ServerTrigger.Exited
Trigger: ServerTrigger.Exited // We don't want to handle the fail event here
})
return;

View File

@@ -30,12 +30,13 @@ public class StartupHandler : IServerStateHandler
// 4. Run file system checks
// 5. Create runtime
// 6. Attach console
// 7. Attach statistics collector
// 8. Create online detector
// 9. Start runtime
// 7. Start runtime
// 1. Fetch latest configuration
// TODO
// Consider moving it out of the startup handler, as other handlers might need
// the updated config as well or add sorting into the handler registration to ensure they are executing in the correct order.
// Sort when building server, not when executing handlers
// 2. Check if file system exists
if (!await Server.RuntimeFileSystem.CheckExistsAsync())
@@ -65,16 +66,7 @@ public class StartupHandler : IServerStateHandler
await Server.Console.AttachRuntimeAsync();
// 7. Attach statistics collector
await Server.Statistics.AttachRuntimeAsync();
// 8. Create online detector
await Server.OnlineDetector.CreateAsync();
await Server.OnlineDetector.DestroyAsync();
// 9. Start runtime
// 7. Start runtime
await Server.Runtime.StartAsync();
}

View File

@@ -58,6 +58,7 @@ public class ServerFactory
// Resolve handlers
var handlers = new List<IServerStateHandler>();
handlers.Add(ActivatorUtilities.CreateInstance<OnlineDetectionHandler>(scope.ServiceProvider));
handlers.Add(ActivatorUtilities.CreateInstance<StartupHandler>(scope.ServiceProvider));
handlers.Add(ActivatorUtilities.CreateInstance<ShutdownHandler>(scope.ServiceProvider));