Skip to content

Commit 9e34510

Browse files
committed
feat(resilience): add Resilience4j circuit breaker and retry for S3
integration - Add resilience4j-spring-boot3 and spring-boot-starter-aop dependencies - Configure CircuitBreaker and Retry instances for S3 in application.yml - Annotate S3Service#uploadFile with @CIRCUITBREAKER and @Retry - Add uploadFallback method with matching signature (MultipartFile, String, String, Exception)
1 parent 2b058d8 commit 9e34510

File tree

3 files changed

+30
-0
lines changed

3 files changed

+30
-0
lines changed

build.gradle

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ ext {
6464
shedlockVersion = "6.9.1"
6565
otelVersion = "1.7.0-M3"
6666
openTelemetryVersion = "2.25.0"
67+
aopVersion = "4.0.0-M2"
68+
resilience4jVersion = "2.3.0"
6769
}
6870

6971
dependencies {
@@ -135,6 +137,10 @@ dependencies {
135137

136138
// Source: https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-zipkin
137139
implementation 'org.springframework.boot:spring-boot-starter-zipkin'
140+
141+
// Source: https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop
142+
implementation "org.springframework.boot:spring-boot-starter-aop:${aopVersion}"
143+
implementation "io.github.resilience4j:resilience4j-spring-boot3:${resilience4jVersion}"
138144
}
139145

140146
// ─────────────────────────────────────────────

src/main/java/com/example/library/aws/S3Service.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
import org.springframework.stereotype.Service;
1313
import org.springframework.web.multipart.MultipartFile;
1414

15+
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
16+
import io.github.resilience4j.retry.annotation.Retry;
17+
1518
import software.amazon.awssdk.awscore.exception.AwsServiceException;
1619
import software.amazon.awssdk.core.exception.SdkClientException;
1720
import software.amazon.awssdk.core.sync.RequestBody;
@@ -51,6 +54,8 @@ public class S3Service {
5154
@Value("${s3.bucket}")
5255
private String bucketName;
5356

57+
@CircuitBreaker(name = "s3", fallbackMethod = "uploadFallback")
58+
@Retry(name = "s3")
5459
public URI uploadFile(MultipartFile file, String folder, String fileName) {
5560

5661
validateFileSize(file);
@@ -94,7 +99,12 @@ public URI uploadFile(MultipartFile file, String folder, String fileName) {
9499
} catch (Exception _) {
95100
throw new URIException();
96101
}
102+
}
97103

104+
@SuppressWarnings("unused")
105+
private URI uploadFallback(MultipartFile file, String folder, String fileName, Exception ex) {
106+
log.error("S3 circuit breaker open or retry exhausted | reason={}", ex.getMessage());
107+
throw new AmazonClientException();
98108
}
99109

100110
private void validateContentType(MultipartFile file) {

src/main/resources/application.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,17 @@ aws:
3232
s3:
3333
bucket: ${BUCKET_NAME:library-api-s3}
3434
region: ${BUCKET_REGION:sa-east-1}
35+
36+
resilience4j:
37+
circuitbreaker:
38+
instances:
39+
s3:
40+
sliding-window-size: 5
41+
failure-rate-threshold: 50
42+
wait-duration-in-open-state: 10s
43+
44+
retry:
45+
instances:
46+
s3:
47+
max-attempts: 3
48+
wait-duration: 500ms

0 commit comments

Comments
 (0)