From 430ee2301f91d791797d40a6495d2b81d7981b16 Mon Sep 17 00:00:00 2001 From: glax Date: Sat, 20 May 2023 14:50:48 +0200 Subject: [PATCH] Implemented Queue, so that taskManager is not held up with other Connector-tasks. Tasks are now executed in another Thread. Replaced TrangaTask.isBeingExecuted bool with 3-states: Waiting, Enqueued, Running Added Queue size to CLI output. --- Tranga-CLI/Tranga_Cli.cs | 15 +++++++++------ Tranga/TaskExecutor.cs | 12 ++++++------ Tranga/TaskManager.cs | 27 ++++++++++++++++++++++----- Tranga/TrangaTask.cs | 13 ++++++++++--- 4 files changed, 47 insertions(+), 20 deletions(-) diff --git a/Tranga-CLI/Tranga_Cli.cs b/Tranga-CLI/Tranga_Cli.cs index 8e36ef2..98b0846 100644 --- a/Tranga-CLI/Tranga_Cli.cs +++ b/Tranga-CLI/Tranga_Cli.cs @@ -129,7 +129,7 @@ public static class Tranga_Cli menu = 0; break; case 6: - PrintTasks(taskManager.GetAllTasks().Where(eTask => eTask.isBeingExecuted).ToArray()); + PrintTasks(taskManager.GetAllTasks().Where(eTask => eTask.state == TrangaTask.ExecutionState.Running).ToArray()); Console.WriteLine("Press any key."); Console.ReadKey(); menu = 0; @@ -167,7 +167,7 @@ public static class Tranga_Cli } } - if (taskManager.GetAllTasks().Any(task => task.isBeingExecuted)) + if (taskManager.GetAllTasks().Any(task => task.state == TrangaTask.ExecutionState.Running)) { Console.WriteLine("Force quit (Even with running tasks?) y/N"); selection = Console.ReadKey().Key; @@ -182,9 +182,11 @@ public static class Tranga_Cli private static ConsoleKey Menu(TaskManager taskManager, string folderPath) { int taskCount = taskManager.GetAllTasks().Length; - int taskRunningCount = taskManager.GetAllTasks().Count(task => task.isBeingExecuted); + int taskRunningCount = taskManager.GetAllTasks().Count(task => task.state == TrangaTask.ExecutionState.Running); + int taskEnqueuedCount = + taskManager.GetAllTasks().Count(task => task.state == TrangaTask.ExecutionState.Enqueued); Console.Clear(); - Console.WriteLine($"Download Folder: {folderPath} Tasks (Running/Total): {taskRunningCount}/{taskCount}"); + Console.WriteLine($"Download Folder: {folderPath} Tasks (Running/Queue/Total): {taskRunningCount}/{taskEnqueuedCount}/{taskCount}"); Console.WriteLine("U: Update this Screen"); Console.WriteLine("L: List tasks"); Console.WriteLine("C: Create Task"); @@ -201,10 +203,11 @@ public static class Tranga_Cli private static void PrintTasks(TrangaTask[] tasks) { int taskCount = tasks.Length; - int taskRunningCount = tasks.Count(task => task.isBeingExecuted); + int taskRunningCount = tasks.Count(task => task.state == TrangaTask.ExecutionState.Running); + int taskEnqueuedCount = tasks.Count(task => task.state == TrangaTask.ExecutionState.Enqueued); Console.Clear(); int tIndex = 0; - Console.WriteLine($"Tasks (Running/Total): {taskRunningCount}/{taskCount}"); + Console.WriteLine($"Tasks (Running/Queue/Total): {taskRunningCount}/{taskEnqueuedCount}/{taskCount}"); foreach(TrangaTask trangaTask in tasks) Console.WriteLine($"{tIndex++:000}: {trangaTask}"); } diff --git a/Tranga/TaskExecutor.cs b/Tranga/TaskExecutor.cs index 139890d..f827e75 100644 --- a/Tranga/TaskExecutor.cs +++ b/Tranga/TaskExecutor.cs @@ -16,15 +16,14 @@ public static class TaskExecutor /// Is thrown when there is no Connector available with the name of the TrangaTask.connectorName public static void Execute(TaskManager taskManager, TrangaTask trangaTask, Dictionary> chapterCollection) { + if (trangaTask.state == TrangaTask.ExecutionState.Running) + return; + trangaTask.state = TrangaTask.ExecutionState.Running; + Connector? connector = null; if (trangaTask.task != TrangaTask.Task.UpdateKomgaLibrary) connector = taskManager.GetConnector(trangaTask.connectorName!); - if (trangaTask.isBeingExecuted) - return; - trangaTask.isBeingExecuted = true; - trangaTask.lastExecuted = DateTime.Now; - //Call appropriate Method based on TrangaTask.Task switch (trangaTask.task) { @@ -42,7 +41,8 @@ public static class TaskExecutor break; } - trangaTask.isBeingExecuted = false; + trangaTask.state = TrangaTask.ExecutionState.Waiting; + trangaTask.lastExecuted = DateTime.Now; } /// diff --git a/Tranga/TaskManager.cs b/Tranga/TaskManager.cs index 8efd325..ec2e6d0 100644 --- a/Tranga/TaskManager.cs +++ b/Tranga/TaskManager.cs @@ -13,6 +13,7 @@ public class TaskManager private readonly HashSet _allTasks; private bool _continueRunning = true; private readonly Connector[] _connectors; + private Dictionary> tasksToExecute = new(); private string downloadLocation { get; } public Komga? komga { get; private set; } @@ -26,6 +27,8 @@ public class TaskManager if (komgaBaseUrl != null && komgaUsername != null && komgaPassword != null) this.komga = new Komga(komgaBaseUrl, komgaUsername, komgaPassword); this._connectors = new Connector[]{ new MangaDex(folderPath) }; + foreach(Connector cConnector in this._connectors) + tasksToExecute.Add(cConnector, new List()); _allTasks = new HashSet(); Thread taskChecker = new(TaskCheckerThread); @@ -35,6 +38,8 @@ public class TaskManager public TaskManager(SettingsData settings) { this._connectors = new Connector[]{ new MangaDex(settings.downloadLocation) }; + foreach(Connector cConnector in this._connectors) + tasksToExecute.Add(cConnector, new List()); this.downloadLocation = settings.downloadLocation; this.komga = settings.komga; _allTasks = settings.allTasks; @@ -46,10 +51,22 @@ public class TaskManager { while (_continueRunning) { - foreach (TrangaTask task in _allTasks) + foreach (KeyValuePair> connectorTaskQueue in tasksToExecute) { - if(task.ShouldExecute()) - TaskExecutor.Execute(this, task, this._chapterCollection); //TODO Might crash here, when adding new Task while another Task is running. Check later + connectorTaskQueue.Value.RemoveAll(task => task.state == TrangaTask.ExecutionState.Waiting); + if (connectorTaskQueue.Value.Count > 0 && !connectorTaskQueue.Value.All(task => task.state is TrangaTask.ExecutionState.Running or TrangaTask.ExecutionState.Waiting)) + ExecuteTaskNow(connectorTaskQueue.Value.First()); + } + + foreach (TrangaTask task in _allTasks.Where(aTask => aTask.ShouldExecute())) + { + task.state = TrangaTask.ExecutionState.Enqueued; + if(task.connectorName is null) + ExecuteTaskNow(task); + else + { + tasksToExecute[GetConnector(task.connectorName!)].Add(task); + } } Thread.Sleep(1000); } @@ -173,10 +190,10 @@ public class TaskManager ExportData(Directory.GetCurrentDirectory()); if(force) - Environment.Exit(_allTasks.Count(task => task.isBeingExecuted)); + Environment.Exit(_allTasks.Count(task => task.state is TrangaTask.ExecutionState.Enqueued or TrangaTask.ExecutionState.Running)); //Wait for tasks to finish - while(_allTasks.Any(task => task.isBeingExecuted)) + while(_allTasks.Any(task => task.state is TrangaTask.ExecutionState.Running or TrangaTask.ExecutionState.Enqueued)) Thread.Sleep(10); Environment.Exit(0); } diff --git a/Tranga/TrangaTask.cs b/Tranga/TrangaTask.cs index 686c1fd..b313e98 100644 --- a/Tranga/TrangaTask.cs +++ b/Tranga/TrangaTask.cs @@ -15,7 +15,14 @@ public class TrangaTask public Task task { get; } public Publication? publication { get; } public string language { get; } - [JsonIgnore]public bool isBeingExecuted { get; set; } + [JsonIgnore]public ExecutionState state { get; set; } + + public enum ExecutionState + { + Waiting, + Enqueued, + Running + }; public TrangaTask(Task task, string? connectorName, Publication? publication, TimeSpan reoccurrence, string language = "") { @@ -36,7 +43,7 @@ public class TrangaTask /// True if elapsed time since last execution is greater than set interval public bool ShouldExecute() { - return DateTime.Now.Subtract(this.lastExecuted) > reoccurrence; + return DateTime.Now.Subtract(this.lastExecuted) > reoccurrence && state is ExecutionState.Waiting; } public enum Task @@ -49,6 +56,6 @@ public class TrangaTask public override string ToString() { - return $"{task}\t{lastExecuted}\t{reoccurrence}\t{(isBeingExecuted ? "running" : "waiting")}\t{connectorName}\t{publication?.sortName}"; + return $"{task}\t{lastExecuted}\t{reoccurrence}\t{state}\t{connectorName}\t{publication?.sortName}"; } } \ No newline at end of file