From a490e233d716bcd816fd4170ec1153abe147fffa Mon Sep 17 00:00:00 2001
From: Glax <johanna@bernloehr.eu>
Date: Wed, 2 Apr 2025 02:16:55 +0200
Subject: [PATCH] Jobs remove redundant fields (context tracking)

---
 .../20250402001438_dev-010425-4.Designer.cs   | 762 ++++++++++++++++++
 API/Migrations/20250402001438_dev-010425-4.cs | 123 +++
 API/Migrations/PgsqlContextModelSnapshot.cs   |  65 --
 .../Jobs/DownloadAvailableChaptersJob.cs      |   4 -
 API/Schema/Jobs/DownloadMangaCoverJob.cs      |   5 +-
 API/Schema/Jobs/DownloadSingleChapterJob.cs   |  12 +-
 API/Schema/Jobs/RetrieveChaptersJob.cs        |   6 +-
 API/Schema/Jobs/UpdateFilesDownloadedJob.cs   |   3 -
 API/Schema/PgsqlContext.cs                    |   6 -
 API/Tranga.cs                                 |  23 +-
 10 files changed, 906 insertions(+), 103 deletions(-)
 create mode 100644 API/Migrations/20250402001438_dev-010425-4.Designer.cs
 create mode 100644 API/Migrations/20250402001438_dev-010425-4.cs

diff --git a/API/Migrations/20250402001438_dev-010425-4.Designer.cs b/API/Migrations/20250402001438_dev-010425-4.Designer.cs
new file mode 100644
index 0000000..88957a4
--- /dev/null
+++ b/API/Migrations/20250402001438_dev-010425-4.Designer.cs
@@ -0,0 +1,762 @@
+// <auto-generated />
+using System;
+using System.Collections.Generic;
+using API.Schema;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace API.Migrations
+{
+    [DbContext(typeof(PgsqlContext))]
+    [Migration("20250402001438_dev-010425-4")]
+    partial class dev0104254
+    {
+        /// <inheritdoc />
+        protected override void BuildTargetModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .HasAnnotation("ProductVersion", "9.0.3")
+                .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+            NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "hstore");
+            NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+            modelBuilder.Entity("API.Schema.Author", b =>
+                {
+                    b.Property<string>("AuthorId")
+                        .HasMaxLength(64)
+                        .HasColumnType("character varying(64)");
+
+                    b.Property<string>("AuthorName")
+                        .IsRequired()
+                        .HasMaxLength(128)
+                        .HasColumnType("character varying(128)");
+
+                    b.HasKey("AuthorId");
+
+                    b.ToTable("Authors");
+                });
+
+            modelBuilder.Entity("API.Schema.Chapter", b =>
+                {
+                    b.Property<string>("ChapterId")
+                        .HasMaxLength(64)
+                        .HasColumnType("character varying(64)");
+
+                    b.Property<string>("ChapterNumber")
+                        .IsRequired()
+                        .HasMaxLength(10)
+                        .HasColumnType("character varying(10)");
+
+                    b.Property<bool>("Downloaded")
+                        .HasColumnType("boolean");
+
+                    b.Property<string>("FileName")
+                        .IsRequired()
+                        .HasMaxLength(256)
+                        .HasColumnType("character varying(256)");
+
+                    b.Property<string>("ParentMangaId")
+                        .IsRequired()
+                        .HasMaxLength(64)
+                        .HasColumnType("character varying(64)");
+
+                    b.Property<string>("Title")
+                        .HasMaxLength(256)
+                        .HasColumnType("character varying(256)");
+
+                    b.Property<string>("Url")
+                        .IsRequired()
+                        .HasMaxLength(2048)
+                        .HasColumnType("character varying(2048)");
+
+                    b.Property<int?>("VolumeNumber")
+                        .HasColumnType("integer");
+
+                    b.HasKey("ChapterId");
+
+                    b.HasIndex("ParentMangaId");
+
+                    b.ToTable("Chapters");
+                });
+
+            modelBuilder.Entity("API.Schema.Jobs.Job", b =>
+                {
+                    b.Property<string>("JobId")
+                        .HasMaxLength(64)
+                        .HasColumnType("character varying(64)");
+
+                    b.PrimitiveCollection<string[]>("DependsOnJobsIds")
+                        .HasMaxLength(64)
+                        .HasColumnType("text[]");
+
+                    b.Property<bool>("Enabled")
+                        .HasColumnType("boolean");
+
+                    b.Property<byte>("JobType")
+                        .HasColumnType("smallint");
+
+                    b.Property<DateTime>("LastExecution")
+                        .HasColumnType("timestamp with time zone");
+
+                    b.Property<string>("ParentJobId")
+                        .HasMaxLength(64)
+                        .HasColumnType("character varying(64)");
+
+                    b.Property<decimal>("RecurrenceMs")
+                        .HasColumnType("numeric(20,0)");
+
+                    b.Property<byte>("state")
+                        .HasColumnType("smallint");
+
+                    b.HasKey("JobId");
+
+                    b.HasIndex("ParentJobId");
+
+                    b.ToTable("Jobs");
+
+                    b.HasDiscriminator<byte>("JobType");
+
+                    b.UseTphMappingStrategy();
+                });
+
+            modelBuilder.Entity("API.Schema.LibraryConnectors.LibraryConnector", b =>
+                {
+                    b.Property<string>("LibraryConnectorId")
+                        .HasMaxLength(64)
+                        .HasColumnType("character varying(64)");
+
+                    b.Property<string>("Auth")
+                        .IsRequired()
+                        .HasMaxLength(256)
+                        .HasColumnType("character varying(256)");
+
+                    b.Property<string>("BaseUrl")
+                        .IsRequired()
+                        .HasMaxLength(256)
+                        .HasColumnType("character varying(256)");
+
+                    b.Property<byte>("LibraryType")
+                        .HasColumnType("smallint");
+
+                    b.HasKey("LibraryConnectorId");
+
+                    b.ToTable("LibraryConnectors");
+
+                    b.HasDiscriminator<byte>("LibraryType");
+
+                    b.UseTphMappingStrategy();
+                });
+
+            modelBuilder.Entity("API.Schema.Link", b =>
+                {
+                    b.Property<string>("LinkId")
+                        .HasMaxLength(64)
+                        .HasColumnType("character varying(64)");
+
+                    b.Property<string>("LinkProvider")
+                        .IsRequired()
+                        .HasMaxLength(64)
+                        .HasColumnType("character varying(64)");
+
+                    b.Property<string>("LinkUrl")
+                        .IsRequired()
+                        .HasMaxLength(2048)
+                        .HasColumnType("character varying(2048)");
+
+                    b.Property<string>("MangaId")
+                        .HasColumnType("character varying(64)");
+
+                    b.HasKey("LinkId");
+
+                    b.HasIndex("MangaId");
+
+                    b.ToTable("Links");
+                });
+
+            modelBuilder.Entity("API.Schema.LocalLibrary", b =>
+                {
+                    b.Property<string>("LocalLibraryId")
+                        .HasMaxLength(64)
+                        .HasColumnType("character varying(64)");
+
+                    b.Property<string>("BasePath")
+                        .IsRequired()
+                        .HasMaxLength(256)
+                        .HasColumnType("character varying(256)");
+
+                    b.Property<string>("LibraryName")
+                        .IsRequired()
+                        .HasMaxLength(512)
+                        .HasColumnType("character varying(512)");
+
+                    b.HasKey("LocalLibraryId");
+
+                    b.ToTable("LocalLibraries");
+                });
+
+            modelBuilder.Entity("API.Schema.Manga", b =>
+                {
+                    b.Property<string>("MangaId")
+                        .HasMaxLength(64)
+                        .HasColumnType("character varying(64)");
+
+                    b.Property<string>("CoverFileNameInCache")
+                        .HasColumnType("text");
+
+                    b.Property<string>("CoverUrl")
+                        .IsRequired()
+                        .HasColumnType("text");
+
+                    b.Property<string>("Description")
+                        .IsRequired()
+                        .HasColumnType("text");
+
+                    b.Property<string>("DirectoryName")
+                        .IsRequired()
+                        .HasMaxLength(1024)
+                        .HasColumnType("character varying(1024)");
+
+                    b.Property<string>("IdOnConnectorSite")
+                        .IsRequired()
+                        .HasMaxLength(256)
+                        .HasColumnType("character varying(256)");
+
+                    b.Property<float>("IgnoreChapterBefore")
+                        .HasColumnType("real");
+
+                    b.Property<string>("LibraryLocalLibraryId")
+                        .HasColumnType("character varying(64)");
+
+                    b.Property<string>("MangaConnectorId")
+                        .IsRequired()
+                        .HasMaxLength(64)
+                        .HasColumnType("character varying(64)");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasMaxLength(512)
+                        .HasColumnType("character varying(512)");
+
+                    b.Property<string>("OriginalLanguage")
+                        .HasMaxLength(8)
+                        .HasColumnType("character varying(8)");
+
+                    b.Property<byte>("ReleaseStatus")
+                        .HasColumnType("smallint");
+
+                    b.Property<string>("WebsiteUrl")
+                        .IsRequired()
+                        .HasMaxLength(512)
+                        .HasColumnType("character varying(512)");
+
+                    b.Property<long>("Year")
+                        .HasColumnType("bigint");
+
+                    b.HasKey("MangaId");
+
+                    b.HasIndex("LibraryLocalLibraryId");
+
+                    b.HasIndex("MangaConnectorId");
+
+                    b.ToTable("Mangas");
+                });
+
+            modelBuilder.Entity("API.Schema.MangaAltTitle", b =>
+                {
+                    b.Property<string>("AltTitleId")
+                        .HasMaxLength(64)
+                        .HasColumnType("character varying(64)");
+
+                    b.Property<string>("Language")
+                        .IsRequired()
+                        .HasMaxLength(8)
+                        .HasColumnType("character varying(8)");
+
+                    b.Property<string>("MangaId")
+                        .HasColumnType("character varying(64)");
+
+                    b.Property<string>("Title")
+                        .IsRequired()
+                        .HasMaxLength(256)
+                        .HasColumnType("character varying(256)");
+
+                    b.HasKey("AltTitleId");
+
+                    b.HasIndex("MangaId");
+
+                    b.ToTable("AltTitles");
+                });
+
+            modelBuilder.Entity("API.Schema.MangaConnectors.MangaConnector", b =>
+                {
+                    b.Property<string>("Name")
+                        .HasMaxLength(32)
+                        .HasColumnType("character varying(32)");
+
+                    b.PrimitiveCollection<string[]>("BaseUris")
+                        .IsRequired()
+                        .HasMaxLength(256)
+                        .HasColumnType("text[]");
+
+                    b.Property<bool>("Enabled")
+                        .HasColumnType("boolean");
+
+                    b.Property<string>("IconUrl")
+                        .IsRequired()
+                        .HasMaxLength(2048)
+                        .HasColumnType("character varying(2048)");
+
+                    b.PrimitiveCollection<string[]>("SupportedLanguages")
+                        .IsRequired()
+                        .HasMaxLength(8)
+                        .HasColumnType("text[]");
+
+                    b.HasKey("Name");
+
+                    b.ToTable("MangaConnectors");
+
+                    b.HasDiscriminator<string>("Name").HasValue("MangaConnector");
+
+                    b.UseTphMappingStrategy();
+                });
+
+            modelBuilder.Entity("API.Schema.MangaTag", b =>
+                {
+                    b.Property<string>("Tag")
+                        .HasMaxLength(64)
+                        .HasColumnType("character varying(64)");
+
+                    b.HasKey("Tag");
+
+                    b.ToTable("Tags");
+                });
+
+            modelBuilder.Entity("API.Schema.Notification", b =>
+                {
+                    b.Property<string>("NotificationId")
+                        .HasMaxLength(64)
+                        .HasColumnType("character varying(64)");
+
+                    b.Property<DateTime>("Date")
+                        .HasColumnType("timestamp with time zone");
+
+                    b.Property<string>("Message")
+                        .IsRequired()
+                        .HasMaxLength(512)
+                        .HasColumnType("character varying(512)");
+
+                    b.Property<string>("Title")
+                        .IsRequired()
+                        .HasMaxLength(128)
+                        .HasColumnType("character varying(128)");
+
+                    b.Property<byte>("Urgency")
+                        .HasColumnType("smallint");
+
+                    b.HasKey("NotificationId");
+
+                    b.ToTable("Notifications");
+                });
+
+            modelBuilder.Entity("API.Schema.NotificationConnectors.NotificationConnector", b =>
+                {
+                    b.Property<string>("Name")
+                        .HasMaxLength(64)
+                        .HasColumnType("character varying(64)");
+
+                    b.Property<string>("Body")
+                        .IsRequired()
+                        .HasMaxLength(4096)
+                        .HasColumnType("character varying(4096)");
+
+                    b.Property<Dictionary<string, string>>("Headers")
+                        .IsRequired()
+                        .HasColumnType("hstore");
+
+                    b.Property<string>("HttpMethod")
+                        .IsRequired()
+                        .HasMaxLength(8)
+                        .HasColumnType("character varying(8)");
+
+                    b.Property<string>("Url")
+                        .IsRequired()
+                        .HasMaxLength(2048)
+                        .HasColumnType("character varying(2048)");
+
+                    b.HasKey("Name");
+
+                    b.ToTable("NotificationConnectors");
+                });
+
+            modelBuilder.Entity("AuthorManga", b =>
+                {
+                    b.Property<string>("AuthorsAuthorId")
+                        .HasColumnType("character varying(64)");
+
+                    b.Property<string>("MangaId")
+                        .HasColumnType("character varying(64)");
+
+                    b.HasKey("AuthorsAuthorId", "MangaId");
+
+                    b.HasIndex("MangaId");
+
+                    b.ToTable("AuthorManga");
+                });
+
+            modelBuilder.Entity("JobJob", b =>
+                {
+                    b.Property<string>("DependsOnJobsJobId")
+                        .HasColumnType("character varying(64)");
+
+                    b.Property<string>("JobId")
+                        .HasColumnType("character varying(64)");
+
+                    b.HasKey("DependsOnJobsJobId", "JobId");
+
+                    b.HasIndex("JobId");
+
+                    b.ToTable("JobJob");
+                });
+
+            modelBuilder.Entity("MangaMangaTag", b =>
+                {
+                    b.Property<string>("MangaId")
+                        .HasColumnType("character varying(64)");
+
+                    b.Property<string>("MangaTagsTag")
+                        .HasColumnType("character varying(64)");
+
+                    b.HasKey("MangaId", "MangaTagsTag");
+
+                    b.HasIndex("MangaTagsTag");
+
+                    b.ToTable("MangaMangaTag");
+                });
+
+            modelBuilder.Entity("API.Schema.Jobs.DownloadAvailableChaptersJob", b =>
+                {
+                    b.HasBaseType("API.Schema.Jobs.Job");
+
+                    b.Property<string>("MangaId")
+                        .IsRequired()
+                        .HasMaxLength(64)
+                        .HasColumnType("character varying(64)");
+
+                    b.ToTable("Jobs", t =>
+                        {
+                            t.Property("MangaId")
+                                .HasColumnName("DownloadAvailableChaptersJob_MangaId");
+                        });
+
+                    b.HasDiscriminator().HasValue((byte)1);
+                });
+
+            modelBuilder.Entity("API.Schema.Jobs.DownloadMangaCoverJob", b =>
+                {
+                    b.HasBaseType("API.Schema.Jobs.Job");
+
+                    b.Property<string>("MangaId")
+                        .IsRequired()
+                        .HasMaxLength(64)
+                        .HasColumnType("character varying(64)");
+
+                    b.HasDiscriminator().HasValue((byte)4);
+                });
+
+            modelBuilder.Entity("API.Schema.Jobs.DownloadSingleChapterJob", b =>
+                {
+                    b.HasBaseType("API.Schema.Jobs.Job");
+
+                    b.Property<string>("ChapterId")
+                        .IsRequired()
+                        .HasMaxLength(64)
+                        .HasColumnType("character varying(64)");
+
+                    b.HasDiscriminator().HasValue((byte)0);
+                });
+
+            modelBuilder.Entity("API.Schema.Jobs.MoveFileOrFolderJob", b =>
+                {
+                    b.HasBaseType("API.Schema.Jobs.Job");
+
+                    b.Property<string>("FromLocation")
+                        .IsRequired()
+                        .HasMaxLength(256)
+                        .HasColumnType("character varying(256)");
+
+                    b.Property<string>("ToLocation")
+                        .IsRequired()
+                        .HasMaxLength(256)
+                        .HasColumnType("character varying(256)");
+
+                    b.HasDiscriminator().HasValue((byte)3);
+                });
+
+            modelBuilder.Entity("API.Schema.Jobs.RetrieveChaptersJob", b =>
+                {
+                    b.HasBaseType("API.Schema.Jobs.Job");
+
+                    b.Property<string>("MangaId")
+                        .IsRequired()
+                        .HasMaxLength(64)
+                        .HasColumnType("character varying(64)");
+
+                    b.ToTable("Jobs", t =>
+                        {
+                            t.Property("MangaId")
+                                .HasColumnName("RetrieveChaptersJob_MangaId");
+                        });
+
+                    b.HasDiscriminator().HasValue((byte)5);
+                });
+
+            modelBuilder.Entity("API.Schema.Jobs.UpdateFilesDownloadedJob", b =>
+                {
+                    b.HasBaseType("API.Schema.Jobs.Job");
+
+                    b.Property<string>("MangaId")
+                        .IsRequired()
+                        .HasMaxLength(64)
+                        .HasColumnType("character varying(64)");
+
+                    b.ToTable("Jobs", t =>
+                        {
+                            t.Property("MangaId")
+                                .HasColumnName("UpdateFilesDownloadedJob_MangaId");
+                        });
+
+                    b.HasDiscriminator().HasValue((byte)6);
+                });
+
+            modelBuilder.Entity("API.Schema.Jobs.UpdateMetadataJob", b =>
+                {
+                    b.HasBaseType("API.Schema.Jobs.Job");
+
+                    b.Property<string>("MangaId")
+                        .IsRequired()
+                        .HasMaxLength(64)
+                        .HasColumnType("character varying(64)");
+
+                    b.HasIndex("MangaId");
+
+                    b.ToTable("Jobs", t =>
+                        {
+                            t.Property("MangaId")
+                                .HasColumnName("UpdateMetadataJob_MangaId");
+                        });
+
+                    b.HasDiscriminator().HasValue((byte)2);
+                });
+
+            modelBuilder.Entity("API.Schema.LibraryConnectors.Kavita", b =>
+                {
+                    b.HasBaseType("API.Schema.LibraryConnectors.LibraryConnector");
+
+                    b.HasDiscriminator().HasValue((byte)1);
+                });
+
+            modelBuilder.Entity("API.Schema.LibraryConnectors.Komga", b =>
+                {
+                    b.HasBaseType("API.Schema.LibraryConnectors.LibraryConnector");
+
+                    b.HasDiscriminator().HasValue((byte)0);
+                });
+
+            modelBuilder.Entity("API.Schema.MangaConnectors.AsuraToon", b =>
+                {
+                    b.HasBaseType("API.Schema.MangaConnectors.MangaConnector");
+
+                    b.HasDiscriminator().HasValue("AsuraToon");
+                });
+
+            modelBuilder.Entity("API.Schema.MangaConnectors.Bato", b =>
+                {
+                    b.HasBaseType("API.Schema.MangaConnectors.MangaConnector");
+
+                    b.HasDiscriminator().HasValue("Bato");
+                });
+
+            modelBuilder.Entity("API.Schema.MangaConnectors.Global", b =>
+                {
+                    b.HasBaseType("API.Schema.MangaConnectors.MangaConnector");
+
+                    b.HasDiscriminator().HasValue("Global");
+                });
+
+            modelBuilder.Entity("API.Schema.MangaConnectors.MangaDex", b =>
+                {
+                    b.HasBaseType("API.Schema.MangaConnectors.MangaConnector");
+
+                    b.HasDiscriminator().HasValue("MangaDex");
+                });
+
+            modelBuilder.Entity("API.Schema.MangaConnectors.MangaHere", b =>
+                {
+                    b.HasBaseType("API.Schema.MangaConnectors.MangaConnector");
+
+                    b.HasDiscriminator().HasValue("MangaHere");
+                });
+
+            modelBuilder.Entity("API.Schema.MangaConnectors.MangaKatana", b =>
+                {
+                    b.HasBaseType("API.Schema.MangaConnectors.MangaConnector");
+
+                    b.HasDiscriminator().HasValue("MangaKatana");
+                });
+
+            modelBuilder.Entity("API.Schema.MangaConnectors.Manganato", b =>
+                {
+                    b.HasBaseType("API.Schema.MangaConnectors.MangaConnector");
+
+                    b.HasDiscriminator().HasValue("Manganato");
+                });
+
+            modelBuilder.Entity("API.Schema.MangaConnectors.Mangaworld", b =>
+                {
+                    b.HasBaseType("API.Schema.MangaConnectors.MangaConnector");
+
+                    b.HasDiscriminator().HasValue("Mangaworld");
+                });
+
+            modelBuilder.Entity("API.Schema.MangaConnectors.ManhuaPlus", b =>
+                {
+                    b.HasBaseType("API.Schema.MangaConnectors.MangaConnector");
+
+                    b.HasDiscriminator().HasValue("ManhuaPlus");
+                });
+
+            modelBuilder.Entity("API.Schema.MangaConnectors.Weebcentral", b =>
+                {
+                    b.HasBaseType("API.Schema.MangaConnectors.MangaConnector");
+
+                    b.HasDiscriminator().HasValue("Weebcentral");
+                });
+
+            modelBuilder.Entity("API.Schema.Chapter", b =>
+                {
+                    b.HasOne("API.Schema.Manga", "ParentManga")
+                        .WithMany()
+                        .HasForeignKey("ParentMangaId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("ParentManga");
+                });
+
+            modelBuilder.Entity("API.Schema.Jobs.Job", b =>
+                {
+                    b.HasOne("API.Schema.Jobs.Job", "ParentJob")
+                        .WithMany()
+                        .HasForeignKey("ParentJobId")
+                        .OnDelete(DeleteBehavior.Cascade);
+
+                    b.Navigation("ParentJob");
+                });
+
+            modelBuilder.Entity("API.Schema.Link", b =>
+                {
+                    b.HasOne("API.Schema.Manga", null)
+                        .WithMany("Links")
+                        .HasForeignKey("MangaId")
+                        .OnDelete(DeleteBehavior.Cascade);
+                });
+
+            modelBuilder.Entity("API.Schema.Manga", b =>
+                {
+                    b.HasOne("API.Schema.LocalLibrary", "Library")
+                        .WithMany()
+                        .HasForeignKey("LibraryLocalLibraryId")
+                        .OnDelete(DeleteBehavior.Restrict);
+
+                    b.HasOne("API.Schema.MangaConnectors.MangaConnector", "MangaConnector")
+                        .WithMany()
+                        .HasForeignKey("MangaConnectorId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Library");
+
+                    b.Navigation("MangaConnector");
+                });
+
+            modelBuilder.Entity("API.Schema.MangaAltTitle", b =>
+                {
+                    b.HasOne("API.Schema.Manga", null)
+                        .WithMany("AltTitles")
+                        .HasForeignKey("MangaId")
+                        .OnDelete(DeleteBehavior.Cascade);
+                });
+
+            modelBuilder.Entity("AuthorManga", b =>
+                {
+                    b.HasOne("API.Schema.Author", null)
+                        .WithMany()
+                        .HasForeignKey("AuthorsAuthorId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("API.Schema.Manga", null)
+                        .WithMany()
+                        .HasForeignKey("MangaId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("JobJob", b =>
+                {
+                    b.HasOne("API.Schema.Jobs.Job", null)
+                        .WithMany()
+                        .HasForeignKey("DependsOnJobsJobId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("API.Schema.Jobs.Job", null)
+                        .WithMany()
+                        .HasForeignKey("JobId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("MangaMangaTag", b =>
+                {
+                    b.HasOne("API.Schema.Manga", null)
+                        .WithMany()
+                        .HasForeignKey("MangaId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("API.Schema.MangaTag", null)
+                        .WithMany()
+                        .HasForeignKey("MangaTagsTag")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("API.Schema.Jobs.UpdateMetadataJob", b =>
+                {
+                    b.HasOne("API.Schema.Manga", "Manga")
+                        .WithMany()
+                        .HasForeignKey("MangaId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Manga");
+                });
+
+            modelBuilder.Entity("API.Schema.Manga", b =>
+                {
+                    b.Navigation("AltTitles");
+
+                    b.Navigation("Links");
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}
diff --git a/API/Migrations/20250402001438_dev-010425-4.cs b/API/Migrations/20250402001438_dev-010425-4.cs
new file mode 100644
index 0000000..2b4bafd
--- /dev/null
+++ b/API/Migrations/20250402001438_dev-010425-4.cs
@@ -0,0 +1,123 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace API.Migrations
+{
+    /// <inheritdoc />
+    public partial class dev0104254 : Migration
+    {
+        /// <inheritdoc />
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropForeignKey(
+                name: "FK_Jobs_Chapters_ChapterId",
+                table: "Jobs");
+
+            migrationBuilder.DropForeignKey(
+                name: "FK_Jobs_Mangas_DownloadAvailableChaptersJob_MangaId",
+                table: "Jobs");
+
+            migrationBuilder.DropForeignKey(
+                name: "FK_Jobs_Mangas_MangaId",
+                table: "Jobs");
+
+            migrationBuilder.DropForeignKey(
+                name: "FK_Jobs_Mangas_RetrieveChaptersJob_MangaId",
+                table: "Jobs");
+
+            migrationBuilder.DropForeignKey(
+                name: "FK_Jobs_Mangas_UpdateFilesDownloadedJob_MangaId",
+                table: "Jobs");
+
+            migrationBuilder.DropIndex(
+                name: "IX_Jobs_ChapterId",
+                table: "Jobs");
+
+            migrationBuilder.DropIndex(
+                name: "IX_Jobs_DownloadAvailableChaptersJob_MangaId",
+                table: "Jobs");
+
+            migrationBuilder.DropIndex(
+                name: "IX_Jobs_MangaId",
+                table: "Jobs");
+
+            migrationBuilder.DropIndex(
+                name: "IX_Jobs_RetrieveChaptersJob_MangaId",
+                table: "Jobs");
+
+            migrationBuilder.DropIndex(
+                name: "IX_Jobs_UpdateFilesDownloadedJob_MangaId",
+                table: "Jobs");
+        }
+
+        /// <inheritdoc />
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.CreateIndex(
+                name: "IX_Jobs_ChapterId",
+                table: "Jobs",
+                column: "ChapterId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Jobs_DownloadAvailableChaptersJob_MangaId",
+                table: "Jobs",
+                column: "DownloadAvailableChaptersJob_MangaId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Jobs_MangaId",
+                table: "Jobs",
+                column: "MangaId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Jobs_RetrieveChaptersJob_MangaId",
+                table: "Jobs",
+                column: "RetrieveChaptersJob_MangaId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Jobs_UpdateFilesDownloadedJob_MangaId",
+                table: "Jobs",
+                column: "UpdateFilesDownloadedJob_MangaId");
+
+            migrationBuilder.AddForeignKey(
+                name: "FK_Jobs_Chapters_ChapterId",
+                table: "Jobs",
+                column: "ChapterId",
+                principalTable: "Chapters",
+                principalColumn: "ChapterId",
+                onDelete: ReferentialAction.Cascade);
+
+            migrationBuilder.AddForeignKey(
+                name: "FK_Jobs_Mangas_DownloadAvailableChaptersJob_MangaId",
+                table: "Jobs",
+                column: "DownloadAvailableChaptersJob_MangaId",
+                principalTable: "Mangas",
+                principalColumn: "MangaId",
+                onDelete: ReferentialAction.Cascade);
+
+            migrationBuilder.AddForeignKey(
+                name: "FK_Jobs_Mangas_MangaId",
+                table: "Jobs",
+                column: "MangaId",
+                principalTable: "Mangas",
+                principalColumn: "MangaId",
+                onDelete: ReferentialAction.Cascade);
+
+            migrationBuilder.AddForeignKey(
+                name: "FK_Jobs_Mangas_RetrieveChaptersJob_MangaId",
+                table: "Jobs",
+                column: "RetrieveChaptersJob_MangaId",
+                principalTable: "Mangas",
+                principalColumn: "MangaId",
+                onDelete: ReferentialAction.Cascade);
+
+            migrationBuilder.AddForeignKey(
+                name: "FK_Jobs_Mangas_UpdateFilesDownloadedJob_MangaId",
+                table: "Jobs",
+                column: "UpdateFilesDownloadedJob_MangaId",
+                principalTable: "Mangas",
+                principalColumn: "MangaId",
+                onDelete: ReferentialAction.Cascade);
+        }
+    }
+}
diff --git a/API/Migrations/PgsqlContextModelSnapshot.cs b/API/Migrations/PgsqlContextModelSnapshot.cs
index 311c0f3..c290382 100644
--- a/API/Migrations/PgsqlContextModelSnapshot.cs
+++ b/API/Migrations/PgsqlContextModelSnapshot.cs
@@ -446,8 +446,6 @@ namespace API.Migrations
                         .HasMaxLength(64)
                         .HasColumnType("character varying(64)");
 
-                    b.HasIndex("MangaId");
-
                     b.ToTable("Jobs", t =>
                         {
                             t.Property("MangaId")
@@ -466,8 +464,6 @@ namespace API.Migrations
                         .HasMaxLength(64)
                         .HasColumnType("character varying(64)");
 
-                    b.HasIndex("MangaId");
-
                     b.HasDiscriminator().HasValue((byte)4);
                 });
 
@@ -480,8 +476,6 @@ namespace API.Migrations
                         .HasMaxLength(64)
                         .HasColumnType("character varying(64)");
 
-                    b.HasIndex("ChapterId");
-
                     b.HasDiscriminator().HasValue((byte)0);
                 });
 
@@ -511,8 +505,6 @@ namespace API.Migrations
                         .HasMaxLength(64)
                         .HasColumnType("character varying(64)");
 
-                    b.HasIndex("MangaId");
-
                     b.ToTable("Jobs", t =>
                         {
                             t.Property("MangaId")
@@ -531,8 +523,6 @@ namespace API.Migrations
                         .HasMaxLength(64)
                         .HasColumnType("character varying(64)");
 
-                    b.HasIndex("MangaId");
-
                     b.ToTable("Jobs", t =>
                         {
                             t.Property("MangaId")
@@ -746,61 +736,6 @@ namespace API.Migrations
                         .IsRequired();
                 });
 
-            modelBuilder.Entity("API.Schema.Jobs.DownloadAvailableChaptersJob", b =>
-                {
-                    b.HasOne("API.Schema.Manga", "Manga")
-                        .WithMany()
-                        .HasForeignKey("MangaId")
-                        .OnDelete(DeleteBehavior.Cascade)
-                        .IsRequired();
-
-                    b.Navigation("Manga");
-                });
-
-            modelBuilder.Entity("API.Schema.Jobs.DownloadMangaCoverJob", b =>
-                {
-                    b.HasOne("API.Schema.Manga", "Manga")
-                        .WithMany()
-                        .HasForeignKey("MangaId")
-                        .OnDelete(DeleteBehavior.Cascade)
-                        .IsRequired();
-
-                    b.Navigation("Manga");
-                });
-
-            modelBuilder.Entity("API.Schema.Jobs.DownloadSingleChapterJob", b =>
-                {
-                    b.HasOne("API.Schema.Chapter", "Chapter")
-                        .WithMany()
-                        .HasForeignKey("ChapterId")
-                        .OnDelete(DeleteBehavior.Cascade)
-                        .IsRequired();
-
-                    b.Navigation("Chapter");
-                });
-
-            modelBuilder.Entity("API.Schema.Jobs.RetrieveChaptersJob", b =>
-                {
-                    b.HasOne("API.Schema.Manga", "Manga")
-                        .WithMany()
-                        .HasForeignKey("MangaId")
-                        .OnDelete(DeleteBehavior.Cascade)
-                        .IsRequired();
-
-                    b.Navigation("Manga");
-                });
-
-            modelBuilder.Entity("API.Schema.Jobs.UpdateFilesDownloadedJob", b =>
-                {
-                    b.HasOne("API.Schema.Manga", "Manga")
-                        .WithMany()
-                        .HasForeignKey("MangaId")
-                        .OnDelete(DeleteBehavior.Cascade)
-                        .IsRequired();
-
-                    b.Navigation("Manga");
-                });
-
             modelBuilder.Entity("API.Schema.Jobs.UpdateMetadataJob", b =>
                 {
                     b.HasOne("API.Schema.Manga", "Manga")
diff --git a/API/Schema/Jobs/DownloadAvailableChaptersJob.cs b/API/Schema/Jobs/DownloadAvailableChaptersJob.cs
index ed2b092..e3ae719 100644
--- a/API/Schema/Jobs/DownloadAvailableChaptersJob.cs
+++ b/API/Schema/Jobs/DownloadAvailableChaptersJob.cs
@@ -1,5 +1,4 @@
 using System.ComponentModel.DataAnnotations;
-using Newtonsoft.Json;
 
 namespace API.Schema.Jobs;
 
@@ -10,9 +9,6 @@ public class DownloadAvailableChaptersJob(ulong recurrenceMs, string mangaId, st
     [Required]
     public string MangaId { get; init; } = mangaId;
     
-    [JsonIgnore]
-    public Manga? Manga { get; init; }
-    
     protected override IEnumerable<Job> RunInternal(PgsqlContext context)
     {
         return context.Chapters.Where(c => c.ParentMangaId == MangaId).AsEnumerable()
diff --git a/API/Schema/Jobs/DownloadMangaCoverJob.cs b/API/Schema/Jobs/DownloadMangaCoverJob.cs
index 7446fa8..bcf2c1c 100644
--- a/API/Schema/Jobs/DownloadMangaCoverJob.cs
+++ b/API/Schema/Jobs/DownloadMangaCoverJob.cs
@@ -1,5 +1,4 @@
 using System.ComponentModel.DataAnnotations;
-using Newtonsoft.Json;
 
 namespace API.Schema.Jobs;
 
@@ -9,12 +8,10 @@ public class DownloadMangaCoverJob(string mangaId, string? parentJobId = null, I
     [StringLength(64)]
     [Required]
     public string MangaId { get; init; } = mangaId;
-    [JsonIgnore]
-    public Manga? Manga { get; init; }
     
     protected override IEnumerable<Job> RunInternal(PgsqlContext context)
     {
-        Manga? manga = Manga ?? context.Mangas.Find(this.MangaId);
+        Manga? manga = context.Mangas.Find(this.MangaId);
         if (manga is null)
         {
             Log.Error($"Manga {this.MangaId} not found.");
diff --git a/API/Schema/Jobs/DownloadSingleChapterJob.cs b/API/Schema/Jobs/DownloadSingleChapterJob.cs
index 51259c0..417f5e8 100644
--- a/API/Schema/Jobs/DownloadSingleChapterJob.cs
+++ b/API/Schema/Jobs/DownloadSingleChapterJob.cs
@@ -3,7 +3,6 @@ using System.IO.Compression;
 using System.Runtime.InteropServices;
 using API.MangaDownloadClients;
 using API.Schema.MangaConnectors;
-using Newtonsoft.Json;
 using SixLabors.ImageSharp;
 using SixLabors.ImageSharp.Formats.Jpeg;
 using SixLabors.ImageSharp.Processing;
@@ -19,24 +18,21 @@ public class DownloadSingleChapterJob(string chapterId, string? parentJobId = nu
     [Required]
     public string ChapterId { get; init; } = chapterId;
     
-    [JsonIgnore]
-    public Chapter? Chapter { get; init; }
-    
     protected override IEnumerable<Job> RunInternal(PgsqlContext context)
     {
-        Chapter? chapter = Chapter ?? context.Chapters.Find(ChapterId);
+        Chapter? chapter = context.Chapters.Find(ChapterId);
         if (chapter is null)
         {
             Log.Error("Chapter is null.");
             return [];
         }
-        Manga? manga = chapter.ParentManga ?? context.Mangas.Find(chapter.ParentMangaId);
+        Manga? manga = context.Mangas.Find(chapter.ParentMangaId) ?? chapter.ParentManga;
         if (manga is null)
         {
             Log.Error("Manga is null.");
             return [];
         }
-        MangaConnector? connector = manga.MangaConnector ?? context.MangaConnectors.Find(manga.MangaConnectorId);
+        MangaConnector? connector = context.MangaConnectors.Find(manga.MangaConnectorId) ?? manga.MangaConnector;
         if (connector is null)
         {
             Log.Error("Connector is null.");
@@ -45,7 +41,7 @@ public class DownloadSingleChapterJob(string chapterId, string? parentJobId = nu
         string[] imageUrls = connector.GetChapterImageUrls(chapter);
         if (imageUrls.Length < 1)
         {
-            Log.Info($"No imageUrls for chapter {chapterId}");
+            Log.Info($"No imageUrls for chapter {ChapterId}");
             return [];
         }
         string? saveArchiveFilePath = chapter.FullArchiveFilePath;
diff --git a/API/Schema/Jobs/RetrieveChaptersJob.cs b/API/Schema/Jobs/RetrieveChaptersJob.cs
index 512e2c1..c0eb38d 100644
--- a/API/Schema/Jobs/RetrieveChaptersJob.cs
+++ b/API/Schema/Jobs/RetrieveChaptersJob.cs
@@ -1,7 +1,6 @@
 using System.ComponentModel.DataAnnotations;
 using API.Schema.MangaConnectors;
 using Microsoft.EntityFrameworkCore;
-using Newtonsoft.Json;
 
 namespace API.Schema.Jobs;
 
@@ -12,12 +11,9 @@ public class RetrieveChaptersJob(ulong recurrenceMs, string mangaId, string? par
     [Required]
     public string MangaId { get; init; } = mangaId;
     
-    [JsonIgnore]
-    public Manga? Manga { get; init; }
-    
     protected override IEnumerable<Job> RunInternal(PgsqlContext context)
     {
-        Manga? manga = context.Mangas.Find(MangaId) ?? Manga;
+        Manga? manga = context.Mangas.Find(MangaId);
         if (manga is null)
         {
             Log.Error("Manga is null.");
diff --git a/API/Schema/Jobs/UpdateFilesDownloadedJob.cs b/API/Schema/Jobs/UpdateFilesDownloadedJob.cs
index 836b1c7..a68c3b6 100644
--- a/API/Schema/Jobs/UpdateFilesDownloadedJob.cs
+++ b/API/Schema/Jobs/UpdateFilesDownloadedJob.cs
@@ -10,9 +10,6 @@ public class UpdateFilesDownloadedJob(ulong recurrenceMs, string mangaId, string
     [Required]
     public string MangaId { get; init; } = mangaId;
     
-    [JsonIgnore]
-    public virtual Manga? Manga { get; init; }
-    
     protected override IEnumerable<Job> RunInternal(PgsqlContext context)
     {
         IQueryable<Chapter> chapters = context.Chapters.Where(c => c.ParentMangaId == MangaId);
diff --git a/API/Schema/PgsqlContext.cs b/API/Schema/PgsqlContext.cs
index 4c570d4..3d6aaf0 100644
--- a/API/Schema/PgsqlContext.cs
+++ b/API/Schema/PgsqlContext.cs
@@ -56,12 +56,6 @@ public class PgsqlContext(DbContextOptions<PgsqlContext> options) : DbContext(op
         modelBuilder.Entity<Job>()
             .HasMany<Job>(j => j.DependsOnJobs)
             .WithMany();
-        modelBuilder.Entity<DownloadAvailableChaptersJob>()
-            .Navigation(dncj => dncj.Manga)
-            .AutoInclude();
-        modelBuilder.Entity<DownloadSingleChapterJob>()
-            .Navigation(dscj => dscj.Chapter)
-            .AutoInclude();
         modelBuilder.Entity<UpdateMetadataJob>()
             .Navigation(umj => umj.Manga)
             .AutoInclude();
diff --git a/API/Tranga.cs b/API/Tranga.cs
index 2d91a43..e5e46b7 100644
--- a/API/Tranga.cs
+++ b/API/Tranga.cs
@@ -148,8 +148,8 @@ public static class Tranga
                 if (job is DownloadAvailableChaptersJob dncj)
                 {
                     if (RunningJobs.Values.Any(j =>
-                            j is DownloadAvailableChaptersJob rdncj &&
-                            rdncj.Manga?.MangaConnector == dncj.Manga?.MangaConnector))
+                            j is DownloadAvailableChaptersJob rdncj && 
+                            context.Mangas.Find(rdncj.MangaId)?.MangaConnector == context.Mangas.Find(dncj.MangaId)?.MangaConnector))
                     {
                         continue;
                     }
@@ -157,8 +157,9 @@ public static class Tranga
                 else if (job is DownloadSingleChapterJob dscj)
                 {
                     if (RunningJobs.Values.Any(j =>
-                            j is DownloadSingleChapterJob rdscj && rdscj.Chapter?.ParentManga?.MangaConnector ==
-                            dscj.Chapter?.ParentManga?.MangaConnector))
+                            j is DownloadSingleChapterJob rdscj &&
+                            context.Chapters.Find(rdscj.ChapterId)?.ParentManga?.MangaConnector ==
+                            context.Chapters.Find(dscj.ChapterId)?.ParentManga?.MangaConnector))
                     {
                         continue;
                     }
@@ -214,7 +215,9 @@ public static class Tranga
         {
             foreach (DownloadAvailableChaptersJob job in jobsByType[JobType.DownloadAvailableChaptersJob])
             {
-                Manga manga = job.Manga ?? context.Mangas.Find(job.MangaId)!;
+                Manga? manga = context.Mangas.Find(job.MangaId);
+                if(manga is null)
+                    continue;
                 MangaConnector connector = manga.MangaConnector ?? context.MangaConnectors.Find(manga.MangaConnectorId)!;
                 if(!metadataJobsByConnector.TryAdd(connector, [job]))
                     metadataJobsByConnector[connector].Add(job);
@@ -234,7 +237,9 @@ public static class Tranga
         {
             foreach (RetrieveChaptersJob job in jobsByType[JobType.RetrieveChaptersJob])
             {
-                Manga manga = job.Manga ?? context.Mangas.Find(job.MangaId)!;
+                Manga? manga = context.Mangas.Find(job.MangaId);
+                if(manga is null)
+                    continue;
                 MangaConnector connector = manga.MangaConnector ?? context.MangaConnectors.Find(manga.MangaConnectorId)!;
                 if(!metadataJobsByConnector.TryAdd(connector, [job]))
                     metadataJobsByConnector[connector].Add(job);
@@ -249,7 +254,9 @@ public static class Tranga
             Dictionary<MangaConnector, List<DownloadSingleChapterJob>> downloadJobsByConnector = new();
             foreach (DownloadSingleChapterJob job in jobsByType[JobType.DownloadSingleChapterJob])
             {
-                Chapter chapter = job.Chapter ?? context.Chapters.Find(job.ChapterId)!;
+                Chapter? chapter = context.Chapters.Find(job.ChapterId);
+                if(chapter is null)
+                    continue;
                 Manga manga = chapter.ParentManga ?? context.Mangas.Find(chapter.ParentMangaId)!;
                 MangaConnector connector = manga.MangaConnector ?? context.MangaConnectors.Find(manga.MangaConnectorId)!;
             
@@ -261,7 +268,7 @@ public static class Tranga
                 ret = ret.Append(
                     downloadJobs.Where(j => j.NextExecution == downloadJobs
                             .MinBy(mj => mj.NextExecution)!.NextExecution)
-                        .MinBy(j => j.Chapter ?? context.Chapters.Find(j.ChapterId)!))!;
+                        .MinBy(j => context.Chapters.Find(j.ChapterId)!))!;
         }
         
         return ret;