Skip to content

Commit

Permalink
refactor: CompletableFuture 이미지 업로드 예외 처리 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
Arachneee committed Nov 7, 2024
1 parent 66c4011 commit 784a400
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import server.haengdong.application.request.EventAppRequest;
import server.haengdong.application.request.EventLoginAppRequest;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -39,12 +40,12 @@ public List<String> uploadImages(List<MultipartFile> images) {
.map(image -> CompletableFuture.supplyAsync(() -> uploadImage(image), executorService))
.toList();

CompletableFuture<List<String>> result = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
.thenApply(v -> futures.stream()
.map(this::getFuture)
.toList());

return result.join();
try {
CompletableFuture<List<String>> result = collectUploadResults(futures);
return result.join();
} catch (CompletionException e) {
throw new HaengdongException(HaengdongErrorCode.IMAGE_UPLOAD_FAIL, e);
}
}

private String uploadImage(MultipartFile image) {
Expand All @@ -71,7 +72,14 @@ private String uploadImageToStorage(InputStream inputStream, MultipartFile image
return imageName;
}

private String getFuture(CompletableFuture<String> future) {
private CompletableFuture<List<String>> collectUploadResults(List<CompletableFuture<String>> futures) {
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
.thenApply(v -> futures.stream()
.map(this::resolveFuture)
.toList());
}

private String resolveFuture(CompletableFuture<String> future) {
try {
return future.get();
} catch (InterruptedException | ExecutionException e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package server.haengdong.application;

import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.awaitility.Awaitility.given;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.when;

import java.util.List;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import server.haengdong.exception.HaengdongException;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.S3Exception;


class ImageServiceTest extends ServiceTestSupport {

@Autowired
private ImageService imageService;

@MockBean
private S3Client s3Client;

@DisplayName("이미지 업로드 도중 실패하면 예외가 커스텀 예외가 발생한다.")
@Test
void uploadImages() {
MultipartFile multipartFile1 = new MockMultipartFile("file1", "test1.txt", "text/plain", "hello1".getBytes());
MultipartFile multipartFile2 = new MockMultipartFile("file2", "test2.txt", "text/plain", "hello2".getBytes());
MultipartFile multipartFile3 = new MockMultipartFile("file3", "test3.txt", "text/plain", "hello3".getBytes());
MultipartFile multipartFile4 = new MockMultipartFile("file4", "test4.txt", "text/plain", "hello4".getBytes());
MultipartFile multipartFile5 = new MockMultipartFile("file5", "test5.txt", "text/plain", "hello5".getBytes());

doThrow(new RuntimeException("S3 upload failed"))
.when(s3Client).putObject(any(PutObjectRequest.class), any(RequestBody.class));

assertThatThrownBy(() -> imageService.uploadImages(List.of(multipartFile1, multipartFile2, multipartFile3, multipartFile4, multipartFile5)))
.isInstanceOf(HaengdongException.class);
}
}

0 comments on commit 784a400

Please sign in to comment.