Skip to content

Commit

Permalink
refactor: 이미지 업로드/삭제 작업을 병렬로 수행하도록 수정
Browse files Browse the repository at this point in the history
  • Loading branch information
amaran-th committed Dec 6, 2023
1 parent e9fe5b9 commit 17ed8f6
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
Expand Down Expand Up @@ -40,21 +41,32 @@ public S3Client(
}

public List<String> uploadImages(final List<MultipartFile> multipartFiles) {
return multipartFiles.stream().map(this::uploadImage)
final AtomicBoolean catchException = new AtomicBoolean(false);

final List<String> uploadedImageNames = multipartFiles.stream()
.parallel()
.map(file -> uploadImage(file, catchException))
.filter(Objects::nonNull)
.collect(Collectors.toList());
if (catchException.get()) {
deleteImages(uploadedImageNames);
throw new ImageException(ImageExceptionType.FAIL_S3_UPLOAD_IMAGE);
}
return uploadedImageNames;
}

public String uploadImage(final MultipartFile file) {
public String uploadImage(final MultipartFile file, final AtomicBoolean catchException) {
final String fileExtension = extractFileExtension(file);
final String newFileName = UUID.randomUUID().toString().concat(fileExtension);
final ObjectMetadata objectMetadata = configureObjectMetadata(file);

try (final InputStream inputStream = file.getInputStream()) {
amazonS3.putObject(new PutObjectRequest(bucket, newFileName, inputStream, objectMetadata));
return newFileName;
} catch (final IOException | SdkClientException exception) {
throw new ImageException(ImageExceptionType.FAIL_S3_UPLOAD_IMAGE);
catchException.set(true);
return null;
}
return newFileName;
}

private String extractFileExtension(final MultipartFile file) {
Expand Down Expand Up @@ -82,8 +94,10 @@ private ObjectMetadata configureObjectMetadata(final MultipartFile file) {

public void deleteImages(final List<String> fileNames) {
try {
fileNames.forEach(fileName ->
amazonS3.deleteObject(new DeleteObjectRequest(bucket, fileName)));
fileNames.stream()
.parallel()
.forEach(fileName ->
amazonS3.deleteObject(new DeleteObjectRequest(bucket, fileName)));
} catch (SdkClientException exception) {
throw new ImageException(ImageExceptionType.FAIL_S3_DELETE_IMAGE);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.emmsale.member.exception.MemberException;
import com.emmsale.member.exception.MemberExceptionType;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
Expand Down Expand Up @@ -51,7 +52,7 @@ public MemberImageResponse updateMemberProfile(
s3Client.deleteImages(List.of(imageName));
}

final String imageName = s3Client.uploadImage(image);
final String imageName = s3Client.uploadImage(image, new AtomicBoolean(false));
final String imageUrl = s3Client.convertImageUrl(imageName);
member.updateProfile(imageUrl);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
Expand Down Expand Up @@ -146,7 +148,7 @@ class UpdateProfile {
@BeforeEach
void setUp() {
ReflectionTestUtils.setField(s3Client, "bucket", bucket);
when(s3Client.uploadImage(image)).thenReturn(imageName);
when(s3Client.uploadImage(eq(image), any())).thenReturn(imageName);
when(s3Client.convertImageUrl(anyString())).thenCallRealMethod();
when(s3Client.convertImageName(anyString())).thenCallRealMethod();
}
Expand All @@ -166,7 +168,7 @@ void pastGithubUrl() {
() -> assertThat(member.getImageUrl())
.isEqualTo(s3Client.convertImageUrl(imageName)),
() -> verify(s3Client, times(1))
.uploadImage(image)
.uploadImage(eq(image), any())
);
}

Expand All @@ -186,7 +188,7 @@ void pastCustomImage() {
() -> assertThat(member.getImageUrl())
.isEqualTo(s3Client.convertImageUrl(imageName)),
() -> verify(s3Client, times(1))
.uploadImage(image),
.uploadImage(eq(image), any()),
() -> verify(s3Client, times(1))
.deleteImages(anyList())
);
Expand Down

0 comments on commit 17ed8f6

Please sign in to comment.