Attach Entities to Jobs

This commit is contained in:
2025-05-15 15:13:53 +02:00
parent 694b88d200
commit 475a29b10d
23 changed files with 132 additions and 57 deletions

View File

@ -0,0 +1,18 @@
using API.Schema.LibraryConnectors;
using Microsoft.EntityFrameworkCore;
namespace API.Schema.Contexts;
public class LibraryContext(DbContextOptions<LibraryContext> options) : DbContext(options)
{
public DbSet<LibraryConnector> LibraryConnectors { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//LibraryConnector Types
modelBuilder.Entity<LibraryConnector>()
.HasDiscriminator(l => l.LibraryType)
.HasValue<Komga>(LibraryType.Komga)
.HasValue<Kavita>(LibraryType.Kavita);
}
}

View File

@ -0,0 +1,10 @@
using API.Schema.NotificationConnectors;
using Microsoft.EntityFrameworkCore;
namespace API.Schema.Contexts;
public class NotificationsContext(DbContextOptions<NotificationsContext> options) : DbContext(options)
{
public DbSet<NotificationConnector> NotificationConnectors { get; set; }
public DbSet<Notification> Notifications { get; set; }
}

View File

@ -1,10 +1,9 @@
using API.Schema.Jobs;
using API.Schema.LibraryConnectors;
using API.Schema.MangaConnectors;
using API.Schema.NotificationConnectors;
using Microsoft.EntityFrameworkCore;
namespace API.Schema;
namespace API.Schema.Contexts;
public class PgsqlContext(DbContextOptions<PgsqlContext> options) : DbContext(options)
{
@ -15,9 +14,6 @@ public class PgsqlContext(DbContextOptions<PgsqlContext> options) : DbContext(op
public DbSet<Chapter> Chapters { get; set; }
public DbSet<Author> Authors { get; set; }
public DbSet<MangaTag> Tags { get; set; }
public DbSet<LibraryConnector> LibraryConnectors { get; set; }
public DbSet<NotificationConnector> NotificationConnectors { get; set; }
public DbSet<Notification> Notifications { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
@ -109,7 +105,7 @@ public class PgsqlContext(DbContextOptions<PgsqlContext> options) : DbContext(op
.HasMany<Job>(root => root.DependsOnJobs)
.WithMany();
modelBuilder.Entity<Job>()
.Navigation(root => root.DependsOnJobs)
.Navigation(j => j.DependsOnJobs)
.AutoInclude(false);
//MangaConnector Types
@ -138,14 +134,23 @@ public class PgsqlContext(DbContextOptions<PgsqlContext> options) : DbContext(op
modelBuilder.Entity<Chapter>()
.Navigation(c => c.ParentManga)
.AutoInclude();
modelBuilder.Entity<Manga>()
.Navigation(m => m.Chapters)
.AutoInclude();
//Manga owns MangaAltTitles
modelBuilder.Entity<Manga>()
.OwnsMany<MangaAltTitle>(m => m.AltTitles)
.WithOwner();
modelBuilder.Entity<Manga>()
.Navigation(m => m.AltTitles)
.AutoInclude();
//Manga owns Links
modelBuilder.Entity<Manga>()
.OwnsMany<Link>(m => m.Links)
.WithOwner();
modelBuilder.Entity<Manga>()
.Navigation(m => m.Links)
.AutoInclude();
//Manga has many Tags associated with many Manga
modelBuilder.Entity<Manga>()
.HasMany<MangaTag>(m => m.MangaTags)
@ -155,6 +160,9 @@ public class PgsqlContext(DbContextOptions<PgsqlContext> options) : DbContext(op
r => r.HasOne(typeof(Manga)).WithMany().HasForeignKey("MangaIds").HasPrincipalKey(nameof(Manga.MangaId)),
j => j.HasKey("MangaTagIds", "MangaIds")
);
modelBuilder.Entity<Manga>()
.Navigation(m => m.MangaTags)
.AutoInclude();
//Manga has many Authors associated with many Manga
modelBuilder.Entity<Manga>()
.HasMany<Author>(m => m.Authors)
@ -164,6 +172,9 @@ public class PgsqlContext(DbContextOptions<PgsqlContext> options) : DbContext(op
r => r.HasOne(typeof(Manga)).WithMany().HasForeignKey("MangaIds").HasPrincipalKey(nameof(Manga.MangaId)),
j => j.HasKey("AuthorIds", "MangaIds")
);
modelBuilder.Entity<Manga>()
.Navigation(m => m.Authors)
.AutoInclude();
//LocalLibrary has many Mangas
modelBuilder.Entity<LocalLibrary>()
@ -171,11 +182,8 @@ public class PgsqlContext(DbContextOptions<PgsqlContext> options) : DbContext(op
.WithOne(m => m.Library)
.HasForeignKey(m => m.LibraryId)
.OnDelete(DeleteBehavior.SetNull);
//LibraryConnector Types
modelBuilder.Entity<LibraryConnector>()
.HasDiscriminator(l => l.LibraryType)
.HasValue<Komga>(LibraryType.Komga)
.HasValue<Kavita>(LibraryType.Kavita);
modelBuilder.Entity<Manga>()
.Navigation(m => m.Library)
.AutoInclude();
}
}

View File

@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations;
using API.Schema.Contexts;
using Newtonsoft.Json;
namespace API.Schema.Jobs;
@ -26,6 +27,7 @@ public class DownloadAvailableChaptersJob : Job
protected override IEnumerable<Job> RunInternal(PgsqlContext context)
{
context.Attach(Manga);
return Manga.Chapters.Select(chapter => new DownloadSingleChapterJob(chapter, this));
}
}

View File

@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations;
using API.Schema.Contexts;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
@ -27,6 +28,7 @@ public class DownloadMangaCoverJob : Job
protected override IEnumerable<Job> RunInternal(PgsqlContext context)
{
context.Attach(Manga);
try
{
Manga.CoverFileNameInCache = Manga.MangaConnector.SaveCoverImageToCache(Manga);

View File

@ -2,6 +2,7 @@
using System.IO.Compression;
using System.Runtime.InteropServices;
using API.MangaDownloadClients;
using API.Schema.Contexts;
using Newtonsoft.Json;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Jpeg;
@ -35,6 +36,7 @@ public class DownloadSingleChapterJob : Job
protected override IEnumerable<Job> RunInternal(PgsqlContext context)
{
context.Attach(Chapter);
string[] imageUrls = Chapter.ParentManga.MangaConnector.GetChapterImageUrls(Chapter);
if (imageUrls.Length < 1)
{

View File

@ -1,5 +1,6 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using API.Schema.Contexts;
using log4net;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
@ -62,14 +63,16 @@ public abstract class Job
{
Log.Debug($"Running job {JobId}");
using IServiceScope scope = serviceProvider.CreateScope();
PgsqlContext context = scope.ServiceProvider.GetRequiredService<PgsqlContext>();
try
{
PgsqlContext context = scope.ServiceProvider.GetRequiredService<PgsqlContext>();
context.Attach(this);
this.state = JobState.Running;
context.SaveChanges();
Job[] newJobs = RunInternal(context).ToArray();
this.state = JobState.Completed;
context.SaveChanges();
context.Jobs.AddRange(newJobs);
context.SaveChanges();
Log.Info($"Job {JobId} completed. Generated {newJobs.Length} new jobs.");

View File

@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations;
using API.Schema.Contexts;
namespace API.Schema.Jobs;

View File

@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations;
using API.Schema.Contexts;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
@ -32,6 +33,7 @@ public class MoveMangaLibraryJob : Job
protected override IEnumerable<Job> RunInternal(PgsqlContext context)
{
context.Attach(Manga);
Dictionary<Chapter, string> oldPath = Manga.Chapters.ToDictionary(c => c, c => c.FullArchiveFilePath);
Manga.Library = ToLibrary;
try

View File

@ -1,5 +1,5 @@
using System.ComponentModel.DataAnnotations;
using API.Schema.MangaConnectors;
using API.Schema.Contexts;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
@ -31,6 +31,7 @@ public class RetrieveChaptersJob : Job
protected override IEnumerable<Job> RunInternal(PgsqlContext context)
{
context.Attach(Manga);
// This gets all chapters that are not downloaded
Chapter[] allChapters = Manga.MangaConnector.GetChapters(Manga, Language);
Chapter[] newChapters = allChapters.Where(chapter => context.Chapters.Contains(chapter) == false).ToArray();

View File

@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations;
using API.Schema.Contexts;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
@ -27,6 +28,7 @@ public class UpdateFilesDownloadedJob : Job
protected override IEnumerable<Job> RunInternal(PgsqlContext context)
{
context.Attach(Manga);
foreach (Chapter chapter in Manga.Chapters)
chapter.Downloaded = chapter.CheckDownloaded();

View File

@ -1,4 +1,6 @@
namespace API.Schema.MangaConnectors;
using API.Schema.Contexts;
namespace API.Schema.MangaConnectors;
public class Global : MangaConnector
{