[FA-misc] Saga seems to work, fixed a UserNovelDataService bug
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using FictionArchive.Common.Enums;
|
||||
using FictionArchive.Service.NovelService.Contracts;
|
||||
using FictionArchive.Service.NovelService.Models;
|
||||
using FictionArchive.Service.NovelService.Models.Configuration;
|
||||
using FictionArchive.Service.NovelService.Models.Enums;
|
||||
using FictionArchive.Service.NovelService.Models.Images;
|
||||
@@ -12,6 +13,7 @@ using HtmlAgilityPack;
|
||||
using MassTransit;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Options;
|
||||
using NodaTime;
|
||||
|
||||
namespace FictionArchive.Service.NovelService.Services;
|
||||
|
||||
@@ -22,14 +24,16 @@ public class NovelUpdateService
|
||||
private readonly IEnumerable<ISourceAdapter> _sourceAdapters;
|
||||
private readonly IPublishEndpoint _publishEndpoint;
|
||||
private readonly NovelUpdateServiceConfiguration _novelUpdateServiceConfiguration;
|
||||
private readonly IClock _clock;
|
||||
|
||||
public NovelUpdateService(NovelServiceDbContext dbContext, ILogger<NovelUpdateService> logger, IEnumerable<ISourceAdapter> sourceAdapters, IPublishEndpoint publishEndpoint, IOptions<NovelUpdateServiceConfiguration> novelUpdateServiceConfiguration)
|
||||
public NovelUpdateService(NovelServiceDbContext dbContext, ILogger<NovelUpdateService> logger, IEnumerable<ISourceAdapter> sourceAdapters, IPublishEndpoint publishEndpoint, IOptions<NovelUpdateServiceConfiguration> novelUpdateServiceConfiguration, IClock clock)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
_logger = logger;
|
||||
_sourceAdapters = sourceAdapters;
|
||||
_publishEndpoint = publishEndpoint;
|
||||
_novelUpdateServiceConfiguration = novelUpdateServiceConfiguration.Value;
|
||||
_clock = clock;
|
||||
}
|
||||
|
||||
#region Helper Methods
|
||||
@@ -299,7 +303,7 @@ public class NovelUpdateService
|
||||
|
||||
#endregion
|
||||
|
||||
public async Task<Novel> ImportNovel(string novelUrl)
|
||||
public async Task<Novel> ImportNovel(Guid importId, string novelUrl)
|
||||
{
|
||||
// Step 1: Get metadata from source adapter
|
||||
NovelMetadata? metadata = null;
|
||||
@@ -417,10 +421,24 @@ public class NovelUpdateService
|
||||
}
|
||||
}
|
||||
|
||||
// Count chapters that need pulling
|
||||
var chaptersNeedingPull = novel.Volumes
|
||||
.SelectMany(v => v.Chapters)
|
||||
.Where(c => c.Body?.Texts == null || !c.Body.Texts.Any())
|
||||
.ToList();
|
||||
|
||||
// Publish metadata imported event for saga
|
||||
await _publishEndpoint.Publish<INovelMetadataImported>(new NovelMetadataImported(
|
||||
importId,
|
||||
novel.Id,
|
||||
chaptersNeedingPull.Count
|
||||
));
|
||||
|
||||
// Publish cover image event if needed
|
||||
if (shouldPublishCoverEvent && novel.CoverImage != null && metadata.CoverImage != null)
|
||||
{
|
||||
await _publishEndpoint.Publish<IFileUploadRequestCreated>(new FileUploadRequestCreated(
|
||||
importId,
|
||||
novel.CoverImage.Id,
|
||||
$"Novels/{novel.Id}/Images/cover.jpg",
|
||||
metadata.CoverImage.Data));
|
||||
@@ -429,13 +447,14 @@ public class NovelUpdateService
|
||||
// Publish chapter pull events for chapters without body content
|
||||
foreach (var volume in novel.Volumes)
|
||||
{
|
||||
var chaptersNeedingPull = volume.Chapters
|
||||
var volumeChaptersNeedingPull = volume.Chapters
|
||||
.Where(c => c.Body?.Texts == null || !c.Body.Texts.Any())
|
||||
.ToList();
|
||||
|
||||
foreach (var chapter in chaptersNeedingPull)
|
||||
foreach (var chapter in volumeChaptersNeedingPull)
|
||||
{
|
||||
await _publishEndpoint.Publish<IChapterPullRequested>(new ChapterPullRequested(
|
||||
importId,
|
||||
novel.Id,
|
||||
volume.Id,
|
||||
chapter.Order));
|
||||
@@ -445,7 +464,7 @@ public class NovelUpdateService
|
||||
return novel;
|
||||
}
|
||||
|
||||
public async Task<Chapter> PullChapterContents(uint novelId, uint volumeId, uint chapterOrder)
|
||||
public async Task<(Chapter chapter, int imageCount)> PullChapterContents(Guid importId, uint novelId, uint volumeId, uint chapterOrder)
|
||||
{
|
||||
var novel = await _dbContext.Novels.Where(novel => novel.Id == novelId)
|
||||
.Include(novel => novel.Volumes)
|
||||
@@ -512,12 +531,13 @@ public class NovelUpdateService
|
||||
{
|
||||
var data = rawChapter.ImageData.FirstOrDefault(img => img.Url == image.OriginalPath);
|
||||
await _publishEndpoint.Publish<IFileUploadRequestCreated>(new FileUploadRequestCreated(
|
||||
importId,
|
||||
image.Id,
|
||||
$"Novels/{novel.Id}/Images/Chapter-{chapter.Id}/{imgCount++}.jpg",
|
||||
data.Data));
|
||||
}
|
||||
|
||||
return chapter;
|
||||
return (chapter, chapter.Images.Count);
|
||||
}
|
||||
|
||||
public async Task UpdateImage(Guid imageId, string newUrl)
|
||||
@@ -548,16 +568,34 @@ public class NovelUpdateService
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task<NovelUpdateRequested> QueueNovelImport(string novelUrl)
|
||||
public async Task<NovelImportRequested> QueueNovelImport(string novelUrl)
|
||||
{
|
||||
var importNovelRequestEvent = new NovelUpdateRequested(novelUrl);
|
||||
await _publishEndpoint.Publish<INovelUpdateRequested>(importNovelRequestEvent);
|
||||
var importId = Guid.NewGuid();
|
||||
var activeImport = new ActiveImport
|
||||
{
|
||||
ImportId = importId,
|
||||
NovelUrl = novelUrl,
|
||||
StartedAt = _clock.GetCurrentInstant()
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
await _dbContext.ActiveImports.AddAsync(activeImport);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
catch (DbUpdateException)
|
||||
{
|
||||
throw new InvalidOperationException($"An import is already in progress for {novelUrl}");
|
||||
}
|
||||
|
||||
var importNovelRequestEvent = new NovelImportRequested(importId, novelUrl);
|
||||
await _publishEndpoint.Publish<INovelImportRequested>(importNovelRequestEvent);
|
||||
return importNovelRequestEvent;
|
||||
}
|
||||
|
||||
public async Task<ChapterPullRequested> QueueChapterPull(uint novelId, uint volumeId, uint chapterOrder)
|
||||
public async Task<ChapterPullRequested> QueueChapterPull(Guid importId, uint novelId, uint volumeId, uint chapterOrder)
|
||||
{
|
||||
var chapterPullEvent = new ChapterPullRequested(novelId, volumeId, chapterOrder);
|
||||
var chapterPullEvent = new ChapterPullRequested(importId, novelId, volumeId, chapterOrder);
|
||||
await _publishEndpoint.Publish<IChapterPullRequested>(chapterPullEvent);
|
||||
return chapterPullEvent;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user