From f10c478cab66f32349bbc833f844cb4aa7d784b7 Mon Sep 17 00:00:00 2001 From: Glax Date: Wed, 19 Mar 2025 00:16:37 +0100 Subject: [PATCH] Add 503 response for covers and requests that take longer --- API/Controllers/MangaController.cs | 39 +++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/API/Controllers/MangaController.cs b/API/Controllers/MangaController.cs index bb0c311..49e689b 100644 --- a/API/Controllers/MangaController.cs +++ b/API/Controllers/MangaController.cs @@ -96,29 +96,32 @@ public class MangaController(PgsqlContext context) : Controller /// Cover not loaded /// The formatting-request was invalid /// Manga with ID not found + /// Retry later, downloading cover [HttpGet("{MangaId}/Cover")] [ProducesResponseType(Status200OK,"image/jpeg")] [ProducesResponseType(Status204NoContent)] [ProducesResponseType(Status400BadRequest)] [ProducesResponseType(Status404NotFound)] + [ProducesResponseType(Status503ServiceUnavailable, "text/plain")] public IActionResult GetCover(string MangaId, [FromQuery]int? width, [FromQuery]int? height) { + DateTime requestStarted = HttpContext.Features.Get()?.RequestTime ?? DateTime.Now; Manga? m = context.Mangas.Find(MangaId); if (m is null) return NotFound(); + if (!System.IO.File.Exists(m.CoverFileNameInCache)) { - bool coverIsBeingDownloaded = false; - do + List coverDownloadJobs = context.Jobs.Where(j => j.JobType == JobType.DownloadMangaCoverJob).ToList(); + if (coverDownloadJobs.Any(j => j is DownloadMangaCoverJob dmc && dmc.MangaId == MangaId)) { - coverIsBeingDownloaded = context.Jobs.Where(j => j.JobType == JobType.DownloadMangaCoverJob).AsEnumerable() - .Any(j => j is DownloadMangaCoverJob dmcj && dmcj.MangaId == MangaId); - Thread.Sleep(100); - } while (coverIsBeingDownloaded); - if (!System.IO.File.Exists(m.CoverFileNameInCache)) - return NoContent(); + Response.Headers.Add("Retry-After", $"{TrangaSettings.startNewJobTimeoutMs * coverDownloadJobs.Count() / 1000:D}"); + return StatusCode(Status503ServiceUnavailable, TrangaSettings.startNewJobTimeoutMs * coverDownloadJobs.Count() / 1000); + } } + if (!System.IO.File.Exists(m.CoverFileNameInCache)) + return NoContent(); Image image = Image.Load(m.CoverFileNameInCache); if (width is { } w && height is { } h) @@ -212,16 +215,25 @@ public class MangaController(PgsqlContext context) : Controller /// No available chapters /// Manga with ID not found. /// Could not retrieve the maximum chapter-number + /// Retry after timeout, updating value [HttpGet("{MangaId}/Chapter/LatestAvailable")] [ProducesResponseType(Status200OK, "application/json")] [ProducesResponseType(Status204NoContent)] - [ProducesResponseType(Status404NotFound)] + [ProducesResponseType(Status404NotFound, "text/plain")] [ProducesResponseType(Status500InternalServerError, "text/plain")] + [ProducesResponseType(Status503ServiceUnavailable, "text/plain")] public IActionResult GetLatestChapter(string MangaId) { Manga? m = context.Mangas.Find(MangaId); if (m is null) return NotFound(); + + List retrieveChapterJobs = context.Jobs.Where(j => j.JobType == JobType.RetrieveChaptersJob).ToList(); + if (retrieveChapterJobs.Any(j => j is RetrieveChaptersJob rcj && rcj.MangaId == MangaId)) + { + Response.Headers.Add("Retry-After", $"{TrangaSettings.startNewJobTimeoutMs * retrieveChapterJobs.Count() / 1000:D}"); + return StatusCode(Status503ServiceUnavailable, TrangaSettings.startNewJobTimeoutMs * retrieveChapterJobs.Count() / 1000); + } List chapters = context.Chapters.Where(c => c.ParentMangaId == m.MangaId).ToList(); if (chapters.Count == 0) @@ -242,17 +254,26 @@ public class MangaController(PgsqlContext context) : Controller /// No available chapters /// Manga with ID not found. /// Could not retrieve the maximum chapter-number + /// Retry after timeout, updating value [HttpGet("{MangaId}/Chapter/LatestDownloaded")] [ProducesResponseType(Status200OK, "application/json")] [ProducesResponseType(Status204NoContent)] [ProducesResponseType(Status404NotFound)] [ProducesResponseType(Status500InternalServerError, "text/plain")] + [ProducesResponseType(Status503ServiceUnavailable, "text/plain")] public IActionResult GetLatestChapterDownloaded(string MangaId) { Manga? m = context.Mangas.Find(MangaId); if (m is null) return NotFound(); + List retrieveChapterJobs = context.Jobs.Where(j => j.JobType == JobType.RetrieveChaptersJob).ToList(); + if (retrieveChapterJobs.Any(j => j is RetrieveChaptersJob rcj && rcj.MangaId == MangaId)) + { + Response.Headers.Add("Retry-After", $"{TrangaSettings.startNewJobTimeoutMs * retrieveChapterJobs.Count() / 1000:D}"); + return StatusCode(Status503ServiceUnavailable, TrangaSettings.startNewJobTimeoutMs * retrieveChapterJobs.Count() / 1000); + } + List chapters = context.Chapters.Where(c => c.ParentMangaId == m.MangaId && c.Downloaded == true).ToList(); if (chapters.Count == 0) return NoContent();