-
Notifications
You must be signed in to change notification settings - Fork 1
feat: 스케줄러추가 #73
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
feat: 스케줄러추가 #73
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| package com.todaysound.todaysound_server.domain.summary.infra.scheduler; | ||
|
|
||
| import com.todaysound.todaysound_server.domain.summary.repository.SummaryRepository; | ||
| import java.time.LocalDateTime; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.scheduling.annotation.Scheduled; | ||
| import org.springframework.stereotype.Component; | ||
| import org.springframework.transaction.annotation.Transactional; | ||
|
|
||
| @Component | ||
| @RequiredArgsConstructor | ||
| public class SummaryCleanupScheduler { | ||
|
|
||
| private final SummaryRepository summaryRepository; | ||
|
|
||
| @Transactional | ||
| @Scheduled(cron = "0 0 3 * * *") // 매일 새벽 3시에 실행 | ||
| public void deleteOldSummaries() { | ||
|
|
||
| LocalDateTime threshold = LocalDateTime.now().minusDays(7); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
제안:
@Configuration
public class AppConfig {
@Bean
public Clock clock() {
return Clock.systemDefaultZone(); // 또는 Clock.systemUTC()
}
}
@Component
@RequiredArgsConstructor
public class SummaryCleanupScheduler {
private final SummaryRepository summaryRepository;
private final Clock clock; // Clock 주입
@Transactional
@Scheduled(cron = "0 0 3 * * *")
public void deleteOldSummaries() {
LocalDateTime threshold = LocalDateTime.now(clock).minusDays(7); // 주입받은 clock 사용
summaryRepository.deleteByCreatedAtBefore(threshold);
}
}테스트에서는 |
||
| summaryRepository.deleteByCreatedAtBefore(threshold); | ||
|
Comment on lines
+20
to
+21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
이를 위해 Repository에 // SummaryRepository.java
@Modifying
@Query("DELETE FROM Summary s WHERE s.createdAt < :threshold")
int deleteBatchByCreatedAtBefore(@Param("threshold") LocalDateTime threshold, Pageable pageable);
// SummaryCleanupScheduler.java
public void deleteOldSummaries() {
LocalDateTime threshold = LocalDateTime.now().minusDays(7);
int deletedCount;
do {
// 예를 들어 1000개씩 삭제
deletedCount = summaryRepository.deleteBatchByCreatedAtBefore(threshold, PageRequest.of(0, 1000));
} while (deletedCount > 0);
}위 예시는 JPA의 |
||
|
|
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,10 +23,8 @@ | |
| @Entity | ||
| @Getter | ||
| @Setter | ||
| @Builder | ||
| @Table(name = "users") | ||
| @NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
| @AllArgsConstructor(access = AccessLevel.PRIVATE) | ||
| public class User extends BaseEntity { | ||
|
|
||
| // ********************************* static final 상수 필드 *********************************/ | ||
|
|
@@ -69,7 +67,6 @@ public class User extends BaseEntity { | |
| /** | ||
| * 사용자 활성 상태 기본값 true, 탈퇴 시 false로 변경 | ||
| */ | ||
| @Builder.Default | ||
| @Column(name = "is_active", nullable = false) | ||
| private boolean isActive = true; | ||
|
|
||
|
|
@@ -92,12 +89,9 @@ public class User extends BaseEntity { | |
| * cascade = CascadeType.ALL: User 삭제 시 관련 Subscription도 함께 삭제 orphanRemoval = true: 고아 객체(연관관계가 끊어진 객체) 자동 삭제 fetch | ||
| * = FetchType.LAZY: 지연 로딩으로 성능 최적화 | ||
| */ | ||
| @Builder.Default | ||
| @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true, | ||
| fetch = FetchType.LAZY) | ||
| @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) | ||
| private List<Subscription> subscriptions = new ArrayList<>(); | ||
|
|
||
| @Builder.Default | ||
| @OneToMany(mappedBy = "user", fetch = FetchType.LAZY, cascade = CascadeType.ALL) | ||
| private List<FCM_Token> fcmTokenList = new ArrayList<>(); | ||
|
|
||
|
|
@@ -162,4 +156,40 @@ public void addFcmToken(FCM_Token fcmToken) { | |
| // FCM_Token의 user 필드는 builder에서 이미 설정되어야 함 | ||
| this.fcmTokenList.add(fcmToken); | ||
| } | ||
|
|
||
| @Builder | ||
| private User(String userId, String hashedSecret, String secretFingerprint, UserType userType, boolean isActive, | ||
| String plainSecret, List<FCM_Token> fcmTokenList) { | ||
| this.userId = userId; | ||
| this.hashedSecret = hashedSecret; | ||
| this.secretFingerprint = secretFingerprint; | ||
| this.userType = userType; | ||
| this.isActive = isActive; | ||
| this.plainSecret = plainSecret; | ||
| this.fcmTokenList = fcmTokenList; | ||
| } | ||
|
|
||
| public static User createAnonymous(String userId, String hashedSecret, String secretFingerprint, UserType userType, | ||
| boolean isActive, String plainSecret, List<FCM_Token> fcmTokenList) { | ||
| return User.builder().userId(userId) | ||
| .hashedSecret(hashedSecret) | ||
| .secretFingerprint(secretFingerprint) | ||
| .userType(userType) | ||
| .isActive(isActive) | ||
| .plainSecret(plainSecret) | ||
| .fcmTokenList(fcmTokenList) | ||
| .build(); | ||
| } | ||
|
Comment on lines
160
to
182
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
의도하신 대로 예시: @Entity
@Getter
@Setter
//@Builder // <- 제거
@Table(name = "users")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
//@AllArgsConstructor(access = AccessLevel.PRIVATE) // <- 제거
public class User extends BaseEntity {
//...
} |
||
|
|
||
| public static User create(String userId, String hashedSecret, String secretFingerprint, UserType userType, | ||
| boolean isActive, String plainSecret) { | ||
| return User.builder().userId(userId) | ||
| .hashedSecret(hashedSecret) | ||
| .secretFingerprint(secretFingerprint) | ||
| .userType(userType) | ||
| .isActive(isActive) | ||
| .plainSecret(plainSecret) | ||
| .fcmTokenList(new ArrayList<>()) | ||
| .build(); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Builder애노테이션이 클래스 레벨(30라인)과 생성자 레벨(104라인)에 중복으로 사용되었습니다. Lombok은 한 클래스에 여러 개의@Builder를 허용하지 않으므로 컴파일 오류가 발생합니다.새로 추가된
create정적 팩토리 메서드와 생성자 빌더 패턴을 사용하시려면, 클래스 레벨의@Builder와@AllArgsConstructor를 제거해야 합니다.예시:
이렇게 수정하면 새로 추가한 빌더만 사용되어 문제가 해결됩니다.