Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bug] 매입 이력 추가 후 목표수익률 이벤트 지연 로딩 문제 #275

Closed
yonghwankim-dev opened this issue Mar 18, 2024 · 0 comments · Fixed by #276
Closed
Assignees
Labels
bug Something isn't working

Comments

@yonghwankim-dev
Copy link
Member

yonghwankim-dev commented Mar 18, 2024

상황

매입 이력을 추가한후 알림 이벤트 서비스 수행중에 매입 이력 조회시 직전에 추가한 매입 이력이 조회되지 않는 문제가 발생합니다.

서비스 수행과정은 다음과 같습니다.

  1. 사용자가 매입 이력을 추가합니다.
  2. 매입 이력 추가 이벤트가 발생하여 알림 서비스를 수행합니다.
    • 알림 서비스는 매입 이력 추가에 따른 포트폴리오의 목표수익률, 최대손실율 도달 알림이 있습니다.
  3. 알림 전송 조건을 만족하면 알림을 전송하고 알림 데이터를 db에 저장합니다.

알림 서비스는 @EventListener가 적용된 리스너 메서드가 다음과 같이 호출합니다.

// 매입 이력 이벤트가 발생하면 포트폴리오 목표수익률에 달성하면 푸시 알림
@Async
@EventListener
public void notifyTargetGainBy(PushNotificationEvent event) {
PurchaseHistoryEventSendableParameter parameter = event.getValue();
PortfolioNotifyMessagesResponse response = notificationService.notifyTargetGainBy(
parameter.getPortfolioId());
log.info("매입 이력 이벤트로 인한 목표 수익률 달성 알림 결과 : {}", response);
}

notificationService.notifyPortfolioTargetGainMessages 메서드 수행중 TargetGainPolicy 객체가 알림 전송 조건에 맞는지 수행중 Portfolio 객체의 reachedTargetGain() 메서드 수행중 purchaseHistory 리스트를 조회하면서 지연 로딩을 기대합니다.

public boolean reachedTargetGain() {
List<PurchaseHistory> histories = portfolioHoldings.stream()
.map(PortfolioHolding::getPurchaseHistory)
.flatMap(Collection::stream)
.collect(Collectors.toList());
return reachedTargetGain(histories);
}

원인

매입 이력이 조회되지 않은 핵심적인 원인은 매입 이력 추가 서비스 과정에서 특정 Portfolio 엔티티를 조회하고 조건을 검증하는 과정에서 �지연 로딩 상태인 연관 엔티티(포트폴리오 종목 리스트, 매입 이력 리스트)들을 로딩했기 때문입니다. 그리고 알림 서비스에서 연관 엔티티들을 이미 로딩한 Portfolio 엔티티가 새로 조회되지 않고 기존 영속성 컨텍스트에 있는 엔티티 객체를 가져와서 직전에 추가한 매입 이력이 조회되지 않았습니다.

매입 이력 추가 서비스 과정중 Portfolio 엔티티 조회 및 연관 엔티티를 로딩한 코드는 다음과 같습니다.

Portfolio portfolio = findPortfolio(portfolioId);
PortfolioHolding findHolding = portfolio.getPortfolioHoldings().stream()
.filter(holding -> holding.getId().equals(portfolioHoldingId))
.findAny()
.orElseThrow(() -> new FineAntsException(PortfolioHoldingErrorCode.NOT_FOUND_PORTFOLIO_HOLDING));
PurchaseHistory history = request.toEntity(findHolding);
verifyCashSufficientForPurchase(portfolio, history.calculateInvestmentAmount());

  • portfolio.getPortfolioHoldings()의 stream 과정중 연관 엔티티인 포트폴리오 종목들을 로딩합니다.
  • verifyCashSufficientForPurchase() 메서드 실행 과정중에서 매입 이력 리스트를 로딩합니다.

위와 같은 매입 이력 추가 서비스 과정중 지연 로딩인 상태의 연관 엔티티들을 이미 로딩하였기 때문에 알림 서비스에서 직전에 추가한 매입 이력이 조회되지 않은 것입니다. (알림 서비스는 매입 이력 추가 서비스와 같은 트랜잭션을 공유합니다.)

해결방법

위와 같은 문제를 해결하기 위해서 db에 저장한 새로운 매입이력 엔티티 데이터를 리스트에 추가하도록 하여 문제를 해결하였습니다.

PurchaseHistory newPurchaseHistory = repository.save(history);
// 매입 이력 알림 이벤트를 위한 매입 이력 데이터 추가
findHolding.addPurchaseHistory(newPurchaseHistory);

@yonghwankim-dev yonghwankim-dev added the bug Something isn't working label Mar 18, 2024
@yonghwankim-dev yonghwankim-dev self-assigned this Mar 18, 2024
@yonghwankim-dev yonghwankim-dev linked a pull request Mar 18, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant