[FA-misc] Mass transit overhaul, needs testing and review

This commit is contained in:
gamer147
2026-01-21 23:16:31 -05:00
parent 055ef33666
commit f88f340d0a
97 changed files with 1150 additions and 858 deletions

View File

@@ -1,15 +1,15 @@
using FictionArchive.Common.Enums;
using FictionArchive.Service.FileService.IntegrationEvents;
using FictionArchive.Service.NovelService.Models.Configuration;
using FictionArchive.Service.NovelService.Models.Enums;
using FictionArchive.Service.NovelService.Models.Images;
using FictionArchive.Service.NovelService.Models.IntegrationEvents;
using FictionArchive.Service.NovelService.Models.Localization;
using FictionArchive.Service.NovelService.Models.Novels;
using FictionArchive.Service.NovelService.Models.SourceAdapters;
using FictionArchive.Service.NovelService.Services.SourceAdapters;
using FictionArchive.Service.Shared.Services.EventBus;
using FictionArchive.Service.Shared.MassTransit.Contracts.Commands;
using FictionArchive.Service.Shared.MassTransit.Contracts.Events;
using HtmlAgilityPack;
using MassTransit;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
@@ -20,15 +20,23 @@ public class NovelUpdateService
private readonly NovelServiceDbContext _dbContext;
private readonly ILogger<NovelUpdateService> _logger;
private readonly IEnumerable<ISourceAdapter> _sourceAdapters;
private readonly IEventBus _eventBus;
private readonly IPublishEndpoint _publishEndpoint;
private readonly ISendEndpointProvider _sendEndpointProvider;
private readonly NovelUpdateServiceConfiguration _novelUpdateServiceConfiguration;
public NovelUpdateService(NovelServiceDbContext dbContext, ILogger<NovelUpdateService> logger, IEnumerable<ISourceAdapter> sourceAdapters, IEventBus eventBus, IOptions<NovelUpdateServiceConfiguration> novelUpdateServiceConfiguration)
public NovelUpdateService(
NovelServiceDbContext dbContext,
ILogger<NovelUpdateService> logger,
IEnumerable<ISourceAdapter> sourceAdapters,
IPublishEndpoint publishEndpoint,
ISendEndpointProvider sendEndpointProvider,
IOptions<NovelUpdateServiceConfiguration> novelUpdateServiceConfiguration)
{
_dbContext = dbContext;
_logger = logger;
_sourceAdapters = sourceAdapters;
_eventBus = eventBus;
_publishEndpoint = publishEndpoint;
_sendEndpointProvider = sendEndpointProvider;
_novelUpdateServiceConfiguration = novelUpdateServiceConfiguration.Value;
}
@@ -393,7 +401,7 @@ public class NovelUpdateService
// Publish novel created event for new novels
if (existingNovel == null)
{
await _eventBus.Publish(new NovelCreatedEvent
await _publishEndpoint.Publish(new NovelCreatedEvent
{
NovelId = novel.Id,
Title = novel.Name.Texts.First(t => t.Language == novel.RawLanguage).Text,
@@ -408,7 +416,7 @@ public class NovelUpdateService
{
foreach (var chapter in volume.Chapters.Where(c => !existingChapterIds.Contains(c.Id)))
{
await _eventBus.Publish(new ChapterCreatedEvent
await _publishEndpoint.Publish(new ChapterCreatedEvent
{
ChapterId = chapter.Id,
NovelId = novel.Id,
@@ -420,10 +428,11 @@ public class NovelUpdateService
}
}
// Publish cover image event if needed
// Send cover image upload command if needed
if (shouldPublishCoverEvent && novel.CoverImage != null && metadata.CoverImage != null)
{
await _eventBus.Publish(new FileUploadRequestCreatedEvent
var uploadEndpoint = await _sendEndpointProvider.GetSendEndpoint(new Uri("queue:upload-file-command"));
await uploadEndpoint.Send(new UploadFileCommand
{
RequestId = novel.CoverImage.Id,
FileData = metadata.CoverImage.Data,
@@ -431,7 +440,8 @@ public class NovelUpdateService
});
}
// Publish chapter pull events for chapters without body content
// Send chapter pull commands for chapters without body content
var pullChapterEndpoint = await _sendEndpointProvider.GetSendEndpoint(new Uri("queue:pull-chapter-content-command"));
foreach (var volume in novel.Volumes)
{
var chaptersNeedingPull = volume.Chapters
@@ -440,7 +450,7 @@ public class NovelUpdateService
foreach (var chapter in chaptersNeedingPull)
{
await _eventBus.Publish(new ChapterPullRequestedEvent
await pullChapterEndpoint.Send(new PullChapterContentCommand
{
NovelId = novel.Id,
VolumeId = volume.Id,
@@ -513,12 +523,13 @@ public class NovelUpdateService
localizationText.Text = chapterDoc.DocumentNode.OuterHtml;
await _dbContext.SaveChangesAsync();
// Body was updated, raise image request
// Body was updated, send upload commands for images
var uploadEndpoint = await _sendEndpointProvider.GetSendEndpoint(new Uri("queue:upload-file-command"));
int imgCount = 0;
foreach (var image in chapter.Images)
{
var data = rawChapter.ImageData.FirstOrDefault(img => img.Url == image.OriginalPath);
await _eventBus.Publish(new FileUploadRequestCreatedEvent()
await uploadEndpoint.Send(new UploadFileCommand
{
FileData = data.Data,
FilePath = $"{novel.Id}/Images/Chapter-{chapter.Id}/{imgCount++}.jpg",
@@ -557,26 +568,28 @@ public class NovelUpdateService
await _dbContext.SaveChangesAsync();
}
public async Task<NovelUpdateRequestedEvent> QueueNovelImport(string novelUrl)
public async Task<ImportNovelCommand> QueueNovelImport(string novelUrl)
{
var importNovelRequestEvent = new NovelUpdateRequestedEvent()
var command = new ImportNovelCommand
{
NovelUrl = novelUrl
};
await _eventBus.Publish(importNovelRequestEvent);
return importNovelRequestEvent;
var endpoint = await _sendEndpointProvider.GetSendEndpoint(new Uri("queue:import-novel-command"));
await endpoint.Send(command);
return command;
}
public async Task<ChapterPullRequestedEvent> QueueChapterPull(uint novelId, uint volumeId, uint chapterOrder)
public async Task<PullChapterContentCommand> QueueChapterPull(uint novelId, uint volumeId, uint chapterOrder)
{
var chapterPullEvent = new ChapterPullRequestedEvent()
var command = new PullChapterContentCommand
{
NovelId = novelId,
VolumeId = volumeId,
ChapterOrder = chapterOrder
};
await _eventBus.Publish(chapterPullEvent);
return chapterPullEvent;
var endpoint = await _sendEndpointProvider.GetSendEndpoint(new Uri("queue:pull-chapter-content-command"));
await endpoint.Send(command);
return command;
}
public async Task DeleteNovel(uint novelId)