From fdcd53b2599a26c79c0db615ae58b3ec9d88e2f5 Mon Sep 17 00:00:00 2001 From: Rodrigo Verdiani Date: Wed, 25 Mar 2026 07:58:01 -0300 Subject: [PATCH] refactor: update RabbitMQ queue configurations and improve content sorting --- pom.xml | 32 +++++ .../queue/consumer/MangaUpdateConsumer.java | 1 + .../common/config/GitInfoLogger.java | 24 ++++ .../magamochi/common/config/RabbitConfig.java | 111 ++++++++++++++++-- .../repository/MangaImportJobRepository.java | 2 +- .../content/service/ContentService.java | 2 +- .../task/PendingImportScannerTask.java | 2 +- src/main/resources/application.yml | 3 + 8 files changed, 163 insertions(+), 14 deletions(-) create mode 100644 src/main/java/com/magamochi/common/config/GitInfoLogger.java diff --git a/pom.xml b/pom.xml index f29e8e7..49ef5d8 100644 --- a/pom.xml +++ b/pom.xml @@ -133,6 +133,22 @@ + + + src/main/resources + true + + **/banner.txt + + + + src/main/resources + false + + **/banner.txt + + + org.apache.maven.plugins @@ -168,6 +184,22 @@ + + io.github.git-commit-id + git-commit-id-maven-plugin + 9.0.1 + + + + revision + + + + + false + true + + diff --git a/src/main/java/com/magamochi/catalog/queue/consumer/MangaUpdateConsumer.java b/src/main/java/com/magamochi/catalog/queue/consumer/MangaUpdateConsumer.java index 3ce0d0d..51b0f60 100644 --- a/src/main/java/com/magamochi/catalog/queue/consumer/MangaUpdateConsumer.java +++ b/src/main/java/com/magamochi/catalog/queue/consumer/MangaUpdateConsumer.java @@ -16,6 +16,7 @@ public class MangaUpdateConsumer { @RabbitListener(queues = "${queues.manga-update}") public void receiveMangaUpdateCommand(MangaUpdateCommand command) { log.info("Received manga update command: {}", command); + mangaUpdateService.update(command.mangaId()); } } diff --git a/src/main/java/com/magamochi/common/config/GitInfoLogger.java b/src/main/java/com/magamochi/common/config/GitInfoLogger.java new file mode 100644 index 0000000..8d8b41d --- /dev/null +++ b/src/main/java/com/magamochi/common/config/GitInfoLogger.java @@ -0,0 +1,24 @@ +package com.magamochi.common.config; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.event.ApplicationStartedEvent; +import org.springframework.boot.info.GitProperties; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +@RequiredArgsConstructor +public class GitInfoLogger { + private final GitProperties gitProperties; + + @EventListener(ApplicationStartedEvent.class) + public void logGitInfo() { + log.info( + "Git Info :: commit {} ({}) :: built at {}", + gitProperties.getShortCommitId(), + gitProperties.getBranch(), + gitProperties.getCommitTime()); + } +} diff --git a/src/main/java/com/magamochi/common/config/RabbitConfig.java b/src/main/java/com/magamochi/common/config/RabbitConfig.java index f15bca0..bdbc28c 100644 --- a/src/main/java/com/magamochi/common/config/RabbitConfig.java +++ b/src/main/java/com/magamochi/common/config/RabbitConfig.java @@ -3,6 +3,7 @@ package com.magamochi.common.config; import com.magamochi.common.model.enumeration.ContentType; import org.springframework.amqp.core.Binding; import org.springframework.amqp.core.Queue; +import org.springframework.amqp.core.QueueBuilder; import org.springframework.amqp.core.TopicExchange; import org.springframework.amqp.rabbit.connection.ConnectionFactory; import org.springframework.amqp.rabbit.core.RabbitTemplate; @@ -53,27 +54,67 @@ public class RabbitConfig { @Bean public Queue imageFetchQueue() { - return new Queue(imageFetchQueue, false); + return QueueBuilder.nonDurable(imageFetchQueue) + .deadLetterExchange("") + .deadLetterRoutingKey(imageFetchQueue + ".dlq") + .build(); + } + + @Bean + public Queue imageFetchDlq() { + return QueueBuilder.nonDurable(imageFetchQueue + ".dlq").build(); } @Bean public Queue mangaUpdateQueue() { - return new Queue(mangaUpdateQueue, false); + return QueueBuilder.nonDurable(mangaUpdateQueue) + .deadLetterExchange("") + .deadLetterRoutingKey(mangaUpdateQueue + ".dlq") + .build(); + } + + @Bean + public Queue mangaUpdateDlq() { + return QueueBuilder.nonDurable(mangaUpdateQueue + ".dlq").build(); } @Bean public Queue mangaContentImageUpdateQueue() { - return new Queue(mangaContentImageUpdateQueue, false); + return QueueBuilder.nonDurable(mangaContentImageUpdateQueue) + .deadLetterExchange("") + .deadLetterRoutingKey(mangaContentImageUpdateQueue + ".dlq") + .build(); + } + + @Bean + public Queue mangaContentImageUpdateDlq() { + return QueueBuilder.nonDurable(mangaContentImageUpdateQueue + ".dlq").build(); } @Bean public Queue mangaCoverUpdateQueue() { - return new Queue(mangaCoverUpdateQueue, false); + return QueueBuilder.nonDurable(mangaCoverUpdateQueue) + .deadLetterExchange("") + .deadLetterRoutingKey(mangaCoverUpdateQueue + ".dlq") + .build(); + } + + @Bean + public Queue mangaCoverUpdateDlq() { + return QueueBuilder.nonDurable(mangaCoverUpdateQueue + ".dlq").build(); } @Bean public Queue fileImportQueue() { - return new Queue(fileImportQueue, false); + return QueueBuilder.nonDurable(fileImportQueue) + .deadLetterExchange("") + .deadLetterRoutingKey(fileImportQueue + ".dlq") + .build(); + } + + @Bean + public Queue fileImportDlq() { + return QueueBuilder.nonDurable(fileImportQueue + ".dlq").build(); } @Bean @@ -101,22 +142,54 @@ public class RabbitConfig { @Bean public Queue mangaContentIngestQueue() { - return new Queue(mangaContentIngestQueue, false); + return QueueBuilder.nonDurable(mangaContentIngestQueue) + .deadLetterExchange("") + .deadLetterRoutingKey(mangaContentIngestQueue + ".dlq") + .build(); + } + + @Bean + public Queue mangaContentIngestDlq() { + return QueueBuilder.nonDurable(mangaContentIngestQueue + ".dlq").build(); } @Bean public Queue mangaContentImageIngestQueue() { - return new Queue(mangaContentImageIngestQueue, false); + return QueueBuilder.nonDurable(mangaContentImageIngestQueue) + .deadLetterExchange("") + .deadLetterRoutingKey(mangaContentImageIngestQueue + ".dlq") + .build(); + } + + @Bean + public Queue mangaContentImageIngestDlq() { + return QueueBuilder.nonDurable(mangaContentImageIngestQueue + ".dlq").build(); } @Bean public Queue mangaIngestQueue() { - return new Queue(mangaIngestQueue, false); + return QueueBuilder.nonDurable(mangaIngestQueue) + .deadLetterExchange("") + .deadLetterRoutingKey(mangaIngestQueue + ".dlq") + .build(); + } + + @Bean + public Queue mangaIngestDlq() { + return QueueBuilder.nonDurable(mangaIngestQueue + ".dlq").build(); } @Bean public Queue providerPageIngestQueue() { - return new Queue(providerPageIngestQueue, false); + return QueueBuilder.nonDurable(providerPageIngestQueue) + .deadLetterExchange("") + .deadLetterRoutingKey(providerPageIngestQueue + ".dlq") + .build(); + } + + @Bean + public Queue providerPageIngestDlq() { + return QueueBuilder.nonDurable(providerPageIngestQueue + ".dlq").build(); } // TODO: remove unused queues @@ -129,12 +202,28 @@ public class RabbitConfig { @Bean public Queue mangaChapterDownloadQueue() { - return new Queue(mangaChapterDownloadQueue, false); + return QueueBuilder.nonDurable(mangaChapterDownloadQueue) + .deadLetterExchange("") + .deadLetterRoutingKey(mangaChapterDownloadQueue + ".dlq") + .build(); + } + + @Bean + public Queue mangaChapterDownloadDlq() { + return QueueBuilder.nonDurable(mangaChapterDownloadQueue + ".dlq").build(); } @Bean public Queue mangaFollowUpdateChapterQueue() { - return new Queue(mangaFollowUpdateChapterQueue, false); + return QueueBuilder.nonDurable(mangaFollowUpdateChapterQueue) + .deadLetterExchange("") + .deadLetterRoutingKey(mangaFollowUpdateChapterQueue + ".dlq") + .build(); + } + + @Bean + public Queue mangaFollowUpdateChapterDlq() { + return QueueBuilder.nonDurable(mangaFollowUpdateChapterQueue + ".dlq").build(); } @Bean diff --git a/src/main/java/com/magamochi/content/model/repository/MangaImportJobRepository.java b/src/main/java/com/magamochi/content/model/repository/MangaImportJobRepository.java index 7fa8d0c..5b21c7c 100644 --- a/src/main/java/com/magamochi/content/model/repository/MangaImportJobRepository.java +++ b/src/main/java/com/magamochi/content/model/repository/MangaImportJobRepository.java @@ -8,5 +8,5 @@ import org.springframework.stereotype.Repository; @Repository public interface MangaImportJobRepository extends JpaRepository { - List findByStatus(ImportJobStatus status); + List findByStatusOrderByIdAsc(ImportJobStatus importJobStatus); } diff --git a/src/main/java/com/magamochi/content/service/ContentService.java b/src/main/java/com/magamochi/content/service/ContentService.java index d1f9db9..463a40b 100644 --- a/src/main/java/com/magamochi/content/service/ContentService.java +++ b/src/main/java/com/magamochi/content/service/ContentService.java @@ -25,7 +25,7 @@ public class ContentService { var mangaContentProvider = mangaContentProviderService.find(mangaContentProviderId); return mangaContentProvider.getMangaContents().stream() - .sorted(Comparator.comparing(MangaContent::getId)) + .sorted(Comparator.comparing(MangaContent::getTitle)) .map( mangaContent -> { var isRead = userMangaContentReadService.isRead(mangaContent.getId()); diff --git a/src/main/java/com/magamochi/content/task/PendingImportScannerTask.java b/src/main/java/com/magamochi/content/task/PendingImportScannerTask.java index 55175d2..554e713 100644 --- a/src/main/java/com/magamochi/content/task/PendingImportScannerTask.java +++ b/src/main/java/com/magamochi/content/task/PendingImportScannerTask.java @@ -26,7 +26,7 @@ public class PendingImportScannerTask { @Scheduled(fixedDelayString = "${tasks.pending-import-scanner.delay:30000}") public void scanPendingImports() { - var pendingJobs = mangaImportJobRepository.findByStatus(ImportJobStatus.PENDING); + var pendingJobs = mangaImportJobRepository.findByStatusOrderByIdAsc(ImportJobStatus.PENDING); for (var job : pendingJobs) { if (!s3Service.objectExists(job.getS3FileKey())) { diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index e79b09b..f9ee347 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -30,6 +30,9 @@ spring: port: ${RABBITMQ_PORT} username: ${RABBITMQ_USERNAME} password: ${RABBITMQ_PASSWORD} + listener: + simple: + default-requeue-rejected: false springdoc: api-docs: