Renamed DownloadNewChaptersTask to MonitorPublicationTask
Added TrangaTask.Clone() method Rewrote TrangaTask.progress for the billionth+1 time. Removed Increment and DecrementProgress methods Removed TrangaTask.ReplaceFailedChildTask method Changed return type of TrangaTask.ExecuteTask to bool, signifying success. Added Failed Execution state to TrangaTask Replaced taskManager failed-task logic Removed TaskManager bulky AddTask and DeleteTask methods Removed TaskManager bulky Constructor
This commit is contained in:
parent
23dfdc0933
commit
e883277400
@ -112,14 +112,12 @@ app.MapPost("/Tasks/CreateMonitorTask",
|
||||
Publication? publication = taskManager.GetAllPublications().FirstOrDefault(pub => pub.internalId == internalId);
|
||||
if (publication is null)
|
||||
return;
|
||||
taskManager.AddTask(new DownloadNewChaptersTask(TrangaTask.Task.DownloadNewChapters, connectorName,
|
||||
(Publication)publication,
|
||||
TimeSpan.Parse(reoccurrenceTime), language ?? "en"));
|
||||
taskManager.AddTask(new MonitorPublicationTask(connectorName, (Publication)publication, TimeSpan.Parse(reoccurrenceTime), language ?? "en"));
|
||||
});
|
||||
|
||||
app.MapPost("/Tasks/CreateUpdateLibraryTask", (string reoccurrenceTime) =>
|
||||
{
|
||||
taskManager.AddTask(new UpdateLibrariesTask(TrangaTask.Task.UpdateLibraries, TimeSpan.Parse(reoccurrenceTime)));
|
||||
taskManager.AddTask(new UpdateLibrariesTask(TimeSpan.Parse(reoccurrenceTime)));
|
||||
});
|
||||
|
||||
app.MapPost("/Tasks/CreateDownloadChaptersTask", (string connectorName, string internalId, string chapters, string? language) => {
|
||||
@ -134,14 +132,14 @@ app.MapPost("/Tasks/CreateDownloadChaptersTask", (string connectorName, string i
|
||||
|
||||
IEnumerable<Chapter> toDownload = connector.SearchChapters((Publication)publication, chapters, language ?? "en");
|
||||
foreach(Chapter chapter in toDownload)
|
||||
taskManager.AddTask(new DownloadChapterTask(TrangaTask.Task.DownloadChapter, connectorName,
|
||||
(Publication)publication, chapter, "en"));
|
||||
taskManager.AddTask(new DownloadChapterTask(connectorName, (Publication)publication, chapter, "en"));
|
||||
});
|
||||
|
||||
app.MapDelete("/Tasks/Delete", (string taskType, string? connectorName, string? publicationId) =>
|
||||
{
|
||||
TrangaTask.Task task = Enum.Parse<TrangaTask.Task>(taskType);
|
||||
taskManager.DeleteTask(task, connectorName, publicationId);
|
||||
foreach(TrangaTask tTask in taskManager.GetTasksMatching(task, connectorName, internalId: publicationId))
|
||||
taskManager.DeleteTask(tTask);
|
||||
});
|
||||
|
||||
app.MapGet("/Tasks/Get", (string taskType, string? connectorName, string? searchString) =>
|
||||
@ -167,7 +165,7 @@ app.MapGet("/Tasks/GetProgress", (string taskType, string connectorName, string
|
||||
{
|
||||
TrangaTask? task = null;
|
||||
TrangaTask.Task pTask = Enum.Parse<TrangaTask.Task>(taskType);
|
||||
if (pTask is TrangaTask.Task.DownloadNewChapters)
|
||||
if (pTask is TrangaTask.Task.MonitorPublication)
|
||||
{
|
||||
task = taskManager.GetTasksMatching(pTask, connectorName: connectorName, internalId: publicationId).FirstOrDefault();
|
||||
}else if (pTask is TrangaTask.Task.DownloadChapter && chapterSortNumber is not null)
|
||||
@ -192,7 +190,7 @@ app.MapPost("/Tasks/Start", (string taskType, string? connectorName, string? int
|
||||
{
|
||||
TrangaTask.Task pTask = Enum.Parse<TrangaTask.Task>(taskType);
|
||||
TrangaTask? task = taskManager
|
||||
.GetTasksMatching(pTask, connectorName: connectorName, internalId: internalId)?.FirstOrDefault();
|
||||
.GetTasksMatching(pTask, connectorName: connectorName, internalId: internalId).FirstOrDefault();
|
||||
|
||||
if (task is null)
|
||||
return;
|
||||
@ -217,7 +215,7 @@ app.MapPost("/Queue/Enqueue", (string taskType, string? connectorName, string? p
|
||||
{
|
||||
TrangaTask.Task pTask = Enum.Parse<TrangaTask.Task>(taskType);
|
||||
TrangaTask? task = taskManager
|
||||
.GetTasksMatching(pTask, connectorName: connectorName, internalId: publicationId)?.First();
|
||||
.GetTasksMatching(pTask, connectorName: connectorName, internalId: publicationId).FirstOrDefault();
|
||||
|
||||
if (task is null)
|
||||
return;
|
||||
@ -235,7 +233,7 @@ app.MapDelete("/Queue/Dequeue", (string taskType, string? connectorName, string?
|
||||
{
|
||||
TrangaTask.Task pTask = Enum.Parse<TrangaTask.Task>(taskType);
|
||||
TrangaTask? task = taskManager
|
||||
.GetTasksMatching(pTask, connectorName: connectorName, internalId: publicationId)?.First();
|
||||
.GetTasksMatching(pTask, connectorName: connectorName, internalId: publicationId).FirstOrDefault();
|
||||
|
||||
if (task is null)
|
||||
return;
|
||||
|
@ -335,8 +335,9 @@ public static class Tranga_Cli
|
||||
|
||||
TimeSpan reoccurrence = SelectReoccurrence(logger);
|
||||
logger.WriteLine("Tranga_CLI", "Sending Task to TaskManager");
|
||||
TrangaTask? newTask = taskManager.AddTask(TrangaTask.Task.DownloadNewChapters, connector.name, publication.Value.publicationId, reoccurrence, "en");
|
||||
Console.WriteLine(newTask);
|
||||
TrangaTask nTask = new MonitorPublicationTask(connector.name, (Publication)publication, reoccurrence, "en");
|
||||
taskManager.AddTask(nTask);
|
||||
Console.WriteLine(nTask);
|
||||
}
|
||||
|
||||
private static void AddTaskToQueue(TaskManager taskManager, Logger logger)
|
||||
@ -408,20 +409,19 @@ public static class Tranga_Cli
|
||||
return;
|
||||
}
|
||||
|
||||
if (task is TrangaTask.Task.DownloadNewChapters)
|
||||
if (task is TrangaTask.Task.MonitorPublication)
|
||||
{
|
||||
TimeSpan reoccurrence = SelectReoccurrence(logger);
|
||||
logger.WriteLine("Tranga_CLI", "Sending Task to TaskManager");
|
||||
|
||||
TrangaTask newTask = new DownloadNewChaptersTask(TrangaTask.Task.DownloadNewChapters, connector!.name, (Publication)publication!, reoccurrence, "en");
|
||||
TrangaTask newTask = new MonitorPublicationTask(connector!.name, (Publication)publication!, reoccurrence, "en");
|
||||
taskManager.AddTask(newTask);
|
||||
Console.WriteLine(newTask);
|
||||
}else if (task is TrangaTask.Task.DownloadChapter)
|
||||
{
|
||||
foreach (Chapter chapter in SelectChapters(connector!, (Publication)publication!, logger))
|
||||
{
|
||||
TrangaTask newTask = new DownloadChapterTask(TrangaTask.Task.DownloadChapter, connector!.name,
|
||||
(Publication)publication!, chapter, "en");
|
||||
TrangaTask newTask = new DownloadChapterTask(connector!.name, (Publication)publication, chapter, "en");
|
||||
taskManager.AddTask(newTask);
|
||||
Console.WriteLine(newTask);
|
||||
}
|
||||
|
@ -20,17 +20,6 @@ public class TaskManager
|
||||
|
||||
private readonly Dictionary<DownloadChapterTask, CancellationTokenSource> _runningDownloadChapterTasks = new();
|
||||
|
||||
/// <param name="downloadFolderPath">Local path to save data (Manga) to</param>
|
||||
/// <param name="workingDirectory">Path to the working directory</param>
|
||||
/// <param name="imageCachePath">Path to the cover-image cache</param>
|
||||
/// <param name="libraryManagers"></param>
|
||||
/// <param name="notificationManagers"></param>
|
||||
/// <param name="logger"></param>
|
||||
public TaskManager(string downloadFolderPath, string workingDirectory, string imageCachePath, HashSet<LibraryManager> libraryManagers, HashSet<NotificationManager> notificationManagers, Logger? logger = null) : this(new TrangaSettings(downloadFolderPath, workingDirectory, libraryManagers, notificationManagers), logger)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public TaskManager(TrangaSettings settings, Logger? logger = null)
|
||||
{
|
||||
this.logger = logger;
|
||||
@ -65,53 +54,46 @@ public class TaskManager
|
||||
waitingButExecute.state = TrangaTask.ExecutionState.Enqueued;
|
||||
}
|
||||
|
||||
foreach (TrangaTask task in _allTasks.Where(enqueuedTask => enqueuedTask.state is TrangaTask.ExecutionState.Enqueued))
|
||||
foreach (TrangaTask enqueuedTask in _allTasks.Where(enqueuedTask => enqueuedTask.state is TrangaTask.ExecutionState.Enqueued))
|
||||
{
|
||||
switch (task.task)
|
||||
switch (enqueuedTask.task)
|
||||
{
|
||||
case TrangaTask.Task.DownloadNewChapters:
|
||||
if (!_allTasks.Any(taskQuery =>
|
||||
taskQuery.task == TrangaTask.Task.DownloadNewChapters &&
|
||||
taskQuery.state is TrangaTask.ExecutionState.Running &&
|
||||
((DownloadNewChaptersTask)taskQuery).connectorName == ((DownloadNewChaptersTask)task).connectorName))
|
||||
{
|
||||
ExecuteTaskNow(task);
|
||||
}
|
||||
break;
|
||||
case TrangaTask.Task.DownloadChapter:
|
||||
case TrangaTask.Task.MonitorPublication:
|
||||
if (!_allTasks.Any(taskQuery =>
|
||||
taskQuery.task == TrangaTask.Task.DownloadChapter &&
|
||||
taskQuery.state is TrangaTask.ExecutionState.Running &&
|
||||
((DownloadChapterTask)taskQuery).connectorName == ((DownloadChapterTask)task).connectorName))
|
||||
{
|
||||
ExecuteTaskNow(task);
|
||||
if (taskQuery.state is not TrangaTask.ExecutionState.Running) return false;
|
||||
switch (taskQuery)
|
||||
{
|
||||
case DownloadChapterTask dct when enqueuedTask is DownloadChapterTask eDct && dct.connectorName == eDct.connectorName:
|
||||
case MonitorPublicationTask mpt when enqueuedTask is MonitorPublicationTask eMpt && mpt.connectorName == eMpt.connectorName:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}))
|
||||
{
|
||||
ExecuteTaskNow(enqueuedTask);
|
||||
}
|
||||
break;
|
||||
case TrangaTask.Task.UpdateLibraries:
|
||||
ExecuteTaskNow(task);
|
||||
ExecuteTaskNow(enqueuedTask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
HashSet<DownloadChapterTask> failedToRemove = new();
|
||||
foreach (KeyValuePair<DownloadChapterTask, CancellationTokenSource> removeTask in _runningDownloadChapterTasks)
|
||||
foreach (TrangaTask failedTask in _allTasks.Where(taskQuery =>
|
||||
taskQuery.state is TrangaTask.ExecutionState.Failed))
|
||||
{
|
||||
if (removeTask.Key.GetType() == typeof(DownloadChapterTask) &&
|
||||
DateTime.Now.Subtract(removeTask.Key.lastChange) > TimeSpan.FromMinutes(3))//3 Minutes since last update to task -> remove
|
||||
switch (failedTask.task)
|
||||
{
|
||||
logger?.WriteLine(this.GetType().ToString(), $"Disposing failed task {removeTask.Key}.");
|
||||
removeTask.Value.Cancel();
|
||||
failedToRemove.Add(removeTask.Key);
|
||||
}
|
||||
}
|
||||
foreach (DownloadChapterTask taskToRestart in failedToRemove)
|
||||
{
|
||||
DeleteTask(taskToRestart);
|
||||
DownloadChapterTask newTask = new (taskToRestart.task, taskToRestart.connectorName,
|
||||
taskToRestart.publication, taskToRestart.chapter, taskToRestart.language,
|
||||
(DownloadNewChaptersTask?)taskToRestart.parentTask);
|
||||
case TrangaTask.Task.DownloadChapter:
|
||||
DeleteTask(failedTask);
|
||||
TrangaTask newTask = failedTask.Clone();
|
||||
failedTask.parentTask?.AddChildTask(newTask);
|
||||
AddTask(newTask);
|
||||
taskToRestart.parentTask?.ReplaceFailedChildTask(taskToRestart, newTask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(waitingTasksCount != _allTasks.Count(task => task.state is TrangaTask.ExecutionState.Waiting))
|
||||
@ -150,23 +132,19 @@ public class TaskManager
|
||||
_allTasks.RemoveWhere(trangaTask => trangaTask.task is TrangaTask.Task.UpdateLibraries);
|
||||
_allTasks.Add(newTask);
|
||||
break;
|
||||
case TrangaTask.Task.DownloadNewChapters:
|
||||
IEnumerable<TrangaTask> matchingdnc =
|
||||
_allTasks.Where(mTask => mTask.GetType() == typeof(DownloadNewChaptersTask));
|
||||
if (!matchingdnc.Any(mTask =>
|
||||
((DownloadNewChaptersTask)mTask).publication.internalId == ((DownloadNewChaptersTask)newTask).publication.internalId &&
|
||||
((DownloadNewChaptersTask)mTask).connectorName == ((DownloadNewChaptersTask)newTask).connectorName))
|
||||
case TrangaTask.Task.MonitorPublication:
|
||||
if (!_allTasks.Any(mTask => mTask is MonitorPublicationTask mpt && newTask is MonitorPublicationTask nMpt &&
|
||||
mpt.publication.internalId == nMpt.publication.internalId &&
|
||||
mpt.connectorName == nMpt.connectorName))
|
||||
_allTasks.Add(newTask);
|
||||
else
|
||||
logger?.WriteLine(this.GetType().ToString(), $"Task already exists {newTask}");
|
||||
break;
|
||||
case TrangaTask.Task.DownloadChapter:
|
||||
IEnumerable<TrangaTask> matchingdc =
|
||||
_allTasks.Where(mTask => mTask.GetType() == typeof(DownloadChapterTask));
|
||||
if (!matchingdc.Any(mTask =>
|
||||
((DownloadChapterTask)mTask).publication.internalId == ((DownloadChapterTask)newTask).publication.internalId &&
|
||||
((DownloadChapterTask)mTask).connectorName == ((DownloadChapterTask)newTask).connectorName &&
|
||||
((DownloadChapterTask)mTask).chapter.sortNumber == ((DownloadChapterTask)newTask).chapter.sortNumber))
|
||||
if (!_allTasks.Any(mTask => mTask is DownloadChapterTask dct && newTask is DownloadChapterTask nDct &&
|
||||
dct.publication.internalId == nDct.publication.internalId &&
|
||||
dct.connectorName == nDct.connectorName &&
|
||||
dct.chapter.sortNumber == nDct.chapter.sortNumber))
|
||||
_allTasks.Add(newTask);
|
||||
else
|
||||
logger?.WriteLine(this.GetType().ToString(), $"Task already exists {newTask}");
|
||||
@ -179,130 +157,60 @@ public class TaskManager
|
||||
{
|
||||
logger?.WriteLine(this.GetType().ToString(), $"Removing Task {removeTask}");
|
||||
_allTasks.Remove(removeTask);
|
||||
if (removeTask.parentTask is not null)
|
||||
removeTask.parentTask.RemoveChildTask(removeTask);
|
||||
if (removeTask.GetType() == typeof(DownloadChapterTask) && _runningDownloadChapterTasks.ContainsKey((DownloadChapterTask)removeTask))
|
||||
removeTask.parentTask?.RemoveChildTask(removeTask);
|
||||
if (removeTask is DownloadChapterTask cRemoveTask && _runningDownloadChapterTasks.ContainsKey(cRemoveTask))
|
||||
{
|
||||
_runningDownloadChapterTasks[(DownloadChapterTask)removeTask].Cancel();
|
||||
_runningDownloadChapterTasks.Remove((DownloadChapterTask)removeTask);
|
||||
_runningDownloadChapterTasks[cRemoveTask].Cancel();
|
||||
_runningDownloadChapterTasks.Remove(cRemoveTask);
|
||||
}
|
||||
}
|
||||
|
||||
public TrangaTask? AddTask(TrangaTask.Task taskType, string? connectorName, string? internalId,
|
||||
TimeSpan reoccurrenceTime, string? language = "en")
|
||||
{
|
||||
TrangaTask? newTask = null;
|
||||
switch (taskType)
|
||||
{
|
||||
case TrangaTask.Task.UpdateLibraries:
|
||||
newTask = new UpdateLibrariesTask(taskType, reoccurrenceTime);
|
||||
break;
|
||||
case TrangaTask.Task.DownloadNewChapters:
|
||||
if (connectorName is null)
|
||||
logger?.WriteLine(this.GetType().ToString(), $"Value connectorName can not be null.");
|
||||
if(internalId is null)
|
||||
logger?.WriteLine(this.GetType().ToString(), $"Value internalId can not be null.");
|
||||
if(language is null)
|
||||
logger?.WriteLine(this.GetType().ToString(), $"Value language can not be null.");
|
||||
if (connectorName is null || internalId is null || language is null)
|
||||
return null;
|
||||
GetConnector(connectorName); //Check if connectorName is valid
|
||||
Publication publication = GetAllPublications().First(pub => pub.internalId == internalId);
|
||||
newTask = new DownloadNewChaptersTask(taskType, connectorName!, publication, reoccurrenceTime, language!);
|
||||
break;
|
||||
}
|
||||
if(newTask is not null)
|
||||
AddTask(newTask);
|
||||
return newTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes Task from task-collection
|
||||
/// </summary>
|
||||
/// <param name="task">TrangaTask.Task type</param>
|
||||
/// <param name="connectorName">Name of Connector that was used</param>
|
||||
/// <param name="publicationId">Publication that was used</param>
|
||||
public void DeleteTask(TrangaTask.Task task, string? connectorName, string? publicationId)
|
||||
{
|
||||
logger?.WriteLine(this.GetType().ToString(), $"Removing Task {task} {publicationId}");
|
||||
|
||||
switch (task)
|
||||
{
|
||||
case TrangaTask.Task.UpdateLibraries:
|
||||
//Only one UpdateKomgaLibrary Task
|
||||
logger?.WriteLine(this.GetType().ToString(), $"Removing old {task}-Task.");
|
||||
_allTasks.RemoveWhere(trangaTask => trangaTask.task is TrangaTask.Task.UpdateLibraries);
|
||||
break;
|
||||
case TrangaTask.Task.DownloadNewChapters:
|
||||
if (connectorName is null || publicationId is null)
|
||||
logger?.WriteLine(this.GetType().ToString(), "connectorName and publication can not be null");
|
||||
else
|
||||
{
|
||||
_allTasks.RemoveWhere(mTask =>
|
||||
mTask.GetType() == typeof(DownloadNewChaptersTask) &&
|
||||
((DownloadNewChaptersTask)mTask).publication.internalId == publicationId &&
|
||||
((DownloadNewChaptersTask)mTask).connectorName == connectorName);
|
||||
foreach(TrangaTask rTask in _allTasks.Where(mTask =>
|
||||
mTask.GetType() == typeof(DownloadChapterTask) &&
|
||||
((DownloadChapterTask)mTask).publication.internalId == publicationId &&
|
||||
((DownloadChapterTask)mTask).connectorName == connectorName))
|
||||
DeleteTask(rTask);
|
||||
}
|
||||
break;
|
||||
}
|
||||
ExportDataAndSettings();
|
||||
}
|
||||
|
||||
public IEnumerable<TrangaTask> GetTasksMatching(TrangaTask.Task taskType, string? connectorName = null, string? searchString = null, string? internalId = null, string? chapterSortNumber = null)
|
||||
{
|
||||
switch (taskType)
|
||||
{
|
||||
case TrangaTask.Task.UpdateLibraries:
|
||||
return _allTasks.Where(tTask => tTask.task == TrangaTask.Task.UpdateLibraries);
|
||||
case TrangaTask.Task.DownloadNewChapters:
|
||||
case TrangaTask.Task.MonitorPublication:
|
||||
if(connectorName is null)
|
||||
return _allTasks.Where(tTask => tTask.task == taskType);
|
||||
GetConnector(connectorName);//Name check
|
||||
IEnumerable<TrangaTask> matchingdnc = _allTasks.Where(tTask => tTask.GetType() == typeof(DownloadNewChaptersTask));
|
||||
if (searchString is not null)
|
||||
{
|
||||
return matchingdnc.Where(mTask =>
|
||||
((DownloadNewChaptersTask)mTask).connectorName == connectorName &&
|
||||
((DownloadNewChaptersTask)mTask).ToString().Contains(searchString, StringComparison.InvariantCultureIgnoreCase));
|
||||
return _allTasks.Where(mTask =>
|
||||
mTask is MonitorPublicationTask mpt && mpt.connectorName == connectorName &&
|
||||
mpt.ToString().Contains(searchString, StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
else if (internalId is not null)
|
||||
{
|
||||
return matchingdnc.Where(mTask =>
|
||||
((DownloadNewChaptersTask)mTask).connectorName == connectorName &&
|
||||
((DownloadNewChaptersTask)mTask).publication.internalId == internalId);
|
||||
return _allTasks.Where(mTask =>
|
||||
mTask is MonitorPublicationTask mpt && mpt.connectorName == connectorName &&
|
||||
mpt.publication.internalId == internalId);
|
||||
}
|
||||
else
|
||||
return _allTasks.Where(tTask =>
|
||||
tTask.GetType() == typeof(DownloadNewChaptersTask) &&
|
||||
((DownloadNewChaptersTask)tTask).connectorName == connectorName);
|
||||
tTask is MonitorPublicationTask mpt && mpt.connectorName == connectorName);
|
||||
|
||||
case TrangaTask.Task.DownloadChapter:
|
||||
if(connectorName is null)
|
||||
return _allTasks.Where(tTask => tTask.task == taskType);
|
||||
GetConnector(connectorName);//Name check
|
||||
IEnumerable<TrangaTask> matchingdc = _allTasks.Where(tTask => tTask.GetType() == typeof(DownloadChapterTask));
|
||||
if (searchString is not null)
|
||||
{
|
||||
return matchingdc.Where(mTask =>
|
||||
((DownloadChapterTask)mTask).connectorName == connectorName &&
|
||||
((DownloadChapterTask)mTask).ToString().Contains(searchString, StringComparison.InvariantCultureIgnoreCase));
|
||||
return _allTasks.Where(mTask =>
|
||||
mTask is DownloadChapterTask dct && dct.connectorName == connectorName &&
|
||||
dct.ToString().Contains(searchString, StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
else if (internalId is not null && chapterSortNumber is not null)
|
||||
{
|
||||
return matchingdc.Where(mTask =>
|
||||
((DownloadChapterTask)mTask).connectorName == connectorName &&
|
||||
((DownloadChapterTask)mTask).publication.publicationId == internalId &&
|
||||
((DownloadChapterTask)mTask).chapter.sortNumber == chapterSortNumber);
|
||||
return _allTasks.Where(mTask =>
|
||||
mTask is DownloadChapterTask dct && dct.connectorName == connectorName &&
|
||||
dct.publication.publicationId == internalId &&
|
||||
dct.chapter.sortNumber == chapterSortNumber);
|
||||
}
|
||||
else
|
||||
return _allTasks.Where(tTask =>
|
||||
tTask.GetType() == typeof(DownloadChapterTask) &&
|
||||
((DownloadChapterTask)tTask).connectorName == connectorName);
|
||||
return _allTasks.Where(mTask =>
|
||||
mTask is DownloadChapterTask dct && dct.connectorName == connectorName);
|
||||
|
||||
default:
|
||||
return Array.Empty<TrangaTask>();
|
||||
|
@ -11,7 +11,7 @@ namespace Tranga;
|
||||
/// <summary>
|
||||
/// Stores information on Task, when implementing new Tasks also update the serializer
|
||||
/// </summary>
|
||||
[JsonDerivedType(typeof(DownloadNewChaptersTask), 2)]
|
||||
[JsonDerivedType(typeof(MonitorPublicationTask), 2)]
|
||||
[JsonDerivedType(typeof(UpdateLibrariesTask), 3)]
|
||||
[JsonDerivedType(typeof(DownloadChapterTask), 4)]
|
||||
public abstract class TrangaTask
|
||||
@ -20,27 +20,27 @@ public abstract class TrangaTask
|
||||
// ReSharper disable once MemberCanBePrivate.Global I want it thaaat way
|
||||
public TimeSpan reoccurrence { get; }
|
||||
public DateTime lastExecuted { get; set; }
|
||||
public Task task { get; }
|
||||
public string taskId { get; set; }
|
||||
[Newtonsoft.Json.JsonIgnore] public ExecutionState state { get; set; }
|
||||
[Newtonsoft.Json.JsonIgnore] protected HashSet<TrangaTask> childTasks { get; }
|
||||
public Task task { get; }
|
||||
public string taskId { get; }
|
||||
[Newtonsoft.Json.JsonIgnore] public TrangaTask? parentTask { get; set; }
|
||||
public string? parentTaskId { get; set; }
|
||||
[Newtonsoft.Json.JsonIgnore]public double progress { get; private set; }
|
||||
[Newtonsoft.Json.JsonIgnore] protected HashSet<TrangaTask> childTasks { get; }
|
||||
[Newtonsoft.Json.JsonIgnore] public double progress => GetProgress();
|
||||
[Newtonsoft.Json.JsonIgnore]public DateTime executionStarted { get; private set; }
|
||||
[Newtonsoft.Json.JsonIgnore]public DateTime lastChange { get; private set; }
|
||||
[Newtonsoft.Json.JsonIgnore]public DateTime executionApproximatelyFinished => progress != 0 ? lastChange.Add(GetRemainingTime()) : DateTime.MaxValue;
|
||||
[Newtonsoft.Json.JsonIgnore]public TimeSpan executionApproximatelyRemaining => executionApproximatelyFinished.Subtract(DateTime.Now);
|
||||
[Newtonsoft.Json.JsonIgnore]public DateTime nextExecution => lastExecuted.Add(reoccurrence);
|
||||
|
||||
public enum ExecutionState { Waiting, Enqueued, Running }
|
||||
public enum ExecutionState { Waiting, Enqueued, Running, Failed }
|
||||
|
||||
protected TrangaTask(Task task, TimeSpan reoccurrence, TrangaTask? parentTask = null)
|
||||
{
|
||||
this.reoccurrence = reoccurrence;
|
||||
this.lastExecuted = DateTime.Now.Subtract(reoccurrence);
|
||||
this.task = task;
|
||||
this.executionStarted = DateTime.Now;
|
||||
this.executionStarted = DateTime.UnixEpoch;
|
||||
this.lastChange = DateTime.MaxValue;
|
||||
this.taskId = Convert.ToBase64String(BitConverter.GetBytes(new Random().Next()));
|
||||
this.childTasks = new();
|
||||
@ -54,7 +54,11 @@ public abstract class TrangaTask
|
||||
/// <param name="taskManager"></param>
|
||||
/// <param name="logger"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
protected abstract void ExecuteTask(TaskManager taskManager, Logger? logger, CancellationToken? cancellationToken = null);
|
||||
protected abstract bool ExecuteTask(TaskManager taskManager, Logger? logger, CancellationToken? cancellationToken = null);
|
||||
|
||||
public abstract TrangaTask Clone();
|
||||
|
||||
protected abstract double GetProgress();
|
||||
|
||||
/// <summary>
|
||||
/// Execute the task
|
||||
@ -68,18 +72,20 @@ public abstract class TrangaTask
|
||||
this.state = ExecutionState.Running;
|
||||
this.executionStarted = DateTime.Now;
|
||||
this.lastChange = DateTime.Now;
|
||||
ExecuteTask(taskManager, logger, cancellationToken);
|
||||
bool success = ExecuteTask(taskManager, logger, cancellationToken);
|
||||
while(childTasks.Any(ct => ct.state is ExecutionState.Enqueued or ExecutionState.Running))
|
||||
Thread.Sleep(1000);
|
||||
if (success)
|
||||
{
|
||||
this.lastExecuted = DateTime.Now;
|
||||
this.state = ExecutionState.Waiting;
|
||||
logger?.WriteLine(this.GetType().ToString(), $"Finished Executing Task {this}");
|
||||
}
|
||||
|
||||
public void ReplaceFailedChildTask(DownloadChapterTask failed, DownloadChapterTask newTask)
|
||||
else
|
||||
{
|
||||
this.RemoveChildTask(failed);
|
||||
this.AddChildTask(newTask);
|
||||
this.lastExecuted = DateTime.MaxValue;
|
||||
this.state = ExecutionState.Failed;
|
||||
}
|
||||
logger?.WriteLine(this.GetType().ToString(), $"Finished Executing Task {this}");
|
||||
}
|
||||
|
||||
public void AddChildTask(TrangaTask childTask)
|
||||
@ -90,40 +96,22 @@ public abstract class TrangaTask
|
||||
public void RemoveChildTask(TrangaTask childTask)
|
||||
{
|
||||
this.childTasks.Remove(childTask);
|
||||
this.DecrementProgress(childTask.progress);
|
||||
}
|
||||
|
||||
public void IncrementProgress(double amount)
|
||||
{
|
||||
this.lastChange = DateTime.Now;
|
||||
this.progress += amount / (childTasks.Count > 0 ? childTasks.Count : 1);
|
||||
if (parentTask is not null)
|
||||
{
|
||||
parentTask.IncrementProgress(amount);
|
||||
parentTask.state = ExecutionState.Running;
|
||||
}
|
||||
}
|
||||
|
||||
public void DecrementProgress(double amount)
|
||||
{
|
||||
this.lastChange = DateTime.Now;
|
||||
this.progress -= amount / childTasks.Count > 0 ? childTasks.Count : 1;
|
||||
parentTask?.DecrementProgress(amount);
|
||||
}
|
||||
|
||||
private TimeSpan GetRemainingTime()
|
||||
{
|
||||
if(progress == 0)
|
||||
return DateTime.MaxValue.Subtract(DateTime.Now);
|
||||
if(progress == 0 || lastChange > executionStarted)
|
||||
return DateTime.MaxValue.Subtract(DateTime.Now.AddYears(1));
|
||||
TimeSpan elapsed = lastChange.Subtract(executionStarted);
|
||||
return elapsed.Divide(progress).Subtract(elapsed);
|
||||
}
|
||||
|
||||
public enum Task : byte
|
||||
{
|
||||
DownloadNewChapters = 2,
|
||||
MonitorPublication = 2,
|
||||
UpdateLibraries = 3,
|
||||
DownloadChapter = 4
|
||||
DownloadChapter = 4,
|
||||
DownloadNewChapters = 2 //legacy
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
@ -135,14 +123,14 @@ public abstract class TrangaTask
|
||||
{
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return (objectType == typeof(TrangaTask));
|
||||
return objectType == typeof(TrangaTask);
|
||||
}
|
||||
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
|
||||
{
|
||||
JObject jo = JObject.Load(reader);
|
||||
if (jo["task"]!.Value<Int64>() == (Int64)Task.DownloadNewChapters)
|
||||
return jo.ToObject<DownloadNewChaptersTask>(serializer)!;
|
||||
if (jo["task"]!.Value<Int64>() == (Int64)Task.MonitorPublication)
|
||||
return jo.ToObject<MonitorPublicationTask>(serializer)!;
|
||||
|
||||
if (jo["task"]!.Value<Int64>() == (Int64)Task.UpdateLibraries)
|
||||
return jo.ToObject<UpdateLibrariesTask>(serializer)!;
|
||||
|
@ -10,7 +10,9 @@ public class DownloadChapterTask : TrangaTask
|
||||
public string language { get; }
|
||||
public Chapter chapter { get; }
|
||||
|
||||
public DownloadChapterTask(Task task, string connectorName, Publication publication, Chapter chapter, string language = "en", DownloadNewChaptersTask? parentTask = null) : base(task, TimeSpan.Zero, parentTask)
|
||||
private double _dctProgress = 0;
|
||||
|
||||
public DownloadChapterTask(string connectorName, Publication publication, Chapter chapter, string language = "en", MonitorPublicationTask? parentTask = null) : base(Task.DownloadChapter, TimeSpan.Zero, parentTask)
|
||||
{
|
||||
this.chapter = chapter;
|
||||
this.connectorName = connectorName;
|
||||
@ -18,21 +20,34 @@ public class DownloadChapterTask : TrangaTask
|
||||
this.language = language;
|
||||
}
|
||||
|
||||
protected override void ExecuteTask(TaskManager taskManager, Logger? logger, CancellationToken? cancellationToken = null)
|
||||
protected override bool ExecuteTask(TaskManager taskManager, Logger? logger, CancellationToken? cancellationToken = null)
|
||||
{
|
||||
if (cancellationToken?.IsCancellationRequested??false)
|
||||
return;
|
||||
if(this.parentTask is not null)
|
||||
this.parentTask.state = ExecutionState.Running;
|
||||
return false;
|
||||
Connector connector = taskManager.GetConnector(this.connectorName);
|
||||
connector.CopyCoverFromCacheToDownloadLocation(this.publication, taskManager.settings);
|
||||
bool downloadSuccess = connector.DownloadChapter(this.publication, this.chapter, this, cancellationToken);
|
||||
if(this.parentTask is not null)
|
||||
this.parentTask.state = ExecutionState.Waiting;
|
||||
taskManager.DeleteTask(this);
|
||||
if(downloadSuccess && parentTask is not null)
|
||||
foreach(NotificationManager nm in taskManager.settings.notificationManagers)
|
||||
nm.SendNotification("New Chapter downloaded", $"{this.publication.sortName} {this.chapter.chapterNumber} {this.chapter.name}");
|
||||
return downloadSuccess;
|
||||
}
|
||||
|
||||
public override TrangaTask Clone()
|
||||
{
|
||||
return new DownloadChapterTask(this.connectorName, this.publication, this.chapter,
|
||||
this.language, (MonitorPublicationTask?)this.parentTask);
|
||||
}
|
||||
|
||||
protected override double GetProgress()
|
||||
{
|
||||
return _dctProgress;
|
||||
}
|
||||
|
||||
internal void IncrementProgress(double amount)
|
||||
{
|
||||
this._dctProgress += amount;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
|
@ -1,45 +0,0 @@
|
||||
using Logging;
|
||||
|
||||
namespace Tranga.TrangaTasks;
|
||||
|
||||
public class DownloadNewChaptersTask : TrangaTask
|
||||
{
|
||||
public string connectorName { get; }
|
||||
public Publication publication { get; }
|
||||
public string language { get; }
|
||||
public DownloadNewChaptersTask(Task task, string connectorName, Publication publication, TimeSpan reoccurrence, string language = "en") : base(task, reoccurrence)
|
||||
{
|
||||
this.connectorName = connectorName;
|
||||
this.publication = publication;
|
||||
this.language = language;
|
||||
}
|
||||
|
||||
protected override void ExecuteTask(TaskManager taskManager, Logger? logger, CancellationToken? cancellationToken = null)
|
||||
{
|
||||
if (cancellationToken?.IsCancellationRequested??false)
|
||||
return;
|
||||
Publication pub = publication!;
|
||||
Connector connector = taskManager.GetConnector(this.connectorName);
|
||||
|
||||
//Check if Publication already has a Folder
|
||||
pub.CreatePublicationFolder(taskManager.settings.downloadLocation);
|
||||
List<Chapter> newChapters = taskManager.GetNewChaptersList(connector, pub, language!);
|
||||
|
||||
connector.CopyCoverFromCacheToDownloadLocation(pub, taskManager.settings);
|
||||
|
||||
pub.SaveSeriesInfoJson(connector.downloadLocation);
|
||||
|
||||
foreach (Chapter newChapter in newChapters)
|
||||
{
|
||||
DownloadChapterTask newTask = new (Task.DownloadChapter, this.connectorName, pub, newChapter, this.language, this);
|
||||
this.childTasks.Add(newTask);
|
||||
newTask.state = ExecutionState.Enqueued;
|
||||
taskManager.AddTask(newTask);
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{base.ToString()}, {connectorName}, {publication.sortName} {publication.internalId}";
|
||||
}
|
||||
}
|
59
Tranga/TrangaTasks/MonitorPublicationTask.cs
Normal file
59
Tranga/TrangaTasks/MonitorPublicationTask.cs
Normal file
@ -0,0 +1,59 @@
|
||||
using Logging;
|
||||
|
||||
namespace Tranga.TrangaTasks;
|
||||
|
||||
public class MonitorPublicationTask : TrangaTask
|
||||
{
|
||||
public string connectorName { get; }
|
||||
public Publication publication { get; }
|
||||
public string language { get; }
|
||||
public MonitorPublicationTask(string connectorName, Publication publication, TimeSpan reoccurrence, string language = "en") : base(Task.MonitorPublication, reoccurrence)
|
||||
{
|
||||
this.connectorName = connectorName;
|
||||
this.publication = publication;
|
||||
this.language = language;
|
||||
}
|
||||
|
||||
protected override bool ExecuteTask(TaskManager taskManager, Logger? logger, CancellationToken? cancellationToken = null)
|
||||
{
|
||||
if (cancellationToken?.IsCancellationRequested??false)
|
||||
return false;
|
||||
Connector connector = taskManager.GetConnector(this.connectorName);
|
||||
|
||||
//Check if Publication already has a Folder
|
||||
publication.CreatePublicationFolder(taskManager.settings.downloadLocation);
|
||||
List<Chapter> newChapters = taskManager.GetNewChaptersList(connector, publication, language);
|
||||
|
||||
connector.CopyCoverFromCacheToDownloadLocation(publication, taskManager.settings);
|
||||
|
||||
publication.SaveSeriesInfoJson(connector.downloadLocation);
|
||||
|
||||
foreach (Chapter newChapter in newChapters)
|
||||
{
|
||||
DownloadChapterTask newTask = new (this.connectorName, publication, newChapter, this.language, this);
|
||||
this.childTasks.Add(newTask);
|
||||
newTask.state = ExecutionState.Enqueued;
|
||||
taskManager.AddTask(newTask);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override TrangaTask Clone()
|
||||
{
|
||||
return new MonitorPublicationTask(this.connectorName, this.publication, this.reoccurrence,
|
||||
this.language);
|
||||
}
|
||||
|
||||
protected override double GetProgress()
|
||||
{
|
||||
if (this.childTasks.Count > 0)
|
||||
return this.childTasks.Sum(ct => ct.progress) / childTasks.Count;
|
||||
return 1;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{base.ToString()}, {connectorName}, {publication.sortName} {publication.internalId}";
|
||||
}
|
||||
}
|
@ -4,16 +4,26 @@ namespace Tranga.TrangaTasks;
|
||||
|
||||
public class UpdateLibrariesTask : TrangaTask
|
||||
{
|
||||
public UpdateLibrariesTask(Task task, TimeSpan reoccurrence) : base(task, reoccurrence)
|
||||
public UpdateLibrariesTask(TimeSpan reoccurrence) : base(Task.UpdateLibraries, reoccurrence)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void ExecuteTask(TaskManager taskManager, Logger? logger, CancellationToken? cancellationToken = null)
|
||||
protected override bool ExecuteTask(TaskManager taskManager, Logger? logger, CancellationToken? cancellationToken = null)
|
||||
{
|
||||
if (cancellationToken?.IsCancellationRequested??false)
|
||||
return;
|
||||
return false;
|
||||
foreach(LibraryManager lm in taskManager.settings.libraryManagers)
|
||||
lm.UpdateLibrary();
|
||||
IncrementProgress(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
public override TrangaTask Clone()
|
||||
{
|
||||
return new UpdateLibrariesTask(this.reoccurrence);
|
||||
}
|
||||
|
||||
protected override double GetProgress()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user