From 3c8038041b2b1a37896c4780a1e73adcaeba7d40 Mon Sep 17 00:00:00 2001 From: Rodrigo Verdiani Date: Sat, 28 Mar 2026 16:11:28 -0300 Subject: [PATCH] refactor: improve image fetching with retry mechanism and error handling --- .../queue/consumer/ImageFetchConsumer.java | 9 ++++--- .../image/service/ImageFetchService.java | 27 +++++++++++-------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/magamochi/image/queue/consumer/ImageFetchConsumer.java b/src/main/java/com/magamochi/image/queue/consumer/ImageFetchConsumer.java index 1ea2b3f..8735e10 100644 --- a/src/main/java/com/magamochi/image/queue/consumer/ImageFetchConsumer.java +++ b/src/main/java/com/magamochi/image/queue/consumer/ImageFetchConsumer.java @@ -1,7 +1,5 @@ package com.magamochi.image.queue.consumer; -import static java.util.Objects.nonNull; - import com.magamochi.common.queue.command.ImageFetchCommand; import com.magamochi.common.queue.command.ImageUpdateCommand; import com.magamochi.image.queue.producer.ImageUpdateProducer; @@ -22,10 +20,13 @@ public class ImageFetchConsumer { public void receiveImageFetchCommand(ImageFetchCommand command) { log.info("Received image fetch command: {}", command); - var imageId = imageFetchService.fetchImage(command.url(), command.contentType()); - if (nonNull(imageId)) { + try { + var imageId = imageFetchService.fetchImage(command.url(), command.contentType()); + imageUpdateProducer.publishImageUpdateCommand( new ImageUpdateCommand(command.entityId(), imageId), command.contentType()); + } catch (Exception e) { + log.error("Failed to fetch image from URL.", e); } } } diff --git a/src/main/java/com/magamochi/image/service/ImageFetchService.java b/src/main/java/com/magamochi/image/service/ImageFetchService.java index d522cff..4849a0c 100644 --- a/src/main/java/com/magamochi/image/service/ImageFetchService.java +++ b/src/main/java/com/magamochi/image/service/ImageFetchService.java @@ -4,6 +4,7 @@ import static java.util.Objects.nonNull; import com.google.common.util.concurrent.RateLimiter; import com.magamochi.common.model.enumeration.ContentType; +import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; @@ -14,6 +15,7 @@ import java.util.UUID; import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; import org.apache.tika.Tika; +import org.springframework.resilience.annotation.Retryable; import org.springframework.stereotype.Service; @Log4j2 @@ -28,20 +30,23 @@ public class ImageFetchService { HttpClient.newBuilder().followRedirects(HttpClient.Redirect.NORMAL).build(); private final Tika tika = new Tika(); - public UUID fetchImage(String imageUrl, ContentType contentType) { - try { - var request = HttpRequest.newBuilder(URI.create(imageUrl.trim())).GET().build(); + @Retryable( + maxRetries = 5, + delay = 1000, + multiplier = 2, + maxDelay = 5000, + includes = Exception.class, + excludes = NoSuchAlgorithmException.class) + public UUID fetchImage(String imageUrl, ContentType contentType) + throws IOException, InterruptedException, NoSuchAlgorithmException { + var request = HttpRequest.newBuilder(URI.create(imageUrl.trim())).GET().build(); - imageDownloadRateLimiter.acquire(); - var response = httpClient.send(request, HttpResponse.BodyHandlers.ofByteArray()); + imageDownloadRateLimiter.acquire(); + var response = httpClient.send(request, HttpResponse.BodyHandlers.ofByteArray()); - var imageBytes = response.body(); + var imageBytes = response.body(); - return uploadImage(imageBytes, response, contentType); - } catch (Exception e) { - log.error("Failed to fetch image from URL: {}", imageUrl, e); - return null; - } + return uploadImage(imageBytes, response, contentType); } public UUID uploadImage(