Skip to content

Commit

Permalink
Merge pull request #302 from zipdabang/refactor/296
Browse files Browse the repository at this point in the history
♻️ Refactor/296 thread 순서 체크 위한 log 추가(@async)
  • Loading branch information
Hanvp authored Feb 3, 2024
2 parents 1d68317 + 0f0d519 commit a9a326a
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 31 deletions.
41 changes: 41 additions & 0 deletions src/main/java/zipdabang/server/async/AsyncConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package zipdabang.server.async;

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {

private int CORE_POOL_SIZE = 3;
private int MAX_POOL_SIZE = 8;
private int QUEUE_CAPACITY = 1000;

@Bean(name = "recipeUploadExecutor")
public Executor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();

taskExecutor.setCorePoolSize(CORE_POOL_SIZE);
taskExecutor.setMaxPoolSize(MAX_POOL_SIZE);
taskExecutor.setQueueCapacity(QUEUE_CAPACITY);
taskExecutor.setThreadNamePrefix("Executor-");

taskExecutor.setTaskDecorator(new CustomDecorator());
taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

return taskExecutor;
}

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return AsyncConfigurer.super.getAsyncUncaughtExceptionHandler();
}

}
15 changes: 15 additions & 0 deletions src/main/java/zipdabang/server/async/AsyncExceptionHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package zipdabang.server.async;

import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;

import java.lang.reflect.Method;

@Slf4j
public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {

@Override
public void handleUncaughtException(Throwable ex, Method method, Object... params) {
log.error(ex.getMessage(), ex);
}
}
22 changes: 22 additions & 0 deletions src/main/java/zipdabang/server/async/CustomDecorator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package zipdabang.server.async;

import org.springframework.core.task.TaskDecorator;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

public class CustomDecorator implements TaskDecorator {
@Override
public Runnable decorate(Runnable runnable) {
RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();

return () ->{
try{
RequestContextHolder.setRequestAttributes(attributes);

runnable.run();
} finally {
RequestContextHolder.resetRequestAttributes();
}
};
}
}
20 changes: 11 additions & 9 deletions src/main/java/zipdabang/server/converter/RecipeConverter.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Matcher;
Expand Down Expand Up @@ -746,10 +747,10 @@ public static TestRecipe toTestRecipe(RecipeRequestDto.CreateRecipeDto request,
return recipe;
}

public static List<TestRecipeCategoryMapping> toTestRecipeCategory(List<Long> categoryIds, TestRecipe recipe) {
return categoryIds.stream().parallel()
public static CompletableFuture<List<TestRecipeCategoryMapping>> toTestRecipeCategory(List<Long> categoryIds, TestRecipe recipe) {
return CompletableFuture.completedFuture(categoryIds.stream()
.map(recipeCategoryId -> toTestRecipeCategoryMappingDto(recipeCategoryId, recipe))
.collect(Collectors.toList());
.collect(Collectors.toList()));
}

private static TestRecipeCategoryMapping toTestRecipeCategoryMappingDto(Long categoryId, TestRecipe recipe) {
Expand All @@ -760,8 +761,8 @@ private static TestRecipeCategoryMapping toTestRecipeCategoryMappingDto(Long cat
.build();
}

public static List<TestStep> toTestStep(RecipeRequestDto.CreateRecipeDto request, TestRecipe recipe, List<MultipartFile> stepImages) {
return request.getSteps().stream().parallel()
public static CompletableFuture<List<TestStep>> toTestStep(RecipeRequestDto.CreateRecipeDto request, TestRecipe recipe, List<MultipartFile> stepImages) {
return CompletableFuture.completedFuture(request.getSteps().stream()
.map(step-> {
if (step.getDescription() == null)
throw new RecipeException(CommonStatus.NULL_RECIPE_ERROR);
Expand All @@ -771,7 +772,8 @@ public static List<TestStep> toTestStep(RecipeRequestDto.CreateRecipeDto request
throw new RuntimeException(e);
}
})
.collect(Collectors.toList());
.collect(Collectors.toList())
);
}

private static TestStep toTestStepDto(RecipeRequestDto.StepDto step, TestRecipe recipe, List<MultipartFile> stepImages) throws IOException {
Expand Down Expand Up @@ -803,10 +805,10 @@ private static TestStep toTestStepDto(RecipeRequestDto.StepDto step, TestRecipe
return createdStep;
}

public static List<TestIngredient> toTestIngredient(RecipeRequestDto.CreateRecipeDto request, TestRecipe recipe) {
return request.getIngredients().stream().parallel()
public static CompletableFuture<List<TestIngredient>> toTestIngredient(RecipeRequestDto.CreateRecipeDto request, TestRecipe recipe) {
return CompletableFuture.completedFuture(request.getIngredients().stream()
.map(ingredient -> toTestIngredientDto(ingredient, recipe))
.collect(Collectors.toList());
.collect(Collectors.toList()));
}

private static TestIngredient toTestIngredientDto(RecipeRequestDto.NewIngredientDto ingredient, TestRecipe recipe) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import zipdabang.server.domain.inform.PushAlarm;
import zipdabang.server.domain.member.*;
import zipdabang.server.domain.recipe.*;
import zipdabang.server.domain.test.QTestRecipe;
import zipdabang.server.domain.test.TestRecipe;
import zipdabang.server.firebase.fcm.service.FirebaseService;
import zipdabang.server.repository.AlarmRepository.AlarmCategoryRepository;
Expand All @@ -45,6 +46,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Slf4j
Expand Down Expand Up @@ -905,29 +907,40 @@ public RecipeCategory getRecipeCategory(Long categoryId) {
@Override
@Transactional(readOnly = false)
public TestRecipe testCreate(RecipeRequestDto.CreateRecipeDto request, MultipartFile thumbnail, List<MultipartFile> stepImages) throws IOException {
TestRecipe buildRecipe = RecipeConverter.toTestRecipe(request, thumbnail);
TestRecipe recipe = testRecipeRepository.save(buildRecipe);

RecipeConverter.toTestRecipeCategory(request.getCategoryId(),recipe).stream()
.map(categoryMapping -> testRecipeCategoryMappingRepository.save(categoryMapping))
.collect(Collectors.toList())
.stream()
.map(categoryMapping -> categoryMapping.setRecipe(recipe));


RecipeConverter.toTestStep(request, recipe, stepImages).stream()
.map(step -> testStepRepository.save(step))
.collect(Collectors.toList())
.stream()
.map(step -> step.setRecipe(recipe));

RecipeConverter.toTestIngredient(request, recipe).stream()
.map(ingredient -> testIngredientRepository.save(ingredient))
.collect(Collectors.toList())
.stream()
.map(ingredient -> ingredient.setRecipe(recipe));

return recipe;
CompletableFuture<TestRecipe> savedRecipeFuture = CompletableFuture.supplyAsync(() ->{
TestRecipe buildRecipe = null;
try {
buildRecipe = RecipeConverter.toTestRecipe(request, thumbnail);
} catch (IOException e) {
throw new RuntimeException(e);
}
return testRecipeRepository.save(buildRecipe);
});

savedRecipeFuture.thenAccept(recipe -> {
RecipeConverter.toTestRecipeCategory(request.getCategoryId(),recipe).join().stream()
.map(categoryMapping -> testRecipeCategoryMappingRepository.save(categoryMapping))
.peek(categoryMapping -> categoryMapping.setRecipe(recipe));
// .collect(Collectors.toList())
// .stream()
// .map(categoryMapping -> categoryMapping.setRecipe(recipe));
});


savedRecipeFuture.thenAccept(recipe -> {
RecipeConverter.toTestStep(request, recipe, stepImages).join().stream()
.map(step -> testStepRepository.save(step))
.peek(step -> step.setRecipe(recipe));
});

savedRecipeFuture.thenAccept(recipe -> {
RecipeConverter.toTestIngredient(request, recipe).join().stream()
.map(ingredient -> testIngredientRepository.save(ingredient))
.peek(ingredient -> ingredient.setRecipe(recipe));
});

return savedRecipeFuture.join();
}

@Override
Expand Down

0 comments on commit a9a326a

Please sign in to comment.