mirror of
https://github.com/chylex/Minecraft-Phantom-Panel.git
synced 2025-05-30 04:34:04 +02:00
Change online player check in backup scheduler to wait for any server process output before retrying
This commit is contained in:
parent
b3104f9ac3
commit
09e7510358
Agent/Phantom.Agent.Services/Backups
Utils/Phantom.Utils.Runtime
@ -55,7 +55,7 @@ sealed partial class BackupManager {
|
|||||||
|
|
||||||
public async Task<BackupCreationResult> CreateBackup() {
|
public async Task<BackupCreationResult> CreateBackup() {
|
||||||
logger.Information("Backup started.");
|
logger.Information("Backup started.");
|
||||||
session.AddOutputListener(listener.OnOutput, 0);
|
session.AddOutputListener(listener.OnOutput, maxLinesToReadFromHistory: 0);
|
||||||
try {
|
try {
|
||||||
var resultBuilder = new BackupCreationResult.Builder();
|
var resultBuilder = new BackupCreationResult.Builder();
|
||||||
|
|
||||||
|
@ -11,13 +11,13 @@ sealed class BackupScheduler : CancellableBackgroundTask {
|
|||||||
private static readonly TimeSpan InitialDelay = TimeSpan.FromMinutes(2);
|
private static readonly TimeSpan InitialDelay = TimeSpan.FromMinutes(2);
|
||||||
private static readonly TimeSpan BackupInterval = TimeSpan.FromMinutes(30);
|
private static readonly TimeSpan BackupInterval = TimeSpan.FromMinutes(30);
|
||||||
private static readonly TimeSpan BackupFailureRetryDelay = TimeSpan.FromMinutes(5);
|
private static readonly TimeSpan BackupFailureRetryDelay = TimeSpan.FromMinutes(5);
|
||||||
private static readonly TimeSpan OnlinePlayersCheckInterval = TimeSpan.FromMinutes(1);
|
|
||||||
|
|
||||||
private readonly string loggerName;
|
private readonly string loggerName;
|
||||||
private readonly BackupManager backupManager;
|
private readonly BackupManager backupManager;
|
||||||
private readonly InstanceSession session;
|
private readonly InstanceSession session;
|
||||||
private readonly int serverPort;
|
private readonly int serverPort;
|
||||||
private readonly ServerStatusProtocol serverStatusProtocol;
|
private readonly ServerStatusProtocol serverStatusProtocol;
|
||||||
|
private readonly ManualResetEventSlim serverOutputWhileWaitingForOnlinePlayers = new ();
|
||||||
|
|
||||||
public BackupScheduler(TaskManager taskManager, BackupManager backupManager, InstanceSession session, int serverPort, string loggerName) : base(PhantomLogger.Create<BackupScheduler>(loggerName), taskManager, "Backup scheduler for " + loggerName) {
|
public BackupScheduler(TaskManager taskManager, BackupManager backupManager, InstanceSession session, int serverPort, string loggerName) : base(PhantomLogger.Create<BackupScheduler>(loggerName), taskManager, "Backup scheduler for " + loggerName) {
|
||||||
this.loggerName = loggerName;
|
this.loggerName = loggerName;
|
||||||
@ -52,24 +52,41 @@ sealed class BackupScheduler : CancellableBackgroundTask {
|
|||||||
private async Task WaitForOnlinePlayers() {
|
private async Task WaitForOnlinePlayers() {
|
||||||
bool needsToLogOfflinePlayersMessage = true;
|
bool needsToLogOfflinePlayersMessage = true;
|
||||||
|
|
||||||
while (!CancellationToken.IsCancellationRequested) {
|
session.AddOutputListener(ServerOutputListener, maxLinesToReadFromHistory: 0);
|
||||||
var onlinePlayerCount = await serverStatusProtocol.GetOnlinePlayerCount(serverPort, CancellationToken);
|
try {
|
||||||
if (onlinePlayerCount == null) {
|
while (!CancellationToken.IsCancellationRequested) {
|
||||||
Logger.Warning("Could not detect whether any players are online, starting a new backup.");
|
serverOutputWhileWaitingForOnlinePlayers.Reset();
|
||||||
break;
|
|
||||||
}
|
var onlinePlayerCount = await serverStatusProtocol.GetOnlinePlayerCount(serverPort, CancellationToken);
|
||||||
|
if (onlinePlayerCount == null) {
|
||||||
if (onlinePlayerCount > 0) {
|
Logger.Warning("Could not detect whether any players are online, starting a new backup.");
|
||||||
Logger.Information("Players are online, starting a new backup.");
|
break;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (needsToLogOfflinePlayersMessage) {
|
|
||||||
needsToLogOfflinePlayersMessage = false;
|
|
||||||
Logger.Information("No players are online, waiting for someone to join before starting a new backup.");
|
|
||||||
}
|
|
||||||
|
|
||||||
await Task.Delay(OnlinePlayersCheckInterval, CancellationToken);
|
if (onlinePlayerCount > 0) {
|
||||||
|
Logger.Information("Players are online, starting a new backup.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needsToLogOfflinePlayersMessage) {
|
||||||
|
needsToLogOfflinePlayersMessage = false;
|
||||||
|
Logger.Information("No players are online, waiting for someone to join before starting a new backup.");
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(10), CancellationToken);
|
||||||
|
|
||||||
|
Logger.Verbose("Waiting for server output before checking for online players again...");
|
||||||
|
await serverOutputWhileWaitingForOnlinePlayers.WaitHandle.WaitOneAsync(CancellationToken);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
session.RemoveOutputListener(ServerOutputListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ServerOutputListener(object? sender, string line) {
|
||||||
|
if (!serverOutputWhileWaitingForOnlinePlayers.IsSet) {
|
||||||
|
serverOutputWhileWaitingForOnlinePlayers.Set();
|
||||||
|
Logger.Verbose("Detected server output, signalling to check for online players again.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
27
Utils/Phantom.Utils.Runtime/WaitHandleExtensions.cs
Normal file
27
Utils/Phantom.Utils.Runtime/WaitHandleExtensions.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
namespace Phantom.Utils.Runtime;
|
||||||
|
|
||||||
|
public static class WaitHandleExtensions {
|
||||||
|
public static Task WaitOneAsync(this WaitHandle waitHandle, CancellationToken cancellationToken = default) {
|
||||||
|
var taskCompletionSource = new TaskCompletionSource();
|
||||||
|
|
||||||
|
void SetResult(object? state, bool timedOut) {
|
||||||
|
taskCompletionSource.TrySetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetCancelled() {
|
||||||
|
taskCompletionSource.TrySetCanceled(cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
var waitRegistration = ThreadPool.RegisterWaitForSingleObject(waitHandle, SetResult, null, Timeout.InfiniteTimeSpan, true);
|
||||||
|
var tokenRegistration = cancellationToken.Register(SetCancelled, useSynchronizationContext: false);
|
||||||
|
|
||||||
|
void Cleanup(Task t) {
|
||||||
|
waitRegistration.Unregister(null);
|
||||||
|
tokenRegistration.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
var task = taskCompletionSource.Task;
|
||||||
|
task.ContinueWith(Cleanup, CancellationToken.None);
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user