From 34f6641575f3b60dde2db5bee0cc49462a2a62da Mon Sep 17 00:00:00 2001 From: ckkim817 Date: Thu, 18 Jul 2024 07:09:28 +0900 Subject: [PATCH 1/2] =?UTF-8?q?[FEAT/#115]=20=EC=98=A8=EB=B3=B4=EB=94=A9?= =?UTF-8?q?=20=EC=8B=9C=20=EC=9D=B4=ED=83=88=ED=95=9C=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=20DB=EB=A5=BC=20=EC=82=AD=EC=A0=9C=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EC=8A=A4=EC=BC=80=EC=A4=84=EB=A7=81=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/sopt/seonyakServer/SeonyakServerApplication.java | 2 ++ .../domain/member/repository/MemberRepository.java | 4 ++++ .../domain/member/service/MemberService.java | 9 +++++++++ 3 files changed, 15 insertions(+) diff --git a/src/main/java/org/sopt/seonyakServer/SeonyakServerApplication.java b/src/main/java/org/sopt/seonyakServer/SeonyakServerApplication.java index cd4ad2d..c602143 100644 --- a/src/main/java/org/sopt/seonyakServer/SeonyakServerApplication.java +++ b/src/main/java/org/sopt/seonyakServer/SeonyakServerApplication.java @@ -2,8 +2,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication +@EnableScheduling public class SeonyakServerApplication { public static void main(String[] args) { diff --git a/src/main/java/org/sopt/seonyakServer/domain/member/repository/MemberRepository.java b/src/main/java/org/sopt/seonyakServer/domain/member/repository/MemberRepository.java index faf0c70..5781d45 100644 --- a/src/main/java/org/sopt/seonyakServer/domain/member/repository/MemberRepository.java +++ b/src/main/java/org/sopt/seonyakServer/domain/member/repository/MemberRepository.java @@ -1,5 +1,6 @@ package org.sopt.seonyakServer.domain.member.repository; +import java.time.LocalDateTime; import java.util.Optional; import org.sopt.seonyakServer.domain.member.model.Member; import org.sopt.seonyakServer.domain.member.model.SocialType; @@ -21,4 +22,7 @@ default Member findMemberByIdOrThrow(Long id) { return findMemberById(id) .orElseThrow(() -> new CustomException(ErrorType.NOT_FOUND_MEMBER_ERROR)); } + + // phoneNumber가 null이고 updatedAt 시간이 time만큼 보다 더 이전인 모든 Member 엔티티를 삭제 + void deleteByPhoneNumberIsNullAndUpdatedAtBefore(LocalDateTime time); } diff --git a/src/main/java/org/sopt/seonyakServer/domain/member/service/MemberService.java b/src/main/java/org/sopt/seonyakServer/domain/member/service/MemberService.java index 6a17345..8f3297f 100644 --- a/src/main/java/org/sopt/seonyakServer/domain/member/service/MemberService.java +++ b/src/main/java/org/sopt/seonyakServer/domain/member/service/MemberService.java @@ -1,6 +1,7 @@ package org.sopt.seonyakServer.domain.member.service; import jakarta.annotation.PostConstruct; +import java.time.LocalDateTime; import java.util.Random; import lombok.RequiredArgsConstructor; import net.nurigo.sdk.NurigoApp; @@ -28,6 +29,7 @@ import org.sopt.seonyakServer.global.exception.model.CustomException; import org.springframework.beans.factory.annotation.Value; import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -214,4 +216,11 @@ private void validPhoneNumberDuplication(String phoneNumber) { throw new CustomException(ErrorType.PHONE_NUMBER_DUP_ERROR); } } + + @Scheduled(fixedRate = 43200000) // 12시간마다 실행 (43200000 밀리초) + @Transactional + public void deleteMembersWithNullPhoneNumber() { + LocalDateTime oneHourAgo = LocalDateTime.now().minusMinutes(60); + memberRepository.deleteByPhoneNumberIsNullAndUpdatedAtBefore(oneHourAgo); + } } From 160231223253cd296128c3ff68266cc87d4cdf2c Mon Sep 17 00:00:00 2001 From: ckkim817 Date: Thu, 18 Jul 2024 07:18:47 +0900 Subject: [PATCH 2/2] =?UTF-8?q?[FIX/#115]=20Transactional=20=EC=96=B4?= =?UTF-8?q?=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=AC=B6=EB=8A=94=20=EB=B2=94=EC=9C=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 내부에서 호출되는 private 메서드에는 자동으로 Transactional이 적용 --- .../domain/member/service/MemberService.java | 12 ++++++++---- .../global/auth/redis/service/CodeService.java | 2 -- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/sopt/seonyakServer/domain/member/service/MemberService.java b/src/main/java/org/sopt/seonyakServer/domain/member/service/MemberService.java index 8f3297f..0062fb3 100644 --- a/src/main/java/org/sopt/seonyakServer/domain/member/service/MemberService.java +++ b/src/main/java/org/sopt/seonyakServer/domain/member/service/MemberService.java @@ -63,6 +63,7 @@ public void init() { } // JWT Access Token 생성 + @Transactional public LoginSuccessResponse create( final String authorizationCode, final MemberLoginRequest loginRequest @@ -73,7 +74,7 @@ public LoginSuccessResponse create( } // 소셜 플랫폼으로부터 해당 유저 정보를 받아옴 - public MemberInfoResponse getMemberInfoResponse( + private MemberInfoResponse getMemberInfoResponse( final String authorizationCode, final MemberLoginRequest loginRequest ) { @@ -106,14 +107,14 @@ private LoginSuccessResponse getTokenDto(final MemberInfoResponse memberInfoResp } } - public boolean isExistingMember( + private boolean isExistingMember( final SocialType socialType, final String socialId ) { return memberRepository.findBySocialTypeAndSocialId(socialType, socialId).isPresent(); } - public Long getMemberIdBySocialId( + private Long getMemberIdBySocialId( final SocialType socialType, final String socialId ) { @@ -124,13 +125,14 @@ public Long getMemberIdBySocialId( return member.getId(); } - public LoginSuccessResponse getTokenByMemberId(final Long id) { + private LoginSuccessResponse getTokenByMemberId(final Long id) { MemberAuthentication memberAuthentication = new MemberAuthentication(id, null, null); return LoginSuccessResponse.of(jwtTokenProvider.issueAccessToken(memberAuthentication)); } // 닉네임 유효성 검증 + @Transactional(readOnly = true) public void validNickname(final NicknameRequest nicknameRequest) { if (!nicknameRequest.nickname().matches(NICKNAME_PATTERN)) { // 형식 체크 throw new CustomException(ErrorType.INVALID_NICKNAME_ERROR); @@ -168,6 +170,7 @@ public MemberJoinResponse patchMemberJoin(MemberJoinRequest memberJoinRequest) { ); } + @Transactional public void sendMessage(SendCodeRequest sendCodeRequest) { Message message = new Message(); @@ -198,6 +201,7 @@ private String generateRandomNumber(int digitCount) { } // 인증번호 일치 여부 확인 + @Transactional public void verifyCode(VerifyCodeRequest verifyCodeRequest) { String number = verifyCodeRequest.phoneNumber().replaceAll("-", ""); diff --git a/src/main/java/org/sopt/seonyakServer/global/auth/redis/service/CodeService.java b/src/main/java/org/sopt/seonyakServer/global/auth/redis/service/CodeService.java index dcf8ae8..174cd31 100644 --- a/src/main/java/org/sopt/seonyakServer/global/auth/redis/service/CodeService.java +++ b/src/main/java/org/sopt/seonyakServer/global/auth/redis/service/CodeService.java @@ -14,7 +14,6 @@ public class CodeService { private final CodeRepository codeRepository; - @Transactional public void saveVerificationCode( final String phoneNumber, final String verificationCode @@ -27,7 +26,6 @@ public void saveVerificationCode( ); } - @Transactional(readOnly = true) public String findCodeByPhoneNumber(final String phoneNumber) { Code code = codeRepository.findByPhoneNumber(phoneNumber).orElseThrow( () -> new CustomException(ErrorType.NO_VERIFICATION_REQUEST_HISTORY)