Skip to content

Commit

Permalink
[BSVR-253] Mixpanel Event Listener 사용하도록 리팩토링 (#186)
Browse files Browse the repository at this point in the history
* refactor : 롤백, TODO 재정의

* feat : MixpanelEvent 구현

* refactor : MixpanelEventListener 사용

* refactor : MixpanelEvent 비즈니스 로직과 분리

* refactor : 불필요한 코드 제거

* refactor : MixpanelRepository 의존성 제거
  • Loading branch information
wjdwnsdnjs13 authored Sep 9, 2024
1 parent aa1fa16 commit 4a2442c
Show file tree
Hide file tree
Showing 15 changed files with 110 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
import org.depromeet.spot.application.review.dto.response.BaseReviewResponse;
import org.depromeet.spot.usecase.port.in.review.CreateReviewUsecase;
import org.depromeet.spot.usecase.port.in.review.CreateReviewUsecase.CreateReviewResult;
import org.depromeet.spot.usecase.service.event.MixpanelEvent;
import org.depromeet.spot.usecase.service.event.MixpanelEvent.MixpanelEventName;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
Expand All @@ -36,6 +39,8 @@
@RequestMapping("/api/v1")
public class CreateReviewController {

private final ApplicationEventPublisher applicationEventPublisher;

private final CreateReviewUsecase createReviewUsecase;

@CurrentMember
Expand All @@ -49,6 +54,11 @@ public BaseReviewResponse create(

CreateReviewResult result =
createReviewUsecase.create(blockId, memberId, request.toCommand());

// 믹스패널 이벤트(후기 등록 완료) 호출
applicationEventPublisher.publishEvent(
new MixpanelEvent(MixpanelEventName.REVIEW_REGISTER, String.valueOf(memberId)));

return BaseReviewResponse.from(result);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
import org.depromeet.spot.usecase.port.in.review.ReadReviewUsecase.MyRecentReviewResult;
import org.depromeet.spot.usecase.port.in.review.ReadReviewUsecase.MyReviewListResult;
import org.depromeet.spot.usecase.port.in.review.ReadReviewUsecase.ReadReviewResult;
import org.depromeet.spot.usecase.service.event.MixpanelEvent;
import org.depromeet.spot.usecase.service.event.MixpanelEvent.MixpanelEventName;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

Expand All @@ -36,6 +39,8 @@
@RequestMapping("/api/v1")
public class ReadReviewController {

private final ApplicationEventPublisher applicationEventPublisher;

private final ReadReviewUsecase readReviewUsecase;

@CurrentMember
Expand Down Expand Up @@ -132,6 +137,11 @@ public BaseReviewResponse findReviewByReviewId(
@PathVariable("reviewId") @NotNull @Parameter(description = "리뷰 PK", required = true)
Long reviewId) {
ReadReviewResult readReviewResult = readReviewUsecase.findReviewById(reviewId, memberId);

// 믹스패널 이벤트(조회수) 발생
applicationEventPublisher.publishEvent(
new MixpanelEvent(MixpanelEventName.REVIEW_OPEN_COUNT, String.valueOf(memberId)));

return BaseReviewResponse.from(readReviewResult.review());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

import org.depromeet.spot.application.common.annotation.CurrentMember;
import org.depromeet.spot.usecase.port.in.review.like.ReviewLikeUsecase;
import org.depromeet.spot.usecase.service.event.MixpanelEvent;
import org.depromeet.spot.usecase.service.event.MixpanelEvent.MixpanelEventName;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
Expand All @@ -23,6 +26,8 @@
@RequestMapping("/api/v1/reviews")
public class ReviewLikeController {

private final ApplicationEventPublisher applicationEventPublisher;

private final ReviewLikeUsecase reviewLikeUsecase;

@CurrentMember
Expand All @@ -32,6 +37,12 @@ public class ReviewLikeController {
public void toggleLike(
@PathVariable @Positive @NotNull final Long reviewId,
@Parameter(hidden = true) Long memberId) {
reviewLikeUsecase.toggleLike(memberId, reviewId);
boolean result = reviewLikeUsecase.toggleLike(memberId, reviewId);
if (result) {
// 리뷰 공감 추이 이벤트 발생
applicationEventPublisher.publishEvent(
new MixpanelEvent(
MixpanelEventName.REVIEW_LIKE_COUNT, String.valueOf(memberId)));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
import org.depromeet.spot.application.review.dto.response.scrap.MyScrapListResponse;
import org.depromeet.spot.usecase.port.in.review.scrap.ReviewScrapUsecase;
import org.depromeet.spot.usecase.port.in.review.scrap.ReviewScrapUsecase.MyScrapListResult;
import org.depromeet.spot.usecase.service.event.MixpanelEvent;
import org.depromeet.spot.usecase.service.event.MixpanelEvent.MixpanelEventName;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
Expand All @@ -29,6 +32,8 @@
@RequestMapping("/api/v1/reviews")
public class ReviewScrapController {

private final ApplicationEventPublisher applicationEventPublisher;

private final ReviewScrapUsecase reviewScrapUsecase;

@CurrentMember
Expand All @@ -38,7 +43,13 @@ public class ReviewScrapController {
public boolean toggleScrap(
@PathVariable @Positive @NotNull final Long reviewId,
@Parameter(hidden = true) Long memberId) {
return reviewScrapUsecase.toggleScrap(memberId, reviewId);
boolean result = reviewScrapUsecase.toggleScrap(memberId, reviewId);

// 믹스패널 이벤트(스크랩 수) 발생
applicationEventPublisher.publishEvent(
new MixpanelEvent(MixpanelEventName.REVIEW_SCRAP_COUNT, String.valueOf(memberId)));

return result;
}

@CurrentMember
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

import java.io.IOException;

import org.depromeet.spot.domain.mixpanel.MixpanelEvent;
import org.depromeet.spot.infrastructure.mixpanel.property.MixpanelProperties;
import org.depromeet.spot.usecase.port.out.mixpanel.MixpanelRepository;
import org.depromeet.spot.usecase.service.event.MixpanelEvent;
import org.json.JSONObject;
import org.springframework.stereotype.Component;

Expand All @@ -25,14 +25,18 @@ public class MixpanelRepositoryImpl implements MixpanelRepository {
// mixpanelEvent는 eventName(이 단위로 이벤트가 묶임)
// distinctId는 사용자를 구분하는 데 사용됨.
@Override
public void eventTrack(MixpanelEvent mixpanelEvent, String distinctId) {
public void eventTrack(MixpanelEvent mixpanelEvent) {
try {

// 믹스패널 이벤트 메시지 생성
MessageBuilder messageBuilder = new MessageBuilder(mixpanelProperties.token());

// 이벤트 생성
JSONObject sentEvent = messageBuilder.event(distinctId, mixpanelEvent.getValue(), null);
JSONObject sentEvent =
messageBuilder.event(
mixpanelEvent.getDistinctId(),
mixpanelEvent.getMixpanelEventName().getValue(),
null);

// 만든 여러 이벤트를 delivery
ClientDelivery delivery = new ClientDelivery();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package org.depromeet.spot.usecase.port.in.review.like;

public interface ReviewLikeUsecase {
void toggleLike(Long memberId, long reviewId);
boolean toggleLike(Long memberId, long reviewId);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.depromeet.spot.usecase.port.out.mixpanel;

import org.depromeet.spot.domain.mixpanel.MixpanelEvent;
import org.depromeet.spot.usecase.service.event.MixpanelEvent;

public interface MixpanelRepository {
void eventTrack(MixpanelEvent mixpanelEvent, String distinctId);
void eventTrack(MixpanelEvent mixpanelEvent);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.depromeet.spot.usecase.service.event;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public class MixpanelEvent {

private final MixpanelEventName mixpanelEventName;

private final String distinctId;

@Getter
public enum MixpanelEventName {
REVIEW_REGISTER("review_register"),
REVIEW_OPEN_COUNT("review_open_count"),
REVIEW_LIKE_COUNT("review_like_count"),
REVIEW_SCRAP_COUNT("review_scrap_count"),
;

String value;

MixpanelEventName(String value) {
this.value = value;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.depromeet.spot.usecase.service.event;

import org.depromeet.spot.usecase.port.out.mixpanel.MixpanelRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import lombok.RequiredArgsConstructor;

@Component
@RequiredArgsConstructor
public class MixpanelEventListener {

private static final Logger log = LoggerFactory.getLogger(MixpanelEventListener.class);
private final MixpanelRepository mixpanelRepository;

@Async
@EventListener
public void eventTrack(MixpanelEvent mixpanelEvent) {
mixpanelRepository.eventTrack(mixpanelEvent);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@
import java.util.Map;

import org.depromeet.spot.domain.member.Member;
import org.depromeet.spot.domain.mixpanel.MixpanelEvent;
import org.depromeet.spot.domain.review.Review;
import org.depromeet.spot.domain.review.keyword.Keyword;
import org.depromeet.spot.usecase.port.in.review.CreateReviewUsecase;
import org.depromeet.spot.usecase.port.out.member.MemberRepository;
import org.depromeet.spot.usecase.port.out.mixpanel.MixpanelRepository;
import org.depromeet.spot.usecase.port.out.review.ReviewRepository;
import org.depromeet.spot.usecase.service.member.processor.MemberLevelProcessor;
import org.depromeet.spot.usecase.service.review.processor.ReviewCreationProcessor;
Expand All @@ -31,7 +29,6 @@ public class CreateReviewService implements CreateReviewUsecase {
private final ReviewImageProcessor reviewImageProcessor;
private final ReviewKeywordProcessor reviewKeywordProcessor;
private final MemberLevelProcessor memberLevelProcessor;
private final MixpanelRepository mixpanelRepository;

@Override
@Transactional
Expand All @@ -49,9 +46,6 @@ public CreateReviewResult create(Long blockId, Long memberId, CreateReviewComman

Member levelUpdateMember = memberLevelProcessor.calculateAndUpdateMemberLevel(member);

// 믹스패널 이벤트(후기 등록 완료) 호출
mixpanelRepository.eventTrack(MixpanelEvent.REVIEW_REGISTER, String.valueOf(memberId));

return new CreateReviewResult(savedReview, levelUpdateMember, review.getSeat());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import java.util.stream.Collectors;

import org.depromeet.spot.domain.member.Member;
import org.depromeet.spot.domain.mixpanel.MixpanelEvent;
import org.depromeet.spot.domain.review.Review;
import org.depromeet.spot.domain.review.Review.ReviewType;
import org.depromeet.spot.domain.review.Review.SortCriteria;
Expand All @@ -16,7 +15,6 @@
import org.depromeet.spot.domain.team.BaseballTeam;
import org.depromeet.spot.usecase.port.in.review.ReadReviewUsecase;
import org.depromeet.spot.usecase.port.out.member.MemberRepository;
import org.depromeet.spot.usecase.port.out.mixpanel.MixpanelRepository;
import org.depromeet.spot.usecase.port.out.review.BlockTopKeywordRepository;
import org.depromeet.spot.usecase.port.out.review.KeywordRepository;
import org.depromeet.spot.usecase.port.out.review.ReviewImageRepository;
Expand Down Expand Up @@ -48,7 +46,6 @@ public class ReadReviewService implements ReadReviewUsecase {
private final ReviewScrapRepository reviewScrapRepository;
private final ReadReviewProcessor readReviewProcessor;
private final PaginationProcessor paginationProcessor;
private final MixpanelRepository mixpanelRepository;

private static final int TOP_KEYWORDS_LIMIT = 5;
private static final int TOP_IMAGES_LIMIT = 5;
Expand Down Expand Up @@ -192,9 +189,6 @@ public ReadReviewResult findReviewById(Long reviewId, Long memberId) {
Review review = reviewRepository.findById(reviewId);
Review reviewWithKeywords = mapKeywordsToSingleReview(review);

// 믹스패널 이벤트(조회수) 발생
mixpanelRepository.eventTrack(MixpanelEvent.REVIEW_OPEN_COUNT, String.valueOf(memberId));

return ReadReviewResult.builder().review(reviewWithKeywords).build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,18 @@ public class ReviewLikeService implements ReviewLikeUsecase {
private final UpdateReviewUsecase updateReviewUsecase;
private final ReviewLikeRepository reviewLikeRepository;

// TODO : Service 코드와 분리하기
// private final MixpanelRepository mixpanelRepository;

@Override
@DistributedLock(key = "#reviewId")
public void toggleLike(final Long memberId, final long reviewId) {
public boolean toggleLike(final Long memberId, final long reviewId) {
Review review = readReviewUsecase.findById(reviewId);

if (reviewLikeRepository.existsBy(memberId, reviewId)) {
cancelLike(memberId, reviewId, review);
return;
return false;
}

addLike(memberId, reviewId, review);

// TODO : 테스트 시에도 이벤트 발생함.
// 믹스패널 이벤트(좋아요 수) 발생
// mixpanelRepository.eventTrack(MixpanelEvent.REVIEW_LIKE_COUNT,
// String.valueOf(memberId));
return true;
}

public void cancelLike(final long memberId, final long reviewId, Review review) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@

import java.util.List;

import org.depromeet.spot.domain.mixpanel.MixpanelEvent;
import org.depromeet.spot.domain.review.Review;
import org.depromeet.spot.domain.review.scrap.ReviewScrap;
import org.depromeet.spot.usecase.port.in.review.ReadReviewUsecase;
import org.depromeet.spot.usecase.port.in.review.UpdateReviewUsecase;
import org.depromeet.spot.usecase.port.in.review.page.PageCommand;
import org.depromeet.spot.usecase.port.in.review.scrap.ReviewScrapUsecase;
import org.depromeet.spot.usecase.port.out.mixpanel.MixpanelRepository;
import org.depromeet.spot.usecase.port.out.review.ReviewScrapRepository;
import org.depromeet.spot.usecase.service.review.ReadReviewService;
import org.depromeet.spot.usecase.service.review.processor.PaginationProcessor;
Expand All @@ -31,8 +29,6 @@ public class ReviewScrapService implements ReviewScrapUsecase {
private final ReadReviewProcessor readReviewProcessor;
private final PaginationProcessor paginationProcessor;

private final MixpanelRepository mixpanelRepository;

@Override
public MyScrapListResult findMyScrappedReviews(
Long memberId, MyScrapCommand command, PageCommand pageCommand) {
Expand Down Expand Up @@ -91,9 +87,6 @@ public boolean toggleScrap(final long memberId, final long reviewId) {

addScrap(memberId, reviewId, review);

// 믹스패널 이벤트(스크랩 수) 발생
mixpanelRepository.eventTrack(MixpanelEvent.REVIEW_SCRAP_COUNT, String.valueOf(memberId));

return true;
}

Expand Down
Loading

0 comments on commit 4a2442c

Please sign in to comment.