feat: add manga content image deletion functionality with RabbitMQ integration
This commit is contained in:
parent
b388bf3740
commit
22a905220e
@ -40,6 +40,9 @@ public class RabbitConfig {
|
||||
@Value("${queues.image-fetch}")
|
||||
private String imageFetchQueue;
|
||||
|
||||
@Value("${queues.manga-content-image-delete}")
|
||||
private String mangaContentImageDeleteQueue;
|
||||
|
||||
@Value("${queues.file-import}")
|
||||
private String fileImportQueue;
|
||||
|
||||
@ -49,6 +52,9 @@ public class RabbitConfig {
|
||||
@Value("${routing-key.image-update}")
|
||||
private String imageUpdateRoutingKey;
|
||||
|
||||
@Value("${routing-key.image-delete}")
|
||||
private String imageDeleteRoutingKey;
|
||||
|
||||
@Value("${queues.manga-content-download}")
|
||||
private String mangaContentDownloadQueue;
|
||||
|
||||
@ -102,6 +108,20 @@ public class RabbitConfig {
|
||||
return QueueBuilder.durable(mangaContentImageUpdateQueue + ".dlq").quorum().build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Queue mangaContentImageDeleteQueue() {
|
||||
return QueueBuilder.durable(mangaContentImageDeleteQueue)
|
||||
.quorum()
|
||||
.deadLetterExchange("")
|
||||
.deadLetterRoutingKey(mangaContentImageDeleteQueue + ".dlq")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Queue mangaContentImageDeleteDlq() {
|
||||
return QueueBuilder.durable(mangaContentImageDeleteQueue + ".dlq").quorum().build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Queue mangaCoverUpdateQueue() {
|
||||
return QueueBuilder.durable(mangaCoverUpdateQueue)
|
||||
@ -153,6 +173,18 @@ public class RabbitConfig {
|
||||
null);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Binding bindingMangaContentImageDeleteQueue(
|
||||
Queue mangaContentImageDeleteQueue, TopicExchange imageUpdatesExchange) {
|
||||
return new Binding(
|
||||
mangaContentImageDeleteQueue.getName(),
|
||||
Binding.DestinationType.QUEUE,
|
||||
imageUpdatesExchange.getName(),
|
||||
String.format(
|
||||
imageDeleteRoutingKey + ".%s", ContentType.CONTENT_IMAGE.name().toLowerCase()),
|
||||
null);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Queue mangaContentIngestQueue() {
|
||||
return QueueBuilder.durable(mangaContentIngestQueue)
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
package com.magamochi.common.queue.command;
|
||||
|
||||
public record MangaContentImageDeleteCommand(long entityId) {}
|
||||
@ -0,0 +1,22 @@
|
||||
package com.magamochi.content.queue.consumer;
|
||||
|
||||
import com.magamochi.common.queue.command.MangaContentImageDeleteCommand;
|
||||
import com.magamochi.content.service.ContentIngestService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Log4j2
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class MangaContentImageDeleteConsumer {
|
||||
private final ContentIngestService contentIngestService;
|
||||
|
||||
@RabbitListener(queues = "${queues.manga-content-image-delete}")
|
||||
public void receiveMangaContentImageDeleteCommand(MangaContentImageDeleteCommand command) {
|
||||
log.info("Received manga content image delete command: {}", command);
|
||||
|
||||
contentIngestService.deleteMangaContentImage(command.entityId());
|
||||
}
|
||||
}
|
||||
@ -119,4 +119,10 @@ public class ContentIngestService {
|
||||
var image = imageService.find(imageId);
|
||||
mangaContentImage.setImage(image);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteMangaContentImage(long mangaContentImageId) {
|
||||
mangaContentImageRepository.deleteById(mangaContentImageId);
|
||||
log.info("Deleted Manga Content Image entity with ID {}", mangaContentImageId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,9 @@ package com.magamochi.image.queue.consumer;
|
||||
import com.magamochi.common.exception.ExcludedImageException;
|
||||
import com.magamochi.common.queue.command.ImageFetchCommand;
|
||||
import com.magamochi.common.queue.command.ImageUpdateCommand;
|
||||
import com.magamochi.common.queue.command.MangaContentImageDeleteCommand;
|
||||
import com.magamochi.image.queue.producer.ImageUpdateProducer;
|
||||
import com.magamochi.common.model.enumeration.ContentType;
|
||||
import com.magamochi.image.service.ImageFetchService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
@ -17,7 +19,7 @@ public class ImageFetchConsumer {
|
||||
private final ImageFetchService imageFetchService;
|
||||
private final ImageUpdateProducer imageUpdateProducer;
|
||||
|
||||
@RabbitListener(queues = "${queues.image-fetch}")
|
||||
@RabbitListener(queues = "${queues.image-fetch}", concurrency = "${queues.image-fetch-concurrency:5-10}")
|
||||
public void receiveImageFetchCommand(ImageFetchCommand command) {
|
||||
log.info("Received image fetch command: {}", command);
|
||||
|
||||
@ -28,6 +30,12 @@ public class ImageFetchConsumer {
|
||||
new ImageUpdateCommand(command.entityId(), imageId), command.contentType());
|
||||
} catch (ExcludedImageException e) {
|
||||
log.info("Image at URL {} is excluded from upload, skipping.", command.url());
|
||||
|
||||
if (ContentType.CONTENT_IMAGE.equals(command.contentType())) {
|
||||
log.info("Deleting excluded manga content image entity for ID {}.", command.entityId());
|
||||
imageUpdateProducer.publishImageDeleteCommand(
|
||||
new MangaContentImageDeleteCommand(command.entityId()), command.contentType());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to fetch image from URL.", e);
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package com.magamochi.image.queue.producer;
|
||||
|
||||
import com.magamochi.common.model.enumeration.ContentType;
|
||||
import com.magamochi.common.queue.command.ImageUpdateCommand;
|
||||
import com.magamochi.common.queue.command.MangaContentImageDeleteCommand;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
@ -20,9 +21,18 @@ public class ImageUpdateProducer {
|
||||
@Value("${routing-key.image-update}")
|
||||
private String imageUpdateRoutingKey;
|
||||
|
||||
@Value("${routing-key.image-delete}")
|
||||
private String imageDeleteRoutingKey;
|
||||
|
||||
public void publishImageUpdateCommand(ImageUpdateCommand command, ContentType contentType) {
|
||||
var routingKey = String.format(imageUpdateRoutingKey + ".%s", contentType.name().toLowerCase());
|
||||
|
||||
rabbitTemplate.convertAndSend(imageUpdatesTopic, routingKey, command);
|
||||
}
|
||||
|
||||
public void publishImageDeleteCommand(MangaContentImageDeleteCommand command, ContentType contentType) {
|
||||
var routingKey = String.format(imageDeleteRoutingKey + ".%s", contentType.name().toLowerCase());
|
||||
|
||||
rabbitTemplate.convertAndSend(imageUpdatesTopic, routingKey, command);
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,6 +77,7 @@ queues:
|
||||
manga-content-ingest: ${MANGA_CONTENT_INGEST_QUEUE:mangamochi.manga.content.ingest}
|
||||
manga-content-image-ingest: ${MANGA_CONTENT_IMAGE_INGEST_QUEUE:mangamochi.manga.content.image.ingest}
|
||||
manga-content-image-update: ${MANGA_CONTENT_IMAGE_UPDATE_QUEUE:mangamochi.manga.content.image.update}
|
||||
manga-content-image-delete: ${MANGA_CONTENT_IMAGE_DELETE_QUEUE:mangamochi.manga.content.image.delete}
|
||||
provider-page-ingest: ${PROVIDER_PAGE_INGEST_QUEUE:mangamochi.provider.page.ingest}
|
||||
image-fetch: ${IMAGE_FETCH_QUEUE:mangamochi.image.fetch}
|
||||
manga-cover-update: ${MANGA_COVER_UDPATE_QUEUE:mangamochi.manga.cover.update}
|
||||
@ -86,6 +87,7 @@ queues:
|
||||
|
||||
routing-key:
|
||||
image-update: ${IMAGE_UPDATE_ROUTING_KEY:mangamochi.image.update}
|
||||
image-delete: ${IMAGE_DELETE_ROUTING_KEY:mangamochi.image.delete}
|
||||
|
||||
image-service:
|
||||
clean-up-enabled: ${IMAGE_SERVICE_CLEAN_UP_ENABLED:false}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user