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}")
|
@Value("${queues.image-fetch}")
|
||||||
private String imageFetchQueue;
|
private String imageFetchQueue;
|
||||||
|
|
||||||
|
@Value("${queues.manga-content-image-delete}")
|
||||||
|
private String mangaContentImageDeleteQueue;
|
||||||
|
|
||||||
@Value("${queues.file-import}")
|
@Value("${queues.file-import}")
|
||||||
private String fileImportQueue;
|
private String fileImportQueue;
|
||||||
|
|
||||||
@ -49,6 +52,9 @@ public class RabbitConfig {
|
|||||||
@Value("${routing-key.image-update}")
|
@Value("${routing-key.image-update}")
|
||||||
private String imageUpdateRoutingKey;
|
private String imageUpdateRoutingKey;
|
||||||
|
|
||||||
|
@Value("${routing-key.image-delete}")
|
||||||
|
private String imageDeleteRoutingKey;
|
||||||
|
|
||||||
@Value("${queues.manga-content-download}")
|
@Value("${queues.manga-content-download}")
|
||||||
private String mangaContentDownloadQueue;
|
private String mangaContentDownloadQueue;
|
||||||
|
|
||||||
@ -102,6 +108,20 @@ public class RabbitConfig {
|
|||||||
return QueueBuilder.durable(mangaContentImageUpdateQueue + ".dlq").quorum().build();
|
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
|
@Bean
|
||||||
public Queue mangaCoverUpdateQueue() {
|
public Queue mangaCoverUpdateQueue() {
|
||||||
return QueueBuilder.durable(mangaCoverUpdateQueue)
|
return QueueBuilder.durable(mangaCoverUpdateQueue)
|
||||||
@ -153,6 +173,18 @@ public class RabbitConfig {
|
|||||||
null);
|
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
|
@Bean
|
||||||
public Queue mangaContentIngestQueue() {
|
public Queue mangaContentIngestQueue() {
|
||||||
return QueueBuilder.durable(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);
|
var image = imageService.find(imageId);
|
||||||
mangaContentImage.setImage(image);
|
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.exception.ExcludedImageException;
|
||||||
import com.magamochi.common.queue.command.ImageFetchCommand;
|
import com.magamochi.common.queue.command.ImageFetchCommand;
|
||||||
import com.magamochi.common.queue.command.ImageUpdateCommand;
|
import com.magamochi.common.queue.command.ImageUpdateCommand;
|
||||||
|
import com.magamochi.common.queue.command.MangaContentImageDeleteCommand;
|
||||||
import com.magamochi.image.queue.producer.ImageUpdateProducer;
|
import com.magamochi.image.queue.producer.ImageUpdateProducer;
|
||||||
|
import com.magamochi.common.model.enumeration.ContentType;
|
||||||
import com.magamochi.image.service.ImageFetchService;
|
import com.magamochi.image.service.ImageFetchService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
@ -17,7 +19,7 @@ public class ImageFetchConsumer {
|
|||||||
private final ImageFetchService imageFetchService;
|
private final ImageFetchService imageFetchService;
|
||||||
private final ImageUpdateProducer imageUpdateProducer;
|
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) {
|
public void receiveImageFetchCommand(ImageFetchCommand command) {
|
||||||
log.info("Received image fetch command: {}", command);
|
log.info("Received image fetch command: {}", command);
|
||||||
|
|
||||||
@ -28,6 +30,12 @@ public class ImageFetchConsumer {
|
|||||||
new ImageUpdateCommand(command.entityId(), imageId), command.contentType());
|
new ImageUpdateCommand(command.entityId(), imageId), command.contentType());
|
||||||
} catch (ExcludedImageException e) {
|
} catch (ExcludedImageException e) {
|
||||||
log.info("Image at URL {} is excluded from upload, skipping.", command.url());
|
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) {
|
} catch (Exception e) {
|
||||||
log.error("Failed to fetch image from URL.", 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.model.enumeration.ContentType;
|
||||||
import com.magamochi.common.queue.command.ImageUpdateCommand;
|
import com.magamochi.common.queue.command.ImageUpdateCommand;
|
||||||
|
import com.magamochi.common.queue.command.MangaContentImageDeleteCommand;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||||
@ -20,9 +21,18 @@ public class ImageUpdateProducer {
|
|||||||
@Value("${routing-key.image-update}")
|
@Value("${routing-key.image-update}")
|
||||||
private String imageUpdateRoutingKey;
|
private String imageUpdateRoutingKey;
|
||||||
|
|
||||||
|
@Value("${routing-key.image-delete}")
|
||||||
|
private String imageDeleteRoutingKey;
|
||||||
|
|
||||||
public void publishImageUpdateCommand(ImageUpdateCommand command, ContentType contentType) {
|
public void publishImageUpdateCommand(ImageUpdateCommand command, ContentType contentType) {
|
||||||
var routingKey = String.format(imageUpdateRoutingKey + ".%s", contentType.name().toLowerCase());
|
var routingKey = String.format(imageUpdateRoutingKey + ".%s", contentType.name().toLowerCase());
|
||||||
|
|
||||||
rabbitTemplate.convertAndSend(imageUpdatesTopic, routingKey, command);
|
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-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-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-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}
|
provider-page-ingest: ${PROVIDER_PAGE_INGEST_QUEUE:mangamochi.provider.page.ingest}
|
||||||
image-fetch: ${IMAGE_FETCH_QUEUE:mangamochi.image.fetch}
|
image-fetch: ${IMAGE_FETCH_QUEUE:mangamochi.image.fetch}
|
||||||
manga-cover-update: ${MANGA_COVER_UDPATE_QUEUE:mangamochi.manga.cover.update}
|
manga-cover-update: ${MANGA_COVER_UDPATE_QUEUE:mangamochi.manga.cover.update}
|
||||||
@ -86,6 +87,7 @@ queues:
|
|||||||
|
|
||||||
routing-key:
|
routing-key:
|
||||||
image-update: ${IMAGE_UPDATE_ROUTING_KEY:mangamochi.image.update}
|
image-update: ${IMAGE_UPDATE_ROUTING_KEY:mangamochi.image.update}
|
||||||
|
image-delete: ${IMAGE_DELETE_ROUTING_KEY:mangamochi.image.delete}
|
||||||
|
|
||||||
image-service:
|
image-service:
|
||||||
clean-up-enabled: ${IMAGE_SERVICE_CLEAN_UP_ENABLED:false}
|
clean-up-enabled: ${IMAGE_SERVICE_CLEAN_UP_ENABLED:false}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user