diff --git a/API/Tranga.cs b/API/Tranga.cs index a5f7e8d..6ef394b 100644 --- a/API/Tranga.cs +++ b/API/Tranga.cs @@ -6,7 +6,6 @@ using API.Schema.NotificationConnectors; using log4net; using log4net.Config; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.ChangeTracking; namespace API; @@ -104,44 +103,34 @@ public static class Tranga } IServiceProvider serviceProvider = (IServiceProvider)serviceProviderObj; using IServiceScope scope = serviceProvider.CreateScope(); - PgsqlContext context = scope.ServiceProvider.GetRequiredService(); while (true) { Log.Debug("Starting Job-Cycle..."); DateTime cycleStart = DateTime.UtcNow; + PgsqlContext cycleContext = scope.ServiceProvider.GetRequiredService(); Log.Debug("Loading Jobs..."); DateTime loadStart = DateTime.UtcNow; - context.Jobs.Load(); Log.Debug($"Jobs Loaded! (took {DateTime.UtcNow.Subtract(loadStart).TotalMilliseconds}ms)"); //Update finished Jobs to new states - List completedJobs = context.Jobs.Local.Where(j => j.state == JobState.Completed).ToList(); + IQueryable completedJobs = cycleContext.Jobs.Where(j => j.state == JobState.Completed); foreach (Job completedJob in completedJobs) if (completedJob.RecurrenceMs <= 0) - context.Jobs.Remove(completedJob); - else { - completedJob.state = JobState.CompletedWaiting; - completedJob.LastExecution = DateTime.UtcNow; + cycleContext.Jobs.Remove(completedJob); } - List failedJobs = context.Jobs.Local.Where(j => j.state == JobState.Failed).ToList(); - foreach (Job failedJob in failedJobs) - { - failedJob.Enabled = false; - failedJob.LastExecution = DateTime.UtcNow; - } //Retrieve waiting and due Jobs - List runningJobs = context.Jobs.Local.Where(j => j.state == JobState.Running).ToList(); + IQueryable runningJobs = cycleContext.Jobs.Where(j => j.state == JobState.Running); DateTime filterStart = DateTime.UtcNow; Log.Debug("Filtering Jobs..."); List busyConnectors = GetBusyConnectors(runningJobs); - List waitingJobs = GetWaitingJobs(context.Jobs.Local.ToList()); + IQueryable waitingJobs = cycleContext.Jobs.Where(j => j.state == JobState.CompletedWaiting || j.state == JobState.FirstExecution); List dueJobs = FilterDueJobs(waitingJobs); List jobsWithoutBusyConnectors = FilterJobWithBusyConnectors(dueJobs, busyConnectors); - List jobsWithoutMissingDependencies = FilterJobDependencies(context, jobsWithoutBusyConnectors); + List jobsWithoutMissingDependencies = FilterJobDependencies(jobsWithoutBusyConnectors); List jobsWithoutDownloading = jobsWithoutMissingDependencies @@ -151,6 +140,7 @@ public static class Tranga List firstChapterPerConnector = jobsWithoutMissingDependencies .Where(j => j.JobType == JobType.DownloadSingleChapterJob) + .AsEnumerable() .OrderBy(j => { DownloadSingleChapterJob dscj = (DownloadSingleChapterJob)j; @@ -174,15 +164,16 @@ public static class Tranga { using IServiceScope jobScope = serviceProvider.CreateScope(); PgsqlContext jobContext = jobScope.ServiceProvider.GetRequiredService(); - job.Run(jobContext); + jobContext.Jobs.Find(job.JobId)?.Run(jobContext); //FIND the job IN THE NEW CONTEXT!!!!!!! SO WE DON'T GET TRACKING PROBLEMS AND AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA }); RunningJobs.Add(t, job); t.Start(); } - Log.Debug($"Jobs Completed: {completedJobs.Count} Failed: {failedJobs.Count} Running: {runningJobs.Count}\n" + - $"Waiting: {waitingJobs.Count}\n" + - $"\tof which Due: {dueJobs.Count}\n" + - $"\t\tof which Started: {jobsWithoutMissingDependencies.Count}"); + Log.Debug($"Jobs Completed: {completedJobs.Count()} Running: {runningJobs.Count()}\n" + + $"Waiting: {waitingJobs.Count()}\n" + + $"\tof which Due: {dueJobs.Count()}\n" + + $"\t\tof which can be started: {jobsWithoutMissingDependencies.Count()}\n" + + $"\t\t\tof which started: {startJobs.Count()}"); (Thread, Job)[] removeFromThreadsList = RunningJobs.Where(t => !t.Key.IsAlive) .Select(t => (t.Key, t.Value)).ToArray(); @@ -194,7 +185,7 @@ public static class Tranga try { - context.SaveChanges(); + cycleContext.SaveChanges(); } catch (DbUpdateException e) { @@ -205,7 +196,7 @@ public static class Tranga } } - private static List GetBusyConnectors(List runningJobs) + private static List GetBusyConnectors(IQueryable runningJobs) { HashSet busyConnectors = new(); foreach (Job runningJob in runningJobs) @@ -215,40 +206,25 @@ public static class Tranga } return busyConnectors.ToList(); } - - private static List GetWaitingJobs(List jobs) => - jobs - .Where(j => - j.Enabled && - (j.state == JobState.FirstExecution || j.state == JobState.CompletedWaiting)) - .ToList(); - private static List FilterDueJobs(List jobs) => - jobs + private static List FilterDueJobs(IQueryable jobs) => + jobs.ToList() .Where(j => j.NextExecution < DateTime.UtcNow) .ToList(); - private static List FilterJobDependencies(PgsqlContext context, List jobs) => + private static List FilterJobDependencies(List jobs) => jobs - .Where(j => - { - Log.Debug($"Loading Job Preconditions {j}..."); - context.Entry(j).Collection(j => j.DependsOnJobs).Load(); - Log.Debug($"Loaded Job Preconditions {j}!"); - return j.DependenciesFulfilled; - }) + .Where(job => job.DependsOnJobs.All(j => j.IsCompleted)) .ToList(); private static List FilterJobWithBusyConnectors(List jobs, List busyConnectors) => - jobs - .Where(j => + jobs.Where(j => { //Filter jobs with busy connectors if (GetJobConnector(j) is { } mangaConnector) return busyConnectors.Contains(mangaConnector) == false; return true; - }) - .ToList(); + }).ToList(); private static MangaConnector? GetJobConnector(Job job) {