diff --git a/mashup-domain/src/main/java/kr/mashup/branding/service/mashong/dto/MissionEventType.java b/mashup-domain/src/main/java/kr/mashup/branding/service/mashong/dto/MissionEventType.java new file mode 100644 index 000000000..75fc12793 --- /dev/null +++ b/mashup-domain/src/main/java/kr/mashup/branding/service/mashong/dto/MissionEventType.java @@ -0,0 +1,12 @@ +package kr.mashup.branding.service.mashong.dto; + +public enum MissionEventType { + + APPLY, + SET_TO_VALUE, + ; + + public boolean isApplyType() { + return this.equals(APPLY); + } +} diff --git a/mashup-domain/src/main/java/kr/mashup/branding/service/mashong/event/MashongMissionEvent.java b/mashup-domain/src/main/java/kr/mashup/branding/service/mashong/event/MashongMissionEvent.java new file mode 100644 index 000000000..03d87451c --- /dev/null +++ b/mashup-domain/src/main/java/kr/mashup/branding/service/mashong/event/MashongMissionEvent.java @@ -0,0 +1,22 @@ +package kr.mashup.branding.service.mashong.event; + + +import kr.mashup.branding.domain.mashong.MissionStrategyType; +import kr.mashup.branding.domain.member.MemberGeneration; +import kr.mashup.branding.service.mashong.dto.MissionEventType; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public class MashongMissionEvent { + + private final MissionStrategyType missionStrategyType; + private final MemberGeneration memberGeneration; + private final Double value; + private final MissionEventType eventType; + + public boolean isApplyEvent() { + return eventType.isApplyType(); + } +} diff --git a/mashup-domain/src/main/java/kr/mashup/branding/service/mashong/event/MashongMissionEventPublisher.java b/mashup-domain/src/main/java/kr/mashup/branding/service/mashong/event/MashongMissionEventPublisher.java new file mode 100644 index 000000000..198e6d5c8 --- /dev/null +++ b/mashup-domain/src/main/java/kr/mashup/branding/service/mashong/event/MashongMissionEventPublisher.java @@ -0,0 +1,18 @@ +package kr.mashup.branding.service.mashong.event; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +@RequiredArgsConstructor +public class MashongMissionEventPublisher { + + private final ApplicationEventPublisher eventPublisher; + + public void publish(MashongMissionEvent event) { + eventPublisher.publishEvent(event); + } +} diff --git a/mashup-member/src/main/java/kr/mashup/branding/config/async/AsyncConfig.java b/mashup-member/src/main/java/kr/mashup/branding/config/async/AsyncConfig.java index b74fe5225..40bea64a1 100644 --- a/mashup-member/src/main/java/kr/mashup/branding/config/async/AsyncConfig.java +++ b/mashup-member/src/main/java/kr/mashup/branding/config/async/AsyncConfig.java @@ -20,4 +20,13 @@ public Executor pushNotiSendThreadPoolTaskExecutor() { return taskExecutor; } + @Bean(name = ThreadPoolName.MASHONG_MISSION_THREAD_POOL) + public Executor mashongMissionThreadPoolTaskExecutor() { + ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); + taskExecutor.setCorePoolSize(3); + taskExecutor.setMaxPoolSize(30); + taskExecutor.setQueueCapacity(100); + taskExecutor.setThreadNamePrefix("Executor-"); + return taskExecutor; + } } diff --git a/mashup-member/src/main/java/kr/mashup/branding/config/async/ThreadPoolName.java b/mashup-member/src/main/java/kr/mashup/branding/config/async/ThreadPoolName.java index 49ca24284..484ac69c3 100644 --- a/mashup-member/src/main/java/kr/mashup/branding/config/async/ThreadPoolName.java +++ b/mashup-member/src/main/java/kr/mashup/branding/config/async/ThreadPoolName.java @@ -2,4 +2,5 @@ public class ThreadPoolName { public static final String PUSH_NOTI_SEND_THREAD_POOL = "PUSH_NOTI_SEND_THREAD_POOL"; + public static final String MASHONG_MISSION_THREAD_POOL = "MASHONG_MISSION_THREAD_POOL"; } diff --git a/mashup-member/src/main/java/kr/mashup/branding/facade/danggn/DanggnFacadeService.java b/mashup-member/src/main/java/kr/mashup/branding/facade/danggn/DanggnFacadeService.java index 9578d789f..8e8d82dd3 100644 --- a/mashup-member/src/main/java/kr/mashup/branding/facade/danggn/DanggnFacadeService.java +++ b/mashup-member/src/main/java/kr/mashup/branding/facade/danggn/DanggnFacadeService.java @@ -1,6 +1,9 @@ package kr.mashup.branding.facade.danggn; -import kr.mashup.branding.domain.danggn.*; +import kr.mashup.branding.domain.danggn.DanggnRankingReward; +import kr.mashup.branding.domain.danggn.DanggnRankingRewardStatus; +import kr.mashup.branding.domain.danggn.DanggnRankingRound; +import kr.mashup.branding.domain.danggn.DanggnScore; import kr.mashup.branding.domain.danggn.Exception.DanggnRankingRewardAlreadyWrittenException; import kr.mashup.branding.domain.danggn.Exception.DanggnRankingRewardNotAllowedException; import kr.mashup.branding.domain.mashong.MissionStrategyType; @@ -9,9 +12,11 @@ import kr.mashup.branding.domain.member.Platform; import kr.mashup.branding.domain.pushnoti.vo.DanggnRewardUpdatedVo; import kr.mashup.branding.domain.randommessage.RandomMessage; -import kr.mashup.branding.facade.mashong.MashongMissionFacadeService; import kr.mashup.branding.infrastructure.pushnoti.PushNotiEventPublisher; import kr.mashup.branding.service.danggn.*; +import kr.mashup.branding.service.mashong.dto.MissionEventType; +import kr.mashup.branding.service.mashong.event.MashongMissionEvent; +import kr.mashup.branding.service.mashong.event.MashongMissionEventPublisher; import kr.mashup.branding.service.member.MemberService; import kr.mashup.branding.ui.danggn.response.*; import kr.mashup.branding.ui.danggn.response.DanggnRankingRoundResponse.DanggnRankingRewardResponse; @@ -43,7 +48,7 @@ public class DanggnFacadeService { private final PushNotiEventPublisher pushNotiEventPublisher; - private final MashongMissionFacadeService mashongMissionFacadeService; + private final MashongMissionEventPublisher mashongMissionEventPublisher; @Transactional public DanggnScoreResponse addScore(Long memberGenerationId, Long score) { @@ -54,9 +59,18 @@ public DanggnScoreResponse addScore(Long memberGenerationId, Long score) { danggnScore.addScore(score); danggnShakeLogService.createLog(memberGeneration, score); - //todo: application event publisher 로 변경 - mashongMissionFacadeService.apply(MissionStrategyType.MASHONG_DANGGN_SHAKE_INDIVIDUAL, memberGeneration, score.doubleValue()); - mashongMissionFacadeService.apply(MissionStrategyType.MASHONG_DANGGN_SHAKE_TEAM, memberGeneration, score.doubleValue()); + mashongMissionEventPublisher.publish(new MashongMissionEvent( + MissionStrategyType.MASHONG_DANGGN_SHAKE_INDIVIDUAL, + memberGeneration, + score.doubleValue(), + MissionEventType.APPLY + )); + mashongMissionEventPublisher.publish(new MashongMissionEvent( + MissionStrategyType.MASHONG_DANGGN_SHAKE_TEAM, + memberGeneration, + score.doubleValue(), + MissionEventType.APPLY + )); return DanggnScoreResponse.of(danggnScore.getTotalShakeScore()); } @@ -67,7 +81,7 @@ public List getMemberRankList(Integer generationNumber, Lo } return danggnScoreService.getDanggnScoreOrderedList(generationNumber, danggnRankingRoundId) - .stream().map(DanggnMemberRankData::from).collect(Collectors.toList()); + .stream().map(DanggnMemberRankData::from).collect(Collectors.toList()); } @Transactional(readOnly = true) @@ -80,8 +94,8 @@ public List getPlatformRankList(Integer generationNu Set notExistingPlatforms = getNotExistingPlatforms(existingPlatformRankList); List notExistingPlatformRankList = notExistingPlatforms.stream() - .map(platform -> DanggnPlatformRankResponse.of(platform, 0L)) - .collect(Collectors.toList()); + .map(platform -> DanggnPlatformRankResponse.of(platform, 0L)) + .collect(Collectors.toList()); return Stream.concat(existingPlatformRankList.stream(), notExistingPlatformRankList.stream()).collect(Collectors.toList()); } @@ -100,9 +114,9 @@ public DanggnRandomMessageResponse getRandomTodayMessage() { public DanggnRankingRoundsResponse getAllRankingRoundByMemberGeneration(Long memberGenerationId) { final MemberGeneration memberGeneration = memberService.findByMemberGenerationId(memberGenerationId); List simpleResponses = danggnRankingRoundService.findPastAndCurrentByGeneration(memberGeneration.getGeneration()) - .stream() - .map(DanggnRankingRoundsResponse.DanggnRankingRoundSimpleResponse::from) - .collect(Collectors.toList()); + .stream() + .map(DanggnRankingRoundsResponse.DanggnRankingRoundSimpleResponse::from) + .collect(Collectors.toList()); return DanggnRankingRoundsResponse.from(simpleResponses); } @@ -118,15 +132,15 @@ public DanggnRankingRoundResponse getRankingRoundById(Long memberId, Long danggn @Transactional public void writeDanggnRankingRewardComment( - Long memberId, - Long danggnRankingRewardId, - String comment + Long memberId, + Long danggnRankingRewardId, + String comment ) { DanggnRankingReward danggnRankingReward = danggnRankingRewardService.findById(danggnRankingRewardId); - if(danggnRankingReward.getComment() != null) { + if (danggnRankingReward.getComment() != null) { throw new DanggnRankingRewardAlreadyWrittenException(); } - if(danggnRankingReward.getFirstPlaceRecordMemberId() != memberId) { + if (danggnRankingReward.getFirstPlaceRecordMemberId() != memberId) { throw new DanggnRankingRewardNotAllowedException(); } danggnRankingRewardService.writeComment(danggnRankingRewardId, comment); @@ -144,15 +158,15 @@ public void writeDanggnRankingRewardComment( private List getExistingPlatformRankList(Integer generationNumber, Long danggnRankingRoundId) { return danggnScoreService.getDanggnScorePlatformOrderedList(generationNumber, danggnRankingRoundId).stream() - .map(queryResult -> DanggnPlatformRankResponse.of(queryResult.getPlatform(), queryResult.getTotalScore())) - .collect(Collectors.toList()); + .map(queryResult -> DanggnPlatformRankResponse.of(queryResult.getPlatform(), queryResult.getTotalScore())) + .collect(Collectors.toList()); } private Set getNotExistingPlatforms(List existingPlatformRankList) { Set entirePlatforms = Arrays.stream(Platform.values()).collect(Collectors.toSet()); Set existingPlatforms = existingPlatformRankList.stream() - .map(DanggnPlatformRankResponse::getPlatform) - .collect(Collectors.toSet()); + .map(DanggnPlatformRankResponse::getPlatform) + .collect(Collectors.toSet()); entirePlatforms.removeAll(existingPlatforms); return entirePlatforms; } @@ -161,7 +175,7 @@ private DanggnRankingRewardResponse getDanggnRankingRewardResponse(Long memberId final DanggnRankingReward reward = danggnRankingRewardService.findByDanggnRankingRoundOrNull(danggnRankingRound); final DanggnRankingRewardStatus status = - (reward == null || reward.getFirstPlaceRecordMemberId() == null) ? DanggnRankingRewardStatus.FIRST_PLACE_MEMBER_NOT_EXISTED : reward.getRankingRewardStatus(); + (reward == null || reward.getFirstPlaceRecordMemberId() == null) ? DanggnRankingRewardStatus.FIRST_PLACE_MEMBER_NOT_EXISTED : reward.getRankingRewardStatus(); final Member member = status.hasFirstPlaceMember() ? memberService.getActiveOrThrowById(reward.getFirstPlaceRecordMemberId()) : null; final Boolean isFirstPlaceMember = member != null && Objects.equals(memberId, member.getId()); diff --git a/mashup-member/src/main/java/kr/mashup/branding/facade/mashong/MashongFacadeService.java b/mashup-member/src/main/java/kr/mashup/branding/facade/mashong/MashongFacadeService.java index 1798cd8b8..6a6854413 100644 --- a/mashup-member/src/main/java/kr/mashup/branding/facade/mashong/MashongFacadeService.java +++ b/mashup-member/src/main/java/kr/mashup/branding/facade/mashong/MashongFacadeService.java @@ -6,6 +6,9 @@ import kr.mashup.branding.domain.member.Platform; import kr.mashup.branding.service.mashong.*; import kr.mashup.branding.service.mashong.dto.LevelUpResult; +import kr.mashup.branding.service.mashong.dto.MissionEventType; +import kr.mashup.branding.service.mashong.event.MashongMissionEvent; +import kr.mashup.branding.service.mashong.event.MashongMissionEventPublisher; import kr.mashup.branding.service.member.MemberService; import kr.mashup.branding.ui.mashong.response.MashongFeedResponse; import kr.mashup.branding.ui.mashong.response.MashongLevelUpResponse; @@ -19,7 +22,6 @@ public class MashongFacadeService { private final MashongAttendanceService mashongAttendanceService; - private final MashongMissionFacadeService mashongMissionFacadeService; private final MashongPopcornService mashongPopcornService; private final MashongMissionLogService mashongMissionLogService; private final MashongMissionTeamLogService mashongMissionTeamLogService; @@ -27,14 +29,25 @@ public class MashongFacadeService { private final PlatformMashongService platformMashongService; private final PlatformMashongLevelService platformMashongLevelService; private final MemberService memberService; + private final MashongMissionEventPublisher mashongMissionEventPublisher; @Transactional public Boolean attend(Long memberGenerationId) { MemberGeneration memberGeneration = memberService.findByMemberGenerationId(memberGenerationId); Boolean result = mashongAttendanceService.attend(memberGeneration); if (result) { - mashongMissionFacadeService.apply(MissionStrategyType.MASHONG_ATTENDANCE_INDIVIDUAL, memberGeneration, 1.0); - mashongMissionFacadeService.setToValue(MissionStrategyType.MASHONG_ATTENDANCE_TEAN, memberGeneration, getPlatformAttendStatus(memberGeneration.getPlatform(), memberGeneration.getGeneration())); + mashongMissionEventPublisher.publish(new MashongMissionEvent( + MissionStrategyType.MASHONG_ATTENDANCE_INDIVIDUAL, + memberGeneration, + 1.0, + MissionEventType.APPLY + )); + mashongMissionEventPublisher.publish(new MashongMissionEvent( + MissionStrategyType.MASHONG_ATTENDANCE_TEAN, + memberGeneration, + getPlatformAttendStatus(memberGeneration.getPlatform(), memberGeneration.getGeneration()), + MissionEventType.SET_TO_VALUE + )); mashongPopcornService.givePopcorn(memberGenerationId, 1L); } return result; @@ -103,12 +116,12 @@ public MashongFeedResponse feedPopcorn(Long memberGenerationId, Long popcornCoun platformMashongService.feedPopcorn(platformMashong, popcornCount); final MashongPopcorn mashongPopcorn = mashongPopcornService.decreasePopcorn(memberGenerationId, popcornCount); - // TODO: event publisher 로 변경 - mashongMissionFacadeService.apply( + mashongMissionEventPublisher.publish(new MashongMissionEvent( MissionStrategyType.MASHONG_POPCORN_INDIVIDUAL, memberGeneration, - popcornCount.doubleValue() - ); + popcornCount.doubleValue(), + MissionEventType.APPLY + )); return MashongFeedResponse.of(true, platformMashong, mashongPopcorn); } @@ -126,13 +139,13 @@ public MashongLevelUpResponse levelUp(Long memberGenerationId, int goalLevel) { return MashongLevelUpResponse.of(levelUpResult, platformMashong.getLevel()); } - // TODO: even publisher 로 변경 if (levelUpResult.isUpdateLog()) { - mashongMissionFacadeService.setToValue( + mashongMissionEventPublisher.publish(new MashongMissionEvent( MissionStrategyType.MASHONG_LEVEL_TEAM, memberGeneration, - (double) goalPlatformMashongLevel.getLevel() - ); + (double) goalPlatformMashongLevel.getLevel(), + MissionEventType.SET_TO_VALUE + )); } return MashongLevelUpResponse.of(levelUpResult, goalPlatformMashongLevel); diff --git a/mashup-member/src/main/java/kr/mashup/branding/facade/mashong/MashongMissionFacadeService.java b/mashup-member/src/main/java/kr/mashup/branding/facade/mashong/MashongMissionFacadeService.java index e155721e4..becdbaae3 100644 --- a/mashup-member/src/main/java/kr/mashup/branding/facade/mashong/MashongMissionFacadeService.java +++ b/mashup-member/src/main/java/kr/mashup/branding/facade/mashong/MashongMissionFacadeService.java @@ -11,6 +11,7 @@ import kr.mashup.branding.service.member.MemberService; import kr.mashup.branding.ui.mashong.response.MashongAttendanceResponse; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -18,6 +19,7 @@ import java.util.Optional; import java.util.stream.Collectors; +@Slf4j @Service @RequiredArgsConstructor public class MashongMissionFacadeService { diff --git a/mashup-member/src/main/java/kr/mashup/branding/ui/mashong/MashongMissionEventListener.java b/mashup-member/src/main/java/kr/mashup/branding/ui/mashong/MashongMissionEventListener.java new file mode 100644 index 000000000..c991c3203 --- /dev/null +++ b/mashup-member/src/main/java/kr/mashup/branding/ui/mashong/MashongMissionEventListener.java @@ -0,0 +1,45 @@ +package kr.mashup.branding.ui.mashong; + +import kr.mashup.branding.config.async.ThreadPoolName; +import kr.mashup.branding.facade.mashong.MashongMissionFacadeService; +import kr.mashup.branding.service.mashong.event.MashongMissionEvent; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.event.TransactionalEventListener; + +@Slf4j +@RequiredArgsConstructor +@Component +public class MashongMissionEventListener { + + private final MashongMissionFacadeService mashongMissionFacadeService; + + @Async(value = ThreadPoolName.MASHONG_MISSION_THREAD_POOL) + @Transactional(propagation = Propagation.NEVER) + @TransactionalEventListener + public void handleMashongMissionEvent(MashongMissionEvent event) { + log.info("MASHONG_MISSION_{}_EVENT_LISTEN :: memberGenerationId = {}", + event.getEventType(), + event.getMemberGeneration().getId() + ); + + if (event.isApplyEvent()) { + mashongMissionFacadeService.apply( + event.getMissionStrategyType(), + event.getMemberGeneration(), + event.getValue() + ); + return; + } + + mashongMissionFacadeService.setToValue( + event.getMissionStrategyType(), + event.getMemberGeneration(), + event.getValue() + ); + } +}