From 4382d69703399cc89f6c1cec345becbd620b21eb Mon Sep 17 00:00:00 2001 From: Yiseul Park Date: Sat, 9 Mar 2024 15:47:39 +0900 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=EB=A0=88=EB=94=94=EC=8A=A4=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EB=B9=84?= =?UTF-8?q?=EB=8F=99=EA=B8=B0=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domains/vote/application/VoteService.java | 24 +++++------ .../event/ranking/vote/RankingAddEvent.java | 9 +++++ .../vote/RankingDecreasePopularityEvent.java | 9 +++++ .../ranking/vote/RankingDeleteEvent.java | 9 +++++ .../ranking/vote/RankingEventListener.java | 40 +++++++++++++++++++ .../ranking/vote/RankingUpdateEvent.java | 10 +++++ 6 files changed, 89 insertions(+), 12 deletions(-) create mode 100644 lime-api/src/main/java/com/programmers/lime/global/event/ranking/vote/RankingAddEvent.java create mode 100644 lime-api/src/main/java/com/programmers/lime/global/event/ranking/vote/RankingDecreasePopularityEvent.java create mode 100644 lime-api/src/main/java/com/programmers/lime/global/event/ranking/vote/RankingDeleteEvent.java create mode 100644 lime-api/src/main/java/com/programmers/lime/global/event/ranking/vote/RankingEventListener.java create mode 100644 lime-api/src/main/java/com/programmers/lime/global/event/ranking/vote/RankingUpdateEvent.java diff --git a/lime-api/src/main/java/com/programmers/lime/domains/vote/application/VoteService.java b/lime-api/src/main/java/com/programmers/lime/domains/vote/application/VoteService.java index 5667251ad..e0f51983d 100644 --- a/lime-api/src/main/java/com/programmers/lime/domains/vote/application/VoteService.java +++ b/lime-api/src/main/java/com/programmers/lime/domains/vote/application/VoteService.java @@ -3,6 +3,7 @@ import java.util.Collections; import java.util.List; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import com.programmers.lime.common.cursor.CursorPageParameters; @@ -26,6 +27,10 @@ import com.programmers.lime.error.BusinessException; import com.programmers.lime.error.EntityNotFoundException; import com.programmers.lime.error.ErrorCode; +import com.programmers.lime.global.event.ranking.vote.RankingAddEvent; +import com.programmers.lime.global.event.ranking.vote.RankingDecreasePopularityEvent; +import com.programmers.lime.global.event.ranking.vote.RankingDeleteEvent; +import com.programmers.lime.global.event.ranking.vote.RankingUpdateEvent; import com.programmers.lime.global.util.MemberUtils; import com.programmers.lime.redis.vote.VoteRankingInfo; import com.programmers.lime.redis.vote.VoteRedisManager; @@ -44,14 +49,15 @@ public class VoteService { private final MemberUtils memberUtils; private final ItemReader itemReader; private final VoteRedisManager voteRedisManager; + private final ApplicationEventPublisher eventPublisher; public Long createVote(final VoteCreateServiceRequest request) { final Long memberId = memberUtils.getCurrentMemberId(); + validateItemIds(request.item1Id(), request.item2Id()); - final Vote vote = voteAppender.append(memberId, request.toImplRequest()); - final VoteRankingInfo rankingInfo = getVoteRedis(vote); - voteRedisManager.addRanking(vote.getHobby().toString(), rankingInfo); + final Vote vote = voteAppender.append(memberId, request.toImplRequest()); + eventPublisher.publishEvent(new RankingAddEvent(String.valueOf(vote.getHobby()), getVoteRedis(vote))); return vote.getId(); } @@ -84,11 +90,7 @@ private void participate( voter -> voteManager.reParticipate(itemId, voter), () -> { voteManager.participate(vote, memberId, itemId); - voteRedisManager.updateRanking( - vote.getHobby().toString(), - vote.isVoting(), - getVoteRedis(vote) - ); + eventPublisher.publishEvent(new RankingUpdateEvent(String.valueOf(vote.getHobby()), vote.isVoting(), getVoteRedis(vote))); } ); } @@ -98,8 +100,7 @@ public void cancelVote(final Long voteId) { final Vote vote = voteReader.read(voteId); voteManager.cancel(vote, memberId); - - voteRedisManager.decreasePopularity(vote.getHobby().toString(), getVoteRedis(vote)); + eventPublisher.publishEvent(new RankingDecreasePopularityEvent(String.valueOf(vote.getHobby()), getVoteRedis(vote))); } public void deleteVote(final Long voteId) { @@ -111,8 +112,7 @@ public void deleteVote(final Long voteId) { } voteRemover.remove(vote); - - voteRedisManager.remove(vote.getHobby().toString(), getVoteRedis(vote)); + eventPublisher.publishEvent(new RankingDeleteEvent(String.valueOf(vote.getHobby()), getVoteRedis(vote))); } public VoteGetServiceResponse getVote(final Long voteId) { diff --git a/lime-api/src/main/java/com/programmers/lime/global/event/ranking/vote/RankingAddEvent.java b/lime-api/src/main/java/com/programmers/lime/global/event/ranking/vote/RankingAddEvent.java new file mode 100644 index 000000000..7040d1bd0 --- /dev/null +++ b/lime-api/src/main/java/com/programmers/lime/global/event/ranking/vote/RankingAddEvent.java @@ -0,0 +1,9 @@ +package com.programmers.lime.global.event.ranking.vote; + +import com.programmers.lime.redis.vote.VoteRankingInfo; + +public record RankingAddEvent( + String hobby, + VoteRankingInfo voteRankingInfo +) { +} diff --git a/lime-api/src/main/java/com/programmers/lime/global/event/ranking/vote/RankingDecreasePopularityEvent.java b/lime-api/src/main/java/com/programmers/lime/global/event/ranking/vote/RankingDecreasePopularityEvent.java new file mode 100644 index 000000000..e7d50c061 --- /dev/null +++ b/lime-api/src/main/java/com/programmers/lime/global/event/ranking/vote/RankingDecreasePopularityEvent.java @@ -0,0 +1,9 @@ +package com.programmers.lime.global.event.ranking.vote; + +import com.programmers.lime.redis.vote.VoteRankingInfo; + +public record RankingDecreasePopularityEvent( + String hobby, + VoteRankingInfo voteRankingInfo +) { +} diff --git a/lime-api/src/main/java/com/programmers/lime/global/event/ranking/vote/RankingDeleteEvent.java b/lime-api/src/main/java/com/programmers/lime/global/event/ranking/vote/RankingDeleteEvent.java new file mode 100644 index 000000000..26a0de151 --- /dev/null +++ b/lime-api/src/main/java/com/programmers/lime/global/event/ranking/vote/RankingDeleteEvent.java @@ -0,0 +1,9 @@ +package com.programmers.lime.global.event.ranking.vote; + +import com.programmers.lime.redis.vote.VoteRankingInfo; + +public record RankingDeleteEvent( + String hobby, + VoteRankingInfo voteRankingInfo +) { +} diff --git a/lime-api/src/main/java/com/programmers/lime/global/event/ranking/vote/RankingEventListener.java b/lime-api/src/main/java/com/programmers/lime/global/event/ranking/vote/RankingEventListener.java new file mode 100644 index 000000000..e38f97c8a --- /dev/null +++ b/lime-api/src/main/java/com/programmers/lime/global/event/ranking/vote/RankingEventListener.java @@ -0,0 +1,40 @@ +package com.programmers.lime.global.event.ranking.vote; + +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; + +import com.programmers.lime.redis.vote.VoteRedisManager; + +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class RankingEventListener { + + private final VoteRedisManager voteRedisManager; + + @Async + @EventListener + public void addRanking(final RankingAddEvent event) { + voteRedisManager.addRanking(event.hobby(), event.voteRankingInfo()); + } + + @Async + @EventListener + public void updateRanking(final RankingUpdateEvent event) { + voteRedisManager.updateRanking(event.hobby(), event.isVoting(), event.voteRankingInfo()); + } + + @Async + @EventListener + public void decreasePopularity(final RankingDecreasePopularityEvent event) { + voteRedisManager.decreasePopularity(event.hobby(), event.voteRankingInfo()); + } + + @Async + @EventListener + public void deleteRanking(final RankingDeleteEvent event) { + voteRedisManager.remove(event.hobby(), event.voteRankingInfo()); + } +} diff --git a/lime-api/src/main/java/com/programmers/lime/global/event/ranking/vote/RankingUpdateEvent.java b/lime-api/src/main/java/com/programmers/lime/global/event/ranking/vote/RankingUpdateEvent.java new file mode 100644 index 000000000..865ae008a --- /dev/null +++ b/lime-api/src/main/java/com/programmers/lime/global/event/ranking/vote/RankingUpdateEvent.java @@ -0,0 +1,10 @@ +package com.programmers.lime.global.event.ranking.vote; + +import com.programmers.lime.redis.vote.VoteRankingInfo; + +public record RankingUpdateEvent( + String hobby, + boolean isVoting, + VoteRankingInfo voteRankingInfo +) { +} From abedcd2228e373ca4b76bdef41e0a927fe57cd8e Mon Sep 17 00:00:00 2001 From: Yiseul Park Date: Sat, 9 Mar 2024 16:17:56 +0900 Subject: [PATCH 2/5] =?UTF-8?q?refactor:=20=EC=9D=B8=EA=B8=B0=EB=8F=84=20?= =?UTF-8?q?=EC=A6=9D=EA=B0=80/=EA=B0=90=EC=86=8C=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=ED=86=B5=ED=95=A9,=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ranking/vote/RankingEventListener.java | 4 ++-- .../lime/redis/vote/VoteRedisManager.java | 24 +++++++------------ 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/lime-api/src/main/java/com/programmers/lime/global/event/ranking/vote/RankingEventListener.java b/lime-api/src/main/java/com/programmers/lime/global/event/ranking/vote/RankingEventListener.java index e38f97c8a..e6e42a09b 100644 --- a/lime-api/src/main/java/com/programmers/lime/global/event/ranking/vote/RankingEventListener.java +++ b/lime-api/src/main/java/com/programmers/lime/global/event/ranking/vote/RankingEventListener.java @@ -29,12 +29,12 @@ public void updateRanking(final RankingUpdateEvent event) { @Async @EventListener public void decreasePopularity(final RankingDecreasePopularityEvent event) { - voteRedisManager.decreasePopularity(event.hobby(), event.voteRankingInfo()); + voteRedisManager.updatePopularity(event.hobby(), event.voteRankingInfo(), -1); } @Async @EventListener public void deleteRanking(final RankingDeleteEvent event) { - voteRedisManager.remove(event.hobby(), event.voteRankingInfo()); + voteRedisManager.deleteRanking(event.hobby(), event.voteRankingInfo()); } } diff --git a/lime-infrastructure/src/main/java/com/programmers/lime/redis/vote/VoteRedisManager.java b/lime-infrastructure/src/main/java/com/programmers/lime/redis/vote/VoteRedisManager.java index dffb08cf5..07339b2c2 100644 --- a/lime-infrastructure/src/main/java/com/programmers/lime/redis/vote/VoteRedisManager.java +++ b/lime-infrastructure/src/main/java/com/programmers/lime/redis/vote/VoteRedisManager.java @@ -27,18 +27,12 @@ public void addRanking( redisTemplate.expire(KEY + hobby, 1, TimeUnit.DAYS); } - public void increasePopularity( + public void updatePopularity( final String hobby, - final VoteRankingInfo rankingInfo - ) { - redisTemplate.opsForZSet().incrementScore(KEY + hobby, rankingInfo, 1); - } - - public void decreasePopularity( - final String hobby, - final VoteRankingInfo rankingInfo + final VoteRankingInfo rankingInfo, + final int delta ) { - redisTemplate.opsForZSet().incrementScore(KEY + hobby, rankingInfo, -1); + redisTemplate.opsForZSet().incrementScore(KEY + hobby, rankingInfo, delta); } public List getRanking(final String hobby) { @@ -56,7 +50,7 @@ public List getRanking(final String hobby) { .toList(); } - public void remove( + public void deleteRanking( final String hobby, final VoteRankingInfo rankingInfo ) { @@ -65,13 +59,13 @@ public void remove( public void updateRanking( final String hobby, - final boolean voting, + final boolean isVoting, final VoteRankingInfo rankingInfo ) { - if (voting) { - increasePopularity(hobby, rankingInfo); + if (isVoting) { + updatePopularity(hobby, rankingInfo, 1); } else { - remove(hobby, rankingInfo); + deleteRanking(hobby, rankingInfo); } } } From bbd55a968b0ba535557a2fbf987dcc2ec4e53175 Mon Sep 17 00:00:00 2001 From: Yiseul Park Date: Sat, 9 Mar 2024 16:50:03 +0900 Subject: [PATCH 3/5] =?UTF-8?q?fix:=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=EA=B0=80?= =?UTF-8?q?=20=EB=B9=84=EB=8F=99=EA=B8=B0=20=EC=B2=98=EB=A6=AC=20=EC=95=88?= =?UTF-8?q?=EB=90=98=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/programmers/lime/LimeApplication.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lime-api/src/main/java/com/programmers/lime/LimeApplication.java b/lime-api/src/main/java/com/programmers/lime/LimeApplication.java index 2ccb7e73b..67233ba95 100644 --- a/lime-api/src/main/java/com/programmers/lime/LimeApplication.java +++ b/lime-api/src/main/java/com/programmers/lime/LimeApplication.java @@ -3,8 +3,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.ConfigurationPropertiesScan; +import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; +@EnableAsync @SpringBootApplication @EnableScheduling @ConfigurationPropertiesScan({"com.programmers.lime.global.config.security.jwt", "com.programmers.lime.domains.auth"}) From 4242bc124c7a75e9dde86b5ea95ccedfbe7b5384 Mon Sep 17 00:00:00 2001 From: Yiseul Park Date: Sun, 10 Mar 2024 16:33:34 +0900 Subject: [PATCH 4/5] =?UTF-8?q?fix:=20=EC=B9=B4=EC=B9=B4=EC=98=A4=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EB=B0=A9=EC=8B=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=EC=9C=BC=EB=A1=9C=20=EC=9D=B8=ED=95=9C=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=ED=94=BD=EC=8A=A4=EC=B3=90=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../programmers/lime/domains/member/domain/MemberBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lime-domain/src/testFixtures/java/com/programmers/lime/domains/member/domain/MemberBuilder.java b/lime-domain/src/testFixtures/java/com/programmers/lime/domains/member/domain/MemberBuilder.java index 8ca26b00a..ca2d5fdfb 100644 --- a/lime-domain/src/testFixtures/java/com/programmers/lime/domains/member/domain/MemberBuilder.java +++ b/lime-domain/src/testFixtures/java/com/programmers/lime/domains/member/domain/MemberBuilder.java @@ -17,7 +17,7 @@ public class MemberBuilder { public static Member build(final Long memberId) { final SocialInfo socialInfo = new SocialInfo( - "357935205", + 357935205L, "test@test.com", "1.png", SocialType.NAVER, From 7d6de8c1e339d8a88276bc3cb1baa2e9000df0ac Mon Sep 17 00:00:00 2001 From: Yiseul Park Date: Sun, 10 Mar 2024 16:35:21 +0900 Subject: [PATCH 5/5] =?UTF-8?q?test:=20=EB=A0=88=EB=94=94=EC=8A=A4=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EB=B6=84=EB=A6=AC=EB=A1=9C=20=EC=9D=B8?= =?UTF-8?q?=ED=95=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vote/application/VoteServiceTest.java | 84 ------------------- 1 file changed, 84 deletions(-) diff --git a/lime-api/src/test/java/com/programmers/lime/domains/vote/application/VoteServiceTest.java b/lime-api/src/test/java/com/programmers/lime/domains/vote/application/VoteServiceTest.java index d35f0d987..170a79d34 100644 --- a/lime-api/src/test/java/com/programmers/lime/domains/vote/application/VoteServiceTest.java +++ b/lime-api/src/test/java/com/programmers/lime/domains/vote/application/VoteServiceTest.java @@ -36,8 +36,6 @@ import com.programmers.lime.error.EntityNotFoundException; import com.programmers.lime.error.ErrorCode; import com.programmers.lime.global.util.MemberUtils; -import com.programmers.lime.redis.vote.VoteRankingInfo; -import com.programmers.lime.redis.vote.VoteRedisManager; class VoteServiceTest extends IntegrationTest { @@ -59,9 +57,6 @@ class VoteServiceTest extends IntegrationTest { @MockBean private MemberUtils memberUtils; - @MockBean - private VoteRedisManager voteRedisManager; - private Item item1; private Item item2; private Vote vote; @@ -94,26 +89,11 @@ void createVoteTest() { given(memberUtils.getCurrentMemberId()) .willReturn(1L); - willDoNothing() - .given(voteRedisManager) - .addRanking(anyString(), any(VoteRankingInfo.class)); - // when final Long result = voteService.createVote(request); // then assertThat(result).isNotNull(); - - // verify - then(voteRedisManager).should(times(1)) - .addRanking( - String.valueOf(Hobby.BASKETBALL), - VoteRankingInfo.builder() - .id(Long.MAX_VALUE - result) - .item1Image(item1.getImage()) - .item2Image(item2.getImage()) - .build() - ); } @Test @@ -136,9 +116,6 @@ void createVoteWithSameItemTest() { assertThatThrownBy(() -> voteService.createVote(request)) .isInstanceOf(BusinessException.class) .hasFieldOrPropertyWithValue("errorCode", ErrorCode.VOTE_ITEM_DUPLICATED); - - // verify - then(voteRedisManager).shouldHaveNoInteractions(); } @Test @@ -162,9 +139,6 @@ void createVoteWithNotExistItemTest() { assertThatThrownBy(() -> voteService.createVote(request)) .isInstanceOf(EntityNotFoundException.class) .hasFieldOrPropertyWithValue("errorCode", ErrorCode.ITEM_NOT_FOUND); - - // verify - then(voteRedisManager).shouldHaveNoInteractions(); } } @@ -180,27 +154,11 @@ void participateVoteTest() { given(memberUtils.getCurrentMemberId()) .willReturn(1L); - willDoNothing() - .given(voteRedisManager) - .updateRanking(anyString(), eq(true), any(VoteRankingInfo.class)); - // when voteService.participateVote(voteId, itemId); // then assertThat(vote.getVoters()).hasSize(1); - - // verify - then(voteRedisManager).should(times(1)) - .updateRanking( - String.valueOf(vote.getHobby()), - true, - VoteRankingInfo.builder() - .id(Long.MAX_VALUE - voteId) - .item1Image(item1.getImage()) - .item2Image(item2.getImage()) - .build() - ); } @Test @@ -221,9 +179,6 @@ void reParticipateVoteTest() { // then assertThat(vote.getVoters()).hasSize(1); assertThat(voter.getItemId()).isEqualTo(reSelectedItemId); - - // verify - then(voteRedisManager).shouldHaveNoInteractions(); } @Test @@ -239,9 +194,6 @@ void participateVoteWithClosedVoteTest() { assertThatThrownBy(() -> voteService.participateVote(voteId, 1L)) .isInstanceOf(BusinessException.class) .hasFieldOrPropertyWithValue("errorCode", ErrorCode.VOTE_CANNOT_PARTICIPATE); - - // verify - then(voteRedisManager).shouldHaveNoInteractions(); } @Test @@ -257,9 +209,6 @@ void participateVoteWithNotExistItemTest() { assertThatThrownBy(() -> voteService.participateVote(voteId, notExistItemId)) .isInstanceOf(BusinessException.class) .hasFieldOrPropertyWithValue("errorCode", ErrorCode.VOTE_NOT_CONTAIN_ITEM); - - // verify - then(voteRedisManager).shouldHaveNoInteractions(); } } @@ -273,26 +222,11 @@ void cancelVoteTest() { given(memberUtils.getCurrentMemberId()) .willReturn(memberId); - willDoNothing() - .given(voteRedisManager) - .decreasePopularity(anyString(), any(VoteRankingInfo.class)); - // when voteService.cancelVote(voteId); // then assertThat(vote.getVoters()).isEmpty(); - - // verify - then(voteRedisManager).should(times(1)) - .decreasePopularity( - String.valueOf(vote.getHobby()), - VoteRankingInfo.builder() - .id(Long.MAX_VALUE - voteId) - .item1Image(item1.getImage()) - .item2Image(item2.getImage()) - .build() - ); } @Nested @@ -306,10 +240,6 @@ void deleteVoteTest() { given(memberUtils.getCurrentMemberId()) .willReturn(memberId); - willDoNothing() - .given(voteRedisManager) - .remove(anyString(), any(VoteRankingInfo.class)); - // when voteService.deleteVote(voteId); @@ -317,17 +247,6 @@ void deleteVoteTest() { assertThatThrownBy(() -> voteReader.read(voteId)) // 삭제된 투표 조회 시 EntityNotFoundException 발생 .isInstanceOf(EntityNotFoundException.class) .hasFieldOrPropertyWithValue("errorCode", ErrorCode.VOTE_NOT_FOUND); - - // verify - then(voteRedisManager).should(times(1)) - .remove( - String.valueOf(vote.getHobby()), - VoteRankingInfo.builder() - .id(Long.MAX_VALUE - voteId) - .item1Image(item1.getImage()) - .item2Image(item2.getImage()) - .build() - ); } @Test @@ -343,9 +262,6 @@ void deleteVoteWithNotOwnerTest() { assertThatThrownBy(() -> voteService.deleteVote(voteId)) .isInstanceOf(BusinessException.class) .hasFieldOrPropertyWithValue("errorCode", ErrorCode.VOTE_NOT_OWNER); - - // verify - then(voteRedisManager).shouldHaveNoInteractions(); } }