Merge pull request 'refactor: add retry mechanism to Feign clients for improved resilience' (#36) from refactor-architecture into main
Reviewed-on: #36
This commit is contained in:
commit
baeffd6f15
@ -3,15 +3,28 @@ package com.magamochi.catalog.client;
|
|||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
|
import org.springframework.resilience.annotation.Retryable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
|
||||||
@FeignClient(name = "aniList", url = "https://graphql.anilist.co")
|
@FeignClient(name = "aniList", url = "https://graphql.anilist.co")
|
||||||
public interface AniListClient {
|
public interface AniListClient {
|
||||||
@PostMapping
|
@PostMapping
|
||||||
|
@Retryable(
|
||||||
|
maxRetries = 5,
|
||||||
|
delay = 1000,
|
||||||
|
multiplier = 2,
|
||||||
|
maxDelay = 5000,
|
||||||
|
includes = Exception.class)
|
||||||
MangaResponse getManga(@RequestBody GraphQLRequest request);
|
MangaResponse getManga(@RequestBody GraphQLRequest request);
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
|
@Retryable(
|
||||||
|
maxRetries = 5,
|
||||||
|
delay = 1000,
|
||||||
|
multiplier = 2,
|
||||||
|
maxDelay = 5000,
|
||||||
|
includes = Exception.class)
|
||||||
MangaSearchResponse searchManga(@RequestBody SearchGraphQLRequest request);
|
MangaSearchResponse searchManga(@RequestBody SearchGraphQLRequest request);
|
||||||
|
|
||||||
record GraphQLRequest(String query, Variables variables) {
|
record GraphQLRequest(String query, Variables variables) {
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package com.magamochi.catalog.client;
|
|||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
|
import org.springframework.resilience.annotation.Retryable;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
@ -10,9 +11,21 @@ import org.springframework.web.bind.annotation.RequestParam;
|
|||||||
@FeignClient(name = "jikan", url = "https://api.jikan.moe/v4/manga")
|
@FeignClient(name = "jikan", url = "https://api.jikan.moe/v4/manga")
|
||||||
public interface JikanClient {
|
public interface JikanClient {
|
||||||
@GetMapping
|
@GetMapping
|
||||||
|
@Retryable(
|
||||||
|
maxRetries = 3,
|
||||||
|
delay = 1000,
|
||||||
|
multiplier = 2,
|
||||||
|
maxDelay = 5000,
|
||||||
|
includes = Exception.class)
|
||||||
SearchResponse mangaSearch(@RequestParam String q);
|
SearchResponse mangaSearch(@RequestParam String q);
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
|
@Retryable(
|
||||||
|
maxRetries = 3,
|
||||||
|
delay = 1000,
|
||||||
|
multiplier = 2,
|
||||||
|
maxDelay = 5000,
|
||||||
|
includes = Exception.class)
|
||||||
MangaResponse getMangaById(@PathVariable Long id);
|
MangaResponse getMangaById(@PathVariable Long id);
|
||||||
|
|
||||||
record SearchResponse(List<MangaData> data) {
|
record SearchResponse(List<MangaData> data) {
|
||||||
|
|||||||
@ -4,18 +4,37 @@ import com.magamochi.model.dto.MangaDexMangaDTO;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
|
import org.springframework.resilience.annotation.Retryable;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@FeignClient(name = "mangaDex", url = "https://api.mangadex.org")
|
@FeignClient(name = "mangaDex", url = "https://api.mangadex.org")
|
||||||
public interface MangaDexClient {
|
public interface MangaDexClient {
|
||||||
@GetMapping("/manga/{id}")
|
@GetMapping("/manga/{id}")
|
||||||
|
@Retryable(
|
||||||
|
maxRetries = 3,
|
||||||
|
delay = 1000,
|
||||||
|
multiplier = 2,
|
||||||
|
maxDelay = 5000,
|
||||||
|
includes = Exception.class)
|
||||||
MangaDexMangaDTO getManga(@PathVariable UUID id);
|
MangaDexMangaDTO getManga(@PathVariable UUID id);
|
||||||
|
|
||||||
@GetMapping("/manga/{id}/feed")
|
@GetMapping("/manga/{id}/feed")
|
||||||
|
@Retryable(
|
||||||
|
maxRetries = 3,
|
||||||
|
delay = 1000,
|
||||||
|
multiplier = 2,
|
||||||
|
maxDelay = 5000,
|
||||||
|
includes = Exception.class)
|
||||||
MangaDexMangaFeedDTO getMangaFeed(
|
MangaDexMangaFeedDTO getMangaFeed(
|
||||||
@PathVariable UUID id, @RequestParam("contentRating[]") List<String> contentRating);
|
@PathVariable UUID id, @RequestParam("contentRating[]") List<String> contentRating);
|
||||||
|
|
||||||
@GetMapping("/manga/{id}/feed")
|
@GetMapping("/manga/{id}/feed")
|
||||||
|
@Retryable(
|
||||||
|
maxRetries = 3,
|
||||||
|
delay = 1000,
|
||||||
|
multiplier = 2,
|
||||||
|
maxDelay = 5000,
|
||||||
|
includes = Exception.class)
|
||||||
MangaDexMangaFeedDTO getMangaFeed(
|
MangaDexMangaFeedDTO getMangaFeed(
|
||||||
@PathVariable UUID id,
|
@PathVariable UUID id,
|
||||||
@RequestParam int limit,
|
@RequestParam int limit,
|
||||||
@ -23,6 +42,12 @@ public interface MangaDexClient {
|
|||||||
@RequestParam("contentRating[]") List<String> contentRating);
|
@RequestParam("contentRating[]") List<String> contentRating);
|
||||||
|
|
||||||
@GetMapping("/at-home/server/{chapterId}")
|
@GetMapping("/at-home/server/{chapterId}")
|
||||||
|
@Retryable(
|
||||||
|
maxRetries = 3,
|
||||||
|
delay = 1000,
|
||||||
|
multiplier = 2,
|
||||||
|
maxDelay = 5000,
|
||||||
|
includes = Exception.class)
|
||||||
MangaChapterDataDTO getMangaChapter(@PathVariable UUID chapterId);
|
MangaChapterDataDTO getMangaChapter(@PathVariable UUID chapterId);
|
||||||
|
|
||||||
record MangaDexMangaFeedDTO(
|
record MangaDexMangaFeedDTO(
|
||||||
|
|||||||
@ -2,11 +2,18 @@ package com.magamochi.client;
|
|||||||
|
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.resilience.annotation.Retryable;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@FeignClient(name = "ntfy", url = "${ntfy.endpoint}")
|
@FeignClient(name = "ntfy", url = "${ntfy.endpoint}")
|
||||||
public interface NtfyClient {
|
public interface NtfyClient {
|
||||||
@PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
|
@PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
@Retryable(
|
||||||
|
maxRetries = 3,
|
||||||
|
delay = 1000,
|
||||||
|
multiplier = 2,
|
||||||
|
maxDelay = 5000,
|
||||||
|
includes = Exception.class)
|
||||||
void notify(@RequestBody Request dto);
|
void notify(@RequestBody Request dto);
|
||||||
|
|
||||||
record Request(String topic, String message, String title) {}
|
record Request(String topic, String message, String title) {}
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
package com.magamochi.image.queue.consumer;
|
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.ImageFetchCommand;
|
||||||
import com.magamochi.common.queue.command.ImageUpdateCommand;
|
import com.magamochi.common.queue.command.ImageUpdateCommand;
|
||||||
import com.magamochi.image.queue.producer.ImageUpdateProducer;
|
import com.magamochi.image.queue.producer.ImageUpdateProducer;
|
||||||
@ -21,8 +23,9 @@ public class ImageFetchConsumer {
|
|||||||
log.info("Received image fetch command: {}", command);
|
log.info("Received image fetch command: {}", command);
|
||||||
|
|
||||||
var imageId = imageFetchService.fetchImage(command.url(), command.contentType());
|
var imageId = imageFetchService.fetchImage(command.url(), command.contentType());
|
||||||
|
if (nonNull(imageId)) {
|
||||||
imageUpdateProducer.publishImageUpdateCommand(
|
imageUpdateProducer.publishImageUpdateCommand(
|
||||||
new ImageUpdateCommand(command.entityId(), imageId), command.contentType());
|
new ImageUpdateCommand(command.entityId(), imageId), command.contentType());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user