Skip to content

Commit

Permalink
refactor: S3 에서 이미지를 삭제하는 로직을 비동기적으로 동작하도록 수정한다. (#445)
Browse files Browse the repository at this point in the history
* chore: asyncImageRemoverExecutor 를 설정한다.

* refactor: handleImageDeletionEvent 에 asyncImageRemoverExecutor 를 적용한다.
  • Loading branch information
pushedrumex authored Dec 27, 2023
1 parent 307d604 commit f49064d
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.clova.anifriends.domain.common.ImageRemover;
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener;
Expand All @@ -12,6 +13,7 @@ public class ImageDeletionListener {

private final ImageRemover imageRemover;

@Async("asyncImageRemoverExecutor")
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void handleImageDeletionEvent(ImageDeletionEvent imageDeletionEvent) {
imageRemover.deleteImages(imageDeletionEvent.imageUrls());
Expand Down
23 changes: 23 additions & 0 deletions src/main/java/com/clova/anifriends/global/config/AsyncConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.clova.anifriends.global.config;

import java.util.concurrent.Executor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@EnableAsync
@Configuration
public class AsyncConfig {

@Bean(name = "asyncImageRemoverExecutor")
public Executor asyncImageRemoverExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(10);
taskExecutor.setMaxPoolSize(30);
taskExecutor.setQueueCapacity(100);
taskExecutor.setThreadNamePrefix("Executor-");
return taskExecutor;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.event.ApplicationEvents;
import org.springframework.test.context.event.RecordApplicationEvents;

@SpringBootTest
@RecordApplicationEvents
@Import({SecurityConfig.class, RedisConfig.class})
public abstract class BaseIntegrationTest extends TestContainerStarter {

Expand All @@ -32,6 +35,9 @@ public abstract class BaseIntegrationTest extends TestContainerStarter {
@Autowired
DatabaseCleaner databaseCleaner;

@Autowired
protected ApplicationEvents events;

@Autowired
protected VolunteerRepository volunteerRepository;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package com.clova.anifriends.domain.animal.service;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import com.clova.anifriends.base.BaseIntegrationTest;
import com.clova.anifriends.domain.animal.Animal;
Expand All @@ -20,6 +18,7 @@
import com.clova.anifriends.domain.animal.vo.AnimalGender;
import com.clova.anifriends.domain.animal.vo.AnimalNeuteredFilter;
import com.clova.anifriends.domain.animal.vo.AnimalType;
import com.clova.anifriends.domain.common.event.ImageDeletionEvent;
import com.clova.anifriends.domain.shelter.Shelter;
import com.clova.anifriends.domain.shelter.support.ShelterFixture;
import java.time.LocalDate;
Expand Down Expand Up @@ -123,7 +122,7 @@ void deleteAnimalWithAnimalImages() {
animalService.deleteAnimal(shelter.getShelterId(), animal.getAnimalId());

//then
verify(s3Service, times(1)).deleteImages(imageUrls);
assertThat(events.stream(ImageDeletionEvent.class).count()).isEqualTo(1);
Animal findAnimal = entityManager.find(Animal.class, animal.getAnimalId());
assertThat(findAnimal).isNull();
List<AnimalImage> findAnimalImages = entityManager.createQuery(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package com.clova.anifriends.domain.recruitment.service;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import com.clova.anifriends.base.BaseIntegrationTest;
import com.clova.anifriends.domain.applicant.Applicant;
import com.clova.anifriends.domain.common.event.ImageDeletionEvent;
import com.clova.anifriends.domain.recruitment.Recruitment;
import com.clova.anifriends.domain.recruitment.RecruitmentImage;
import com.clova.anifriends.domain.recruitment.controller.RecruitmentStatusFilter;
Expand Down Expand Up @@ -144,7 +143,7 @@ void deleteRecruitment() {
recruitment.getRecruitmentId());

//then
verify(s3Service, times(1)).deleteImages(imageUrls);
assertThat(events.stream(ImageDeletionEvent.class).count()).isEqualTo(1);
Recruitment findRecruitment = entityManager.find(Recruitment.class,
recruitment.getRecruitmentId());
assertThat(findRecruitment).isNull();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchException;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import com.clova.anifriends.base.BaseIntegrationTest;
import com.clova.anifriends.domain.applicant.Applicant;
import com.clova.anifriends.domain.applicant.support.ApplicantFixture;
import com.clova.anifriends.domain.applicant.vo.ApplicantStatus;
import com.clova.anifriends.domain.common.event.ImageDeletionEvent;
import com.clova.anifriends.domain.recruitment.Recruitment;
import com.clova.anifriends.domain.recruitment.support.fixture.RecruitmentFixture;
import com.clova.anifriends.domain.review.Review;
Expand Down Expand Up @@ -68,7 +67,7 @@ void deleteReviewThenTryDeleteImages() {
reviewService.deleteReview(volunteer.getVolunteerId(), review.getReviewId());

//then
verify(s3Service, times(1)).deleteImages(List.of("image1", "image2"));
assertThat(events.stream(ImageDeletionEvent.class).count()).isEqualTo(1);

}

Expand Down

0 comments on commit f49064d

Please sign in to comment.