diff --git a/src/main/java/com/javajober/core/config/AsyncConfig.java b/src/main/java/com/javajober/core/config/AsyncConfig.java new file mode 100644 index 0000000..c5d1b39 --- /dev/null +++ b/src/main/java/com/javajober/core/config/AsyncConfig.java @@ -0,0 +1,33 @@ +package com.javajober.core.config; + +import java.util.concurrent.Executor; + +import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.AsyncConfigurerSupport; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import com.javajober.core.exception.AsyncExceptionHandler; + +@Configuration +@EnableAsync +public class AsyncConfig extends AsyncConfigurerSupport { + + @Bean(name="threadPoolTaskExecutor") + public Executor getAsyncExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(5); + executor.setMaxPoolSize(30); + executor.setQueueCapacity(50); + executor.setThreadNamePrefix("ASYNC-"); + executor.initialize(); + return executor; + } + + @Override + public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { + return new AsyncExceptionHandler(); + } +} diff --git a/src/main/java/com/javajober/core/exception/AsyncExceptionHandler.java b/src/main/java/com/javajober/core/exception/AsyncExceptionHandler.java new file mode 100644 index 0000000..825aad4 --- /dev/null +++ b/src/main/java/com/javajober/core/exception/AsyncExceptionHandler.java @@ -0,0 +1,20 @@ +package com.javajober.core.exception; + +import java.lang.reflect.Method; + +import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler { + + @Override + public void handleUncaughtException(Throwable throwable, Method method, Object... obj) { + log.info("Exception message - " + throwable.getMessage()); + log.info("Method name - " + method.getName()); + for (Object param: obj) { + log.info("Parameter value - " + param); + } + } +} diff --git a/src/main/java/com/javajober/member/event/MemberSignupEvent.java b/src/main/java/com/javajober/member/event/MemberSignupEvent.java new file mode 100644 index 0000000..7b80371 --- /dev/null +++ b/src/main/java/com/javajober/member/event/MemberSignupEvent.java @@ -0,0 +1,15 @@ +package com.javajober.member.event; + +import com.javajober.member.domain.Member; + +import lombok.Getter; + +@Getter +public class MemberSignupEvent { + + private final Member member; + + public MemberSignupEvent(final Member member) { + this.member = member; + } +} diff --git a/src/main/java/com/javajober/member/event/MemberSignupEventHandler.java b/src/main/java/com/javajober/member/event/MemberSignupEventHandler.java new file mode 100644 index 0000000..b1a863e --- /dev/null +++ b/src/main/java/com/javajober/member/event/MemberSignupEventHandler.java @@ -0,0 +1,24 @@ +package com.javajober.member.event; + +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; +import org.springframework.transaction.event.TransactionPhase; +import org.springframework.transaction.event.TransactionalEventListener; + +import com.javajober.space.service.SpaceService; + +@Component +public class MemberSignupEventHandler { + + private final SpaceService spaceService; + + public MemberSignupEventHandler(final SpaceService spaceService) { + this.spaceService = spaceService; + } + + @Async("threadPoolTaskExecutor") + @TransactionalEventListener(classes = MemberSignupEvent.class, phase = TransactionPhase.AFTER_COMMIT) + public void handleMemberSignupEvent(final MemberSignupEvent event) { + spaceService.initializeAndSaveNewMemberSpaces(event.getMember()); + } +} diff --git a/src/main/java/com/javajober/member/service/MemberService.java b/src/main/java/com/javajober/member/service/MemberService.java index f0845cf..ebe7714 100644 --- a/src/main/java/com/javajober/member/service/MemberService.java +++ b/src/main/java/com/javajober/member/service/MemberService.java @@ -1,12 +1,10 @@ package com.javajober.member.service; - -import java.util.HashSet; import java.util.Optional; -import java.util.Set; import javax.transaction.Transactional; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; @@ -17,14 +15,11 @@ import com.javajober.member.dto.MemberLoginResponse; import com.javajober.member.dto.MemberSignupRequest; import com.javajober.member.dto.MemberSignupResponse; +import com.javajober.member.event.MemberSignupEvent; import com.javajober.member.repository.MemberRepository; import com.javajober.core.refreshToken.repository.RefreshTokenRepository; import com.javajober.core.security.JwtTokenizer; import com.javajober.core.refreshToken.domain.RefreshToken; -import com.javajober.space.domain.AddSpace; -import com.javajober.space.domain.SpaceType; -import com.javajober.space.dto.request.SpaceSaveRequest; -import com.javajober.space.repository.AddSpaceRepository; @Service public class MemberService { @@ -32,19 +27,24 @@ public class MemberService { private final PasswordEncoder passwordEncoder; private final JwtTokenizer jwtTokenizer; private final RefreshTokenRepository refreshTokenRepository; - private final AddSpaceRepository addSpaceRepository; - - public MemberService(MemberRepository memberRepository, PasswordEncoder passwordEncoder, JwtTokenizer jwtTokenizer, - RefreshTokenRepository refreshTokenRepository, AddSpaceRepository addSpaceRepository) { + private final ApplicationEventPublisher eventPublisher; + + public MemberService( + final MemberRepository memberRepository, + final PasswordEncoder passwordEncoder, + final JwtTokenizer jwtTokenizer, + final RefreshTokenRepository refreshTokenRepository, + final ApplicationEventPublisher eventPublisher + ) { this.memberRepository = memberRepository; this.passwordEncoder = passwordEncoder; this.jwtTokenizer = jwtTokenizer; this.refreshTokenRepository = refreshTokenRepository; - this.addSpaceRepository = addSpaceRepository; + this.eventPublisher = eventPublisher; } @Transactional - public MemberSignupResponse signup(MemberSignupRequest memberSignupRequest) { + public MemberSignupResponse signup(final MemberSignupRequest memberSignupRequest) { Optional existingMember = memberRepository.findMember(memberSignupRequest.getEmail()); if (existingMember.isPresent()) { @@ -55,41 +55,13 @@ public MemberSignupResponse signup(MemberSignupRequest memberSignupRequest) { member.setPassword(passwordEncoder.encode(memberSignupRequest.getPassword())); Member saveMember = memberRepository.save(member); - initializeAndSaveNewMemberSpaces(member); + eventPublisher.publishEvent(new MemberSignupEvent(member)); return new MemberSignupResponse(saveMember); } - private void initializeAndSaveNewMemberSpaces(Member member) { - - SpaceSaveRequest personalSpaceRequest = createSpaceSaveRequest(member.getMemberName(), SpaceType.PERSONAL.getEngTitle(), member.getMemberName()); - SpaceSaveRequest organizationSpaceRequest = createSpaceSaveRequest(member.getMemberName(), SpaceType.ORGANIZATION.getEngTitle(), "임시회사명"); - - Set spaces = new HashSet<>(); - - AddSpace personalSpace = SpaceSaveRequest.toEntity(personalSpaceRequest, member); - spaces.add(personalSpace); - - AddSpace organizationSpace = SpaceSaveRequest.toEntity(organizationSpaceRequest, member); - spaces.add(organizationSpace); - - saveSpaces(spaces); - } - - private SpaceSaveRequest createSpaceSaveRequest(String spaceTitle, String spaceType, String representativeName) { - return SpaceSaveRequest.builder() - .spaceTitle(spaceTitle) - .spaceType(spaceType) - .representativeName(representativeName) - .build(); - } - - private void saveSpaces(Set spaces) { - addSpaceRepository.saveAll(spaces); - } - @Transactional - public MemberLoginResponse login(MemberLoginRequest loginDto) { + public MemberLoginResponse login(final MemberLoginRequest loginDto) { Member member = memberRepository.findMember(loginDto.getEmail()).orElseThrow(() -> new ApplicationException(ApiStatus.NOT_FOUND, "존재하지 않는 회원 아이디입니다.")); diff --git a/src/main/java/com/javajober/space/service/SpaceService.java b/src/main/java/com/javajober/space/service/SpaceService.java index db076d3..ad518da 100644 --- a/src/main/java/com/javajober/space/service/SpaceService.java +++ b/src/main/java/com/javajober/space/service/SpaceService.java @@ -14,12 +14,20 @@ import com.javajober.space.dto.response.MemberGroupResponse; import com.javajober.spaceWall.domain.FlagType; import com.javajober.spaceWall.repository.SpaceWallRepository; + import org.springframework.stereotype.Service; +import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.Set; + +import javax.transaction.Transactional; + +import lombok.extern.slf4j.Slf4j; +@Slf4j @Service public class SpaceService { @@ -28,16 +36,54 @@ public class SpaceService { private final AddSpaceRepository addSpaceRepository; private final SpaceWallRepository spaceWallRepository; - public SpaceService(final MemberRepository memberRepository, final MemberGroupRepository memberGroupRepository, - final AddSpaceRepository addSpaceRepository, final SpaceWallRepository spaceWallRepository) { - + public SpaceService( + final MemberRepository memberRepository, + final MemberGroupRepository memberGroupRepository, + final AddSpaceRepository addSpaceRepository, + final SpaceWallRepository spaceWallRepository + ) { this.memberRepository = memberRepository; this.memberGroupRepository = memberGroupRepository; this.addSpaceRepository = addSpaceRepository; this.spaceWallRepository = spaceWallRepository; } - public SpaceSaveResponse save(SpaceSaveRequest request, Long memberId) { + + public void initializeAndSaveNewMemberSpaces(final Member member) { + + log.info("initializeAndSaveNewMemberSpaces 시작: {}, 스레드 이름: {}", member.getMemberName(), Thread.currentThread().getName()); + + SpaceSaveRequest personalSpaceRequest = createSpaceSaveRequest(member.getMemberName(), SpaceType.PERSONAL.getEngTitle(), member.getMemberName()); + SpaceSaveRequest organizationSpaceRequest = createSpaceSaveRequest(member.getMemberName(), SpaceType.ORGANIZATION.getEngTitle(), "임시회사명"); + + Set spaces = new HashSet<>(); + + AddSpace personalSpace = SpaceSaveRequest.toEntity(personalSpaceRequest, member); + spaces.add(personalSpace); + + AddSpace organizationSpace = SpaceSaveRequest.toEntity(organizationSpaceRequest, member); + spaces.add(organizationSpace); + + saveSpaces(spaces); + + log.info("initializeAndSaveNewMemberSpaces 종료: {}, 스레드 이름: {}", member.getMemberName(), Thread.currentThread().getName()); + } + + private SpaceSaveRequest createSpaceSaveRequest(final String spaceTitle, final String spaceType, final String representativeName) { + return SpaceSaveRequest.builder() + .spaceTitle(spaceTitle) + .spaceType(spaceType) + .representativeName(representativeName) + .build(); + } + + @Transactional + public void saveSpaces(final Set spaces) { + addSpaceRepository.saveAll(spaces); + } + + + public SpaceSaveResponse save(final SpaceSaveRequest request, final Long memberId) { Member member = memberRepository.findMember(memberId); AddSpace space = SpaceSaveRequest.toEntity(request, member); Long spaceId = addSpaceRepository.save(space).getId(); @@ -45,7 +91,7 @@ public SpaceSaveResponse save(SpaceSaveRequest request, Long memberId) { return new SpaceSaveResponse(spaceId); } - public SpaceResponse find(Long addSpaceId, String spaceTypeString, Long memberId) { + public SpaceResponse find(final Long addSpaceId, final String spaceTypeString, final Long memberId) { SpaceType spaceType = SpaceType.findSpaceTypeByString(spaceTypeString); List addSpaceIds = addSpaceRepository.findAddSpaceIds(spaceType, memberId); existsAddSpace(addSpaceId, addSpaceIds); @@ -58,11 +104,10 @@ public SpaceResponse find(Long addSpaceId, String spaceTypeString, Long memberId .orElseGet(() -> new SpaceResponse(false, 0L, memberGroupResponses)); } - private static void existsAddSpace(Long addSpaceId, List addSpaceIds) { + private static void existsAddSpace(final Long addSpaceId, final List addSpaceIds) { boolean containsId = addSpaceIds.stream().anyMatch(id -> Objects.equals(id, addSpaceId)); if(!containsId) { throw new ApplicationException(ApiStatus.NOT_FOUND, "존재하지 않는 스페이스입니다."); } } - } \ No newline at end of file