diff --git a/Agent/Phantom.Agent.Services/AgentServices.cs b/Agent/Phantom.Agent.Services/AgentServices.cs index c31e118..304631b 100644 --- a/Agent/Phantom.Agent.Services/AgentServices.cs +++ b/Agent/Phantom.Agent.Services/AgentServices.cs @@ -6,7 +6,6 @@ using Phantom.Agent.Services.Instances; using Phantom.Common.Data.Agent; using Phantom.Utils.Actor; using Phantom.Utils.Logging; -using Phantom.Utils.Tasks; using Serilog; namespace Phantom.Agent.Services; @@ -18,7 +17,6 @@ public sealed class AgentServices { private AgentFolders AgentFolders { get; } private AgentState AgentState { get; } - private TaskManager TaskManager { get; } private BackupManager BackupManager { get; } internal JavaRuntimeRepository JavaRuntimeRepository { get; } @@ -30,13 +28,12 @@ public sealed class AgentServices { this.AgentFolders = agentFolders; this.AgentState = new AgentState(); - this.TaskManager = new TaskManager(PhantomLogger.Create<TaskManager, AgentServices>()); this.BackupManager = new BackupManager(agentFolders, serviceConfiguration.MaxConcurrentCompressionTasks); this.JavaRuntimeRepository = new JavaRuntimeRepository(); this.InstanceTicketManager = new InstanceTicketManager(agentInfo, controllerConnection); - var instanceManagerInit = new InstanceManagerActor.Init(controllerConnection, agentFolders, AgentState, JavaRuntimeRepository, InstanceTicketManager, TaskManager, BackupManager); + var instanceManagerInit = new InstanceManagerActor.Init(controllerConnection, agentFolders, AgentState, JavaRuntimeRepository, InstanceTicketManager, BackupManager); this.InstanceManager = ActorSystem.ActorOf(InstanceManagerActor.Factory(instanceManagerInit), "InstanceManager"); } @@ -50,7 +47,6 @@ public sealed class AgentServices { Logger.Information("Stopping services..."); await InstanceManager.Stop(new InstanceManagerActor.ShutdownCommand()); - await TaskManager.Stop(); BackupManager.Dispose(); diff --git a/Agent/Phantom.Agent.Services/Backups/BackupScheduler.cs b/Agent/Phantom.Agent.Services/Backups/BackupScheduler.cs index 3853625..4ff9a68 100644 --- a/Agent/Phantom.Agent.Services/Backups/BackupScheduler.cs +++ b/Agent/Phantom.Agent.Services/Backups/BackupScheduler.cs @@ -24,7 +24,7 @@ sealed class BackupScheduler : CancellableBackgroundTask { public event EventHandler<BackupCreationResult>? BackupCompleted; - public BackupScheduler(InstanceContext context, InstanceProcess process, int serverPort) : base(PhantomLogger.Create<BackupScheduler>(context.ShortName), context.Services.TaskManager, "Backup scheduler for " + context.ShortName) { + public BackupScheduler(InstanceContext context, InstanceProcess process, int serverPort) : base(PhantomLogger.Create<BackupScheduler>(context.ShortName)) { this.backupManager = context.Services.BackupManager; this.context = context; this.process = process; diff --git a/Agent/Phantom.Agent.Services/Instances/InstanceManagerActor.cs b/Agent/Phantom.Agent.Services/Instances/InstanceManagerActor.cs index f036b51..2f95e79 100644 --- a/Agent/Phantom.Agent.Services/Instances/InstanceManagerActor.cs +++ b/Agent/Phantom.Agent.Services/Instances/InstanceManagerActor.cs @@ -20,7 +20,7 @@ namespace Phantom.Agent.Services.Instances; sealed class InstanceManagerActor : ReceiveActor<InstanceManagerActor.ICommand> { private static readonly ILogger Logger = PhantomLogger.Create<InstanceManagerActor>(); - public readonly record struct Init(ControllerConnection ControllerConnection, AgentFolders AgentFolders, AgentState AgentState, JavaRuntimeRepository JavaRuntimeRepository, InstanceTicketManager InstanceTicketManager, TaskManager TaskManager, BackupManager BackupManager); + public readonly record struct Init(ControllerConnection ControllerConnection, AgentFolders AgentFolders, AgentState AgentState, JavaRuntimeRepository JavaRuntimeRepository, InstanceTicketManager InstanceTicketManager, BackupManager BackupManager); public static Props<ICommand> Factory(Init init) { return Props<ICommand>.Create(() => new InstanceManagerActor(init), new ActorConfiguration { SupervisorStrategy = SupervisorStrategies.Resume }); @@ -47,7 +47,7 @@ sealed class InstanceManagerActor : ReceiveActor<InstanceManagerActor.ICommand> var minecraftServerExecutables = new MinecraftServerExecutables(init.AgentFolders.ServerExecutableFolderPath); var launchServices = new LaunchServices(minecraftServerExecutables, init.JavaRuntimeRepository); - this.instanceServices = new InstanceServices(init.ControllerConnection, init.TaskManager, init.BackupManager, launchServices); + this.instanceServices = new InstanceServices(init.ControllerConnection, init.BackupManager, launchServices); ReceiveAndReply<ConfigureInstanceCommand, InstanceActionResult<ConfigureInstanceResult>>(ConfigureInstance); ReceiveAndReply<LaunchInstanceCommand, InstanceActionResult<LaunchInstanceResult>>(LaunchInstance); diff --git a/Agent/Phantom.Agent.Services/Instances/InstanceServices.cs b/Agent/Phantom.Agent.Services/Instances/InstanceServices.cs index b8363ba..209e0c4 100644 --- a/Agent/Phantom.Agent.Services/Instances/InstanceServices.cs +++ b/Agent/Phantom.Agent.Services/Instances/InstanceServices.cs @@ -1,8 +1,7 @@ using Phantom.Agent.Minecraft.Launcher; using Phantom.Agent.Rpc; using Phantom.Agent.Services.Backups; -using Phantom.Utils.Tasks; namespace Phantom.Agent.Services.Instances; -sealed record InstanceServices(ControllerConnection ControllerConnection, TaskManager TaskManager, BackupManager BackupManager, LaunchServices LaunchServices); +sealed record InstanceServices(ControllerConnection ControllerConnection, BackupManager BackupManager, LaunchServices LaunchServices); diff --git a/Agent/Phantom.Agent.Services/Instances/State/InstanceLogSender.cs b/Agent/Phantom.Agent.Services/Instances/State/InstanceLogSender.cs index 8aa63a6..0915d8f 100644 --- a/Agent/Phantom.Agent.Services/Instances/State/InstanceLogSender.cs +++ b/Agent/Phantom.Agent.Services/Instances/State/InstanceLogSender.cs @@ -22,7 +22,7 @@ sealed class InstanceLogSender : CancellableBackgroundTask { private int droppedLinesSinceLastSend; - public InstanceLogSender(ControllerConnection controllerConnection, TaskManager taskManager, Guid instanceGuid, string loggerName) : base(PhantomLogger.Create<InstanceLogSender>(loggerName), taskManager, "Instance log sender for " + loggerName) { + public InstanceLogSender(ControllerConnection controllerConnection, Guid instanceGuid, string loggerName) : base(PhantomLogger.Create<InstanceLogSender>(loggerName)) { this.controllerConnection = controllerConnection; this.instanceGuid = instanceGuid; this.outputChannel = Channel.CreateBounded<string>(BufferOptions, OnLineDropped); diff --git a/Agent/Phantom.Agent.Services/Instances/State/InstanceRunningState.cs b/Agent/Phantom.Agent.Services/Instances/State/InstanceRunningState.cs index 3d30b3b..1470682 100644 --- a/Agent/Phantom.Agent.Services/Instances/State/InstanceRunningState.cs +++ b/Agent/Phantom.Agent.Services/Instances/State/InstanceRunningState.cs @@ -31,7 +31,7 @@ sealed class InstanceRunningState : IDisposable { this.Process = process; this.cancellationToken = cancellationToken; - this.logSender = new InstanceLogSender(context.Services.ControllerConnection, context.Services.TaskManager, context.InstanceGuid, context.ShortName); + this.logSender = new InstanceLogSender(context.Services.ControllerConnection, context.InstanceGuid, context.ShortName); this.backupScheduler = new BackupScheduler(context, process, configuration.ServerPort); this.backupScheduler.BackupCompleted += OnScheduledBackupCompleted; diff --git a/Controller/Phantom.Controller/Program.cs b/Controller/Phantom.Controller/Program.cs index 63be6eb..29aa80c 100644 --- a/Controller/Phantom.Controller/Program.cs +++ b/Controller/Phantom.Controller/Program.cs @@ -10,7 +10,6 @@ using Phantom.Utils.Logging; using Phantom.Utils.Rpc; using Phantom.Utils.Rpc.Runtime; using Phantom.Utils.Runtime; -using Phantom.Utils.Tasks; var shutdownCancellationTokenSource = new CancellationTokenSource(); var shutdownCancellationToken = shutdownCancellationTokenSource.Token; @@ -64,14 +63,12 @@ try { return new RpcConfiguration(serviceName, host, port, connectionKey.Certificate); } - var rpcTaskManager = new TaskManager(PhantomLogger.Create<TaskManager>("Rpc")); try { await Task.WhenAll( RpcServerRuntime.Launch(ConfigureRpc("Agent", agentRpcServerHost, agentRpcServerPort, agentKeyData), AgentMessageRegistries.Definitions, controllerServices.AgentRegistrationHandler, controllerServices.ActorSystem, shutdownCancellationToken), RpcServerRuntime.Launch(ConfigureRpc("Web", webRpcServerHost, webRpcServerPort, webKeyData), WebMessageRegistries.Definitions, controllerServices.WebRegistrationHandler, controllerServices.ActorSystem, shutdownCancellationToken) ); } finally { - await rpcTaskManager.Stop(); NetMQConfig.Cleanup(); } diff --git a/Utils/Phantom.Utils/Tasks/CancellableBackgroundTask.cs b/Utils/Phantom.Utils/Tasks/CancellableBackgroundTask.cs index ee60040..cc4af28 100644 --- a/Utils/Phantom.Utils/Tasks/CancellableBackgroundTask.cs +++ b/Utils/Phantom.Utils/Tasks/CancellableBackgroundTask.cs @@ -8,19 +8,13 @@ public abstract class CancellableBackgroundTask { protected ILogger Logger { get; } protected CancellationToken CancellationToken { get; } - private readonly TaskManager taskManager; - private readonly string taskName; - - protected CancellableBackgroundTask(ILogger logger, TaskManager taskManager, string taskName) { + protected CancellableBackgroundTask(ILogger logger) { this.Logger = logger; this.CancellationToken = cancellationTokenSource.Token; - - this.taskManager = taskManager; - this.taskName = taskName; } protected void Start() { - taskManager.Run(taskName, Run); + Task.Run(Run, CancellationToken.None); } private async Task Run() { diff --git a/Utils/Phantom.Utils/Tasks/TaskManager.cs b/Utils/Phantom.Utils/Tasks/TaskManager.cs deleted file mode 100644 index e0064eb..0000000 --- a/Utils/Phantom.Utils/Tasks/TaskManager.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System.Collections.Concurrent; -using Phantom.Utils.Collections; -using Serilog; - -namespace Phantom.Utils.Tasks; - -public sealed class TaskManager { - private readonly ILogger logger; - private readonly CancellationTokenSource cancellationTokenSource = new (); - private readonly CancellationToken cancellationToken; - - private readonly ConcurrentDictionary<Task, string> runningTasks = new (ReferenceEqualityComparer<Task>.Instance); - - public TaskManager(ILogger logger) { - this.logger = logger; - this.cancellationToken = cancellationTokenSource.Token; - } - - private T Add<T>(string name, T task) where T : Task { - cancellationToken.ThrowIfCancellationRequested(); - runningTasks.TryAdd(task, name); - task.ContinueWith(OnFinished, CancellationToken.None, TaskContinuationOptions.RunContinuationsAsynchronously, TaskScheduler.Default); - return task; - } - - private void OnFinished(Task task) { - runningTasks.TryRemove(task, out _); - } - - public Task Run(string name, Action action) { - return Add(name, Task.Run(action, cancellationToken)); - } - - public Task Run(string name, Func<Task> taskFunc) { - return Add(name, Task.Run(taskFunc, cancellationToken)); - } - - public Task<T> Run<T>(string name, Func<Task<T>> taskFunc) { - return Add(name, Task.Run(taskFunc, cancellationToken)); - } - - public async Task Stop() { - logger.Information("Stopping task manager..."); - - cancellationTokenSource.Cancel(); - - var remainingTasksAwaiterTask = WaitForRemainingTasks(); - while (true) { - var logStateTimeoutTask = Task.Delay(TimeSpan.FromSeconds(10), CancellationToken.None); - var completedTask = await Task.WhenAny(remainingTasksAwaiterTask, logStateTimeoutTask); - if (completedTask == logStateTimeoutTask) { - var remainingTaskNames = runningTasks.Values.Order().ToList(); - var remainingTaskNameList = string.Join('\n', remainingTaskNames.Select(static name => "- " + name)); - logger.Warning("Waiting for {TaskCount} task(s) to finish:\n{TaskNames}", remainingTaskNames.Count, remainingTaskNameList); - } - else { - break; - } - } - - runningTasks.Clear(); - cancellationTokenSource.Dispose(); - - logger.Information("Task manager stopped."); - } - - private async Task WaitForRemainingTasks() { - foreach (var task in runningTasks.Keys) { - try { - await task; - } catch (Exception) { - // ignored - } - } - } -} diff --git a/Web/Phantom.Web/Program.cs b/Web/Phantom.Web/Program.cs index 34c9b2a..831fa36 100644 --- a/Web/Phantom.Web/Program.cs +++ b/Web/Phantom.Web/Program.cs @@ -9,7 +9,6 @@ using Phantom.Utils.Logging; using Phantom.Utils.Rpc; using Phantom.Utils.Rpc.Sockets; using Phantom.Utils.Runtime; -using Phantom.Utils.Tasks; using Phantom.Web; using Phantom.Web.Services; using Phantom.Web.Services.Rpc; @@ -59,8 +58,7 @@ try { var rpcSocket = RpcClientSocket.Connect(rpcConfiguration, WebMessageRegistries.Definitions, new RegisterWebMessage(webToken)); var webConfiguration = new WebLauncher.Configuration(PhantomLogger.Create("Web"), webServerHost, webServerPort, webBasePath, dataProtectionKeysPath, shutdownCancellationToken); - var taskManager = new TaskManager(PhantomLogger.Create<TaskManager>("Web")); - var webApplication = WebLauncher.CreateApplication(webConfiguration, taskManager, applicationProperties, rpcSocket.Connection); + var webApplication = WebLauncher.CreateApplication(webConfiguration, applicationProperties, rpcSocket.Connection); using var actorSystem = ActorSystemFactory.Create("Web"); @@ -88,7 +86,6 @@ try { await WebLauncher.Launch(webConfiguration, webApplication); } finally { shutdownCancellationTokenSource.Cancel(); - await taskManager.Stop(); rpcDisconnectSemaphore.Release(); await rpcTask; diff --git a/Web/Phantom.Web/WebLauncher.cs b/Web/Phantom.Web/WebLauncher.cs index 7266a5f..cdabb4d 100644 --- a/Web/Phantom.Web/WebLauncher.cs +++ b/Web/Phantom.Web/WebLauncher.cs @@ -1,7 +1,6 @@ using Microsoft.AspNetCore.DataProtection; using Phantom.Common.Messages.Web; using Phantom.Utils.Rpc.Runtime; -using Phantom.Utils.Tasks; using Phantom.Web.Services; using Serilog; using ILogger = Serilog.ILogger; @@ -13,7 +12,7 @@ static class WebLauncher { public string HttpUrl => "http://" + Host + ":" + Port; } - internal static WebApplication CreateApplication(Configuration config, TaskManager taskManager, ApplicationProperties applicationProperties, RpcConnectionToServer<IMessageToController> controllerConnection) { + internal static WebApplication CreateApplication(Configuration config, ApplicationProperties applicationProperties, RpcConnectionToServer<IMessageToController> controllerConnection) { var assembly = typeof(WebLauncher).Assembly; var builder = WebApplication.CreateBuilder(new WebApplicationOptions { ApplicationName = assembly.GetName().Name, @@ -29,7 +28,6 @@ static class WebLauncher { builder.WebHost.UseStaticWebAssets(); } - builder.Services.AddSingleton(taskManager); builder.Services.AddSingleton(applicationProperties); builder.Services.AddSingleton(controllerConnection); builder.Services.AddPhantomServices();