diff --git a/MoonlightServers.Daemon/ServerSystem/Handlers/OnlineDetectionHandler.cs b/MoonlightServers.Daemon/ServerSystem/Handlers/OnlineDetectionHandler.cs new file mode 100644 index 0000000..7aa1dfd --- /dev/null +++ b/MoonlightServers.Daemon/ServerSystem/Handlers/OnlineDetectionHandler.cs @@ -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.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(); + } +} \ No newline at end of file diff --git a/MoonlightServers.Daemon/ServerSystem/Handlers/ShutdownHandler.cs b/MoonlightServers.Daemon/ServerSystem/Handlers/ShutdownHandler.cs index 58ac6dd..368816d 100644 --- a/MoonlightServers.Daemon/ServerSystem/Handlers/ShutdownHandler.cs +++ b/MoonlightServers.Daemon/ServerSystem/Handlers/ShutdownHandler.cs @@ -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; diff --git a/MoonlightServers.Daemon/ServerSystem/Handlers/StartupHandler.cs b/MoonlightServers.Daemon/ServerSystem/Handlers/StartupHandler.cs index e66f16d..2097a80 100644 --- a/MoonlightServers.Daemon/ServerSystem/Handlers/StartupHandler.cs +++ b/MoonlightServers.Daemon/ServerSystem/Handlers/StartupHandler.cs @@ -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(); } diff --git a/MoonlightServers.Daemon/ServerSystem/ServerFactory.cs b/MoonlightServers.Daemon/ServerSystem/ServerFactory.cs index 4f24ee5..17be4d6 100644 --- a/MoonlightServers.Daemon/ServerSystem/ServerFactory.cs +++ b/MoonlightServers.Daemon/ServerSystem/ServerFactory.cs @@ -58,6 +58,7 @@ public class ServerFactory // Resolve handlers var handlers = new List(); + handlers.Add(ActivatorUtilities.CreateInstance(scope.ServiceProvider)); handlers.Add(ActivatorUtilities.CreateInstance(scope.ServiceProvider)); handlers.Add(ActivatorUtilities.CreateInstance(scope.ServiceProvider));