Lazy Load Jobs.DependsOnJobs, Manga.Chapters

This commit is contained in:
Glax 2025-05-16 21:53:59 +02:00
parent 6258e07f20
commit 225b7f02ad
7 changed files with 45 additions and 42 deletions

View File

@ -118,7 +118,8 @@ public class PgsqlContext(DbContextOptions<PgsqlContext> options) : DbContext(op
.WithMany();
modelBuilder.Entity<Job>()
.Navigation(j => j.DependsOnJobs)
.AutoInclude(false);
.AutoInclude(false)
.EnableLazyLoading();
//MangaConnector Types
modelBuilder.Entity<MangaConnector>()
@ -149,7 +150,8 @@ public class PgsqlContext(DbContextOptions<PgsqlContext> options) : DbContext(op
.AutoInclude();
modelBuilder.Entity<Manga>()
.Navigation(m => m.Chapters)
.AutoInclude(false);
.AutoInclude(false)
.EnableLazyLoading();
//Manga owns MangaAltTitles
modelBuilder.Entity<Manga>()
.OwnsMany<MangaAltTitle>(m => m.AltTitles)

View File

@ -36,7 +36,6 @@ public class DownloadAvailableChaptersJob : Job
protected override IEnumerable<Job> RunInternal(PgsqlContext context)
{
context.Entry(Manga).Collection<Chapter>(m => m.Chapters).Load();
return Manga.Chapters.Select(chapter => new DownloadSingleChapterJob(chapter, this));
}
}

View File

@ -17,7 +17,12 @@ public abstract class Job
[StringLength(64)] public string? ParentJobId { get; init; }
[JsonIgnore] public Job? ParentJob { get; init; }
[JsonIgnore] public ICollection<Job> DependsOnJobs { get; init; }
private ICollection<Job> _dependsOnJobs = null!;
[JsonIgnore] public ICollection<Job> DependsOnJobs
{
get => LazyLoader.Load(this, ref _dependsOnJobs);
init => _dependsOnJobs = value;
}
[Required] public JobType JobType { get; init; }
@ -68,9 +73,6 @@ public abstract class Job
DateTime jobStart = DateTime.UtcNow;
Job[]? ret = null;
try
{
using IServiceScope scope = serviceProvider.CreateScope();
PgsqlContext context = scope.ServiceProvider.GetRequiredService<PgsqlContext>();
try
@ -82,28 +84,21 @@ public abstract class Job
this.state = JobState.Completed;
context.Jobs.AddRange(ret);
Log.Info($"Job {JobId} completed. Generated {ret.Length} new jobs.");
context.SaveChanges();
}
catch (Exception e)
{
if (e is not DbUpdateException dbEx)
if (e is not DbUpdateException)
{
this.state = JobState.Failed;
Log.Error($"Failed to run job {JobId}", e);
context.SaveChanges();
}
else
{
throw;
}
}
finally
{
context.SaveChanges();
}
}
catch (DbUpdateException e)
{
Log.Error($"Failed to update Database {JobId}", e);
}
}
Log.Info($"Finished Job {JobId}! (took {DateTime.UtcNow.Subtract(jobStart).TotalMilliseconds}ms)");
return ret ?? [];

View File

@ -42,8 +42,6 @@ public class MoveMangaLibraryJob : Job
protected override IEnumerable<Job> RunInternal(PgsqlContext context)
{
context.Attach(Manga);
context.Entry(Manga).Collection<Chapter>(m => m.Chapters).Load();
Dictionary<Chapter, string> oldPath = Manga.Chapters.ToDictionary(c => c, c => c.FullArchiveFilePath);
Manga.Library = ToLibrary;
try

View File

@ -40,7 +40,6 @@ public class RetrieveChaptersJob : Job
protected override IEnumerable<Job> RunInternal(PgsqlContext context)
{
context.Entry(Manga).Collection<Chapter>(m => m.Chapters).Load();
// This gets all chapters that are not downloaded
Chapter[] allChapters = Manga.MangaConnector.GetChapters(Manga, Language);
Chapter[] newChapters = allChapters.Where(chapter => Manga.Chapters.Contains(chapter) == false).ToArray();

View File

@ -36,7 +36,6 @@ public class UpdateChaptersDownloadedJob : Job
protected override IEnumerable<Job> RunInternal(PgsqlContext context)
{
context.Entry(Manga).Collection<Chapter>(m => m.Chapters).Load();
return Manga.Chapters.Select(c => new UpdateSingleChapterDownloadedJob(c, this));
}
}

View File

@ -4,6 +4,7 @@ using System.Runtime.InteropServices;
using System.Text;
using API.Schema.MangaConnectors;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Newtonsoft.Json;
using static System.IO.UnixFileMode;
@ -46,7 +47,15 @@ public class Manga
[NotMapped]
public string? FullDirectoryPath => Library is not null ? Path.Join(Library.BasePath, DirectoryName) : null;
[JsonIgnore] public ICollection<Chapter> Chapters { get; internal set; } = [];
[NotMapped] public ICollection<string> ChapterIds => Chapters.Select(c => c.ChapterId).ToList();
private readonly ILazyLoader _lazyLoader = null!;
private ICollection<Chapter> _chapters = null!;
[JsonIgnore]
public ICollection<Chapter> Chapters
{
get => _lazyLoader.Load(this, ref _chapters);
init => _chapters = value;
}
public Manga(string idOnConnector, string name, string description, string websiteUrl, string coverUrl, MangaReleaseStatus releaseStatus,
MangaConnector mangaConnector, ICollection<Author> authors, ICollection<MangaTag> mangaTags, ICollection<Link> links, ICollection<MangaAltTitle> altTitles,
@ -71,14 +80,16 @@ public class Manga
this.DirectoryName = CleanDirectoryName(name);
this.Year = year;
this.OriginalLanguage = originalLanguage;
this.Chapters = [];
}
/// <summary>
/// EF ONLY!!!
/// </summary>
public Manga(string mangaId, string idOnConnectorSite, string name, string description, string websiteUrl, string coverUrl, MangaReleaseStatus releaseStatus,
public Manga(ILazyLoader lazyLoader, string mangaId, string idOnConnectorSite, string name, string description, string websiteUrl, string coverUrl, MangaReleaseStatus releaseStatus,
string mangaConnectorName, string directoryName, float ignoreChaptersBefore, string? libraryId, uint? year, string? originalLanguage)
{
this._lazyLoader = lazyLoader;
this.MangaId = mangaId;
this.IdOnConnectorSite = idOnConnectorSite;
this.Name = name;