Skip to content

탈퇴 회원 완전 삭제 크론이 자기 호출이라 @Transactional이 적용되지 않는다 #267

Description

@howudong

무엇이

LeftMemberPurgeService.purgeExpired()(크론 진입점)가 같은 클래스의 purge()를 직접 부른다. 프록시를 거치지 않아 purge()의 @Transactional이 적용되지 않는다.

근거

  • LeftMemberPurgeService.kt:40-43: @Scheduled fun purgeExpired() { purge() }
  • LeftMemberPurgeService.kt:45: @Transactional fun purge(). 자기 호출이라 트랜잭션이 열리지 않는다.
  • MemberDeviceRepository.deleteAllByMemberId는 @Modifying @Query이고 @Transactional이 없다. 트랜잭션 없이 부르면 TransactionRequiredException이 난다.
  • refreshTokenRepository.deleteAllByMemberId, notificationRepository.deleteAllByMemberId는 querydsl Impl의 @Transactional로 각각 따로 커밋된다.

무엇이 문제인가

ditto.member.purge.dry-run=false로 켜면 04:00 크론에서 토큰·알림만 지워지고 기기 삭제에서 예외가 난다. 회원은 지워지지 않고 루프도 멈춘다. 다음 날에도 같은 회원에서 같은 식으로 실패해서 "30일 뒤 완전 삭제"가 끝나지 않는다.

지금은 기본값이 dry-run=true라 대상 조회만 하고 끝나서 드러나지 않는다. dry-run을 끄기 전에 고쳐야 한다.

테스트가 이 문제를 잡지 못한다. MemberLeaveTest는 purge()를 테스트 쪽 트랜잭션 안에서 부르고, 크론 진입점 테스트는 삭제 대상이 없는 경우만 본다.

수정 방향

  • @Scheduled를 purge()에 직접 붙이거나, 크론 진입점을 다른 빈으로 나눈다.
  • dry-run을 끈 상태로 크론 진입점을 불러 회원까지 지워지는지 보는 테스트를 추가한다.

배경

#138 PR의 버그 리뷰에서 나왔다. 스케줄러 스레드 변경과는 상관없이 원래 있던 문제다.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions