Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.security.core.parameters.P;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
Expand Down Expand Up @@ -178,7 +177,7 @@ List<Diaries> findNearDiariesCandidates(
@Param("userId") Long userId
);

List<Diaries> findAllByCreatedAtBetween(LocalDateTime startDateTime, LocalDateTime endDateTime);
List<Diaries> findAllByUsersAndCreatedAtBetween(Users user, LocalDateTime startDateTime, LocalDateTime endDateTime);

@Modifying
@Query("UPDATE Diaries d SET d.memoryDiaryAlarmCoolTime = d.memoryDiaryAlarmCoolTime - 1 WHERE d.memoryDiaryAlarmCoolTime > 0")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,25 +140,29 @@ private void reserveSendPushNotificationByFcm(LocalDateTime alarmTime, Users use
private void reserveSendPushNotificationByFcm(LocalDateTime alarmTime, Users user, AlaramType alaramType, Map<Long, ScheduledFuture<?>> scheduledTasks, String memoryDiaryAlarmDaysAgo, Long diaryId) {
ScheduledFuture<?> future = taskScheduler.schedule(() -> {
try {
ZoneId zoneId = ZoneId.of("Asia/Seoul");
LocalDate today = LocalDate.now(zoneId);
List<Diaries> diaries = diaryRepository.findAllByCreatedAtBetween(
today.atStartOfDay(), // 오늘 00:00:00
today.plusDays(1).atStartOfDay() // 내일 00:00:00
);

if (scheduledTasks.containsKey(user.getId())) {
// 이미 예약된 알림이 있는 경우, 기존 예약 취소
scheduledTasks.get(user.getId()).cancel(false);
scheduledTasks.remove(user.getId());
}
if (alaramType == AlaramType.DAILY_SUMMARY && diaries.size() < 2) return; // 일일 요약 알림은 오늘 작성한 일기가 2개 미만이면 보내지 않음
else if (alaramType == AlaramType.DAILY_SUMMARY && diaries.size() >= 2) {
summaryCommandService.summarize(
DiarySummaryRequestDTO.SummarizeDTO.builder()
.date(today)
.build()
if (alaramType == AlaramType.DAILY_SUMMARY) {
ZoneId zoneId = ZoneId.of("Asia/Seoul");
LocalDate today = LocalDate.now(zoneId);
List<Diaries> diaries = diaryRepository.findAllByUsersAndCreatedAtBetween(
user,
today.atStartOfDay(), // 오늘 00:00:00
today.plusDays(1).atStartOfDay() // 내일 00:00:00
);
if (diaries.size() < 2) {
return; // 오늘 작성한 일기가 2개 미만이면 일일 요약 알림 보내지 않음
} else {
summaryCommandService.summarizeByDailySummaryAlarm(
user.getId(),
DiarySummaryRequestDTO.SummarizeDTO.builder()
.date(today)
.build()
);
}
}
fcmPushSender.sendPushNotification(user.getFcmToken(), alaramType, memoryDiaryAlarmDaysAgo, diaryId);
} finally {
Expand Down Expand Up @@ -348,6 +352,7 @@ public AlarmResponseDTO.DailySummaryAlarmOnResponseDTO sendDailySummaryPushAlarm
}
if (getDailySummaryAlarm.getAlarmTime().isAfter(LocalTime.now())) { // 현재 시간보다 이전 알림 시간은 예약하지 않음
LocalDateTime ALARM_TIME = getAlarmLocalDateTime(getDailySummaryAlarm.getAlarmTime());
System.out.println("하루 요약 알림 예약!!!");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

디버깅 목적으로 추가된 System.out.println 구문이 코드에 남아있습니다. 프로덕션 코드에는 이러한 출력문이 포함되지 않는 것이 좋습니다. 로깅이 필요하다면, 다른 서비스 클래스에서처럼 @Slf4j 어노테이션과 로거를 사용해주세요.

reserveSendPushNotificationByFcm(ALARM_TIME, getUser, AlaramType.DAILY_SUMMARY, dailySummaryAlarmScheduledTasks);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@

import TtattaBackend.ttatta.apiPayload.code.status.ErrorStatus;
import TtattaBackend.ttatta.apiPayload.exception.handler.ExceptionHandler;
import com.google.firebase.messaging.FirebaseMessaging;
import com.google.firebase.messaging.FirebaseMessagingException;
import com.google.firebase.messaging.Message;
import com.google.firebase.messaging.Notification;
import com.google.firebase.messaging.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
import TtattaBackend.ttatta.web.dto.DiarySummaryResponseDTO;

public interface SummaryCommandService {
public SummaryDiary summarize(DiarySummaryRequestDTO.SummarizeDTO request);
public SummaryDiary reSummarize(DiarySummaryRequestDTO.SummarizeDTO request);
public DiarySummaryResponseDTO.DiarySummaryResultDTO getSummary(DiarySummaryRequestDTO.GetDiarySummaryDTO request);
SummaryDiary summarize(DiarySummaryRequestDTO.SummarizeDTO request);
SummaryDiary summarizeByDailySummaryAlarm(Long userId, DiarySummaryRequestDTO.SummarizeDTO request);
SummaryDiary reSummarize(DiarySummaryRequestDTO.SummarizeDTO request);
DiarySummaryResponseDTO.DiarySummaryResultDTO getSummary(DiarySummaryRequestDTO.GetDiarySummaryDTO request);
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,40 @@ public SummaryDiary summarize(DiarySummaryRequestDTO.SummarizeDTO request) {
return summaryDiary;
}

@Override
public SummaryDiary summarizeByDailySummaryAlarm(Long userId, DiarySummaryRequestDTO.SummarizeDTO request) {
Users user = userRepository.findById(userId).orElse(null);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

userRepository.findById(userId).orElse(null)을 사용하여 사용자를 조회하고 있습니다. 만약 userId에 해당하는 사용자가 존재하지 않을 경우 user 변수는 null이 됩니다. 이 null 값은 이후 diaryRepository.findAllByUserIdAndDate(user, ...) 호출 시 NullPointerException을 발생시킬 수 있습니다.
다른 서비스에서처럼 orElseThrow를 사용하여 사용자를 찾지 못한 경우 예외를 발생시키는 것이 더 안전합니다.

Suggested change
Users user = userRepository.findById(userId).orElse(null);
Users user = userRepository.findById(userId).orElseThrow(() -> new ExceptionHandler(ErrorStatus.USER_NOT_FOUND));

LocalDate day = request.getDate();

LocalDateTime todayStart = day.atStartOfDay();
LocalDateTime todayEnd = day.atTime(LocalTime.MAX);

List<Diaries> diaries = diaryRepository.findAllByUserIdAndDate(user, todayStart, todayEnd);
String prompt = PromptBuilder.buildPrompt(diaries);

ChatGPTRequestDTO gptRequest = new ChatGPTRequestDTO(model, prompt);
ChatGPTResponseDTO responseDTO = restTemplate.postForObject(apiUrl, gptRequest, ChatGPTResponseDTO.class);

String content = responseDTO.getChoices().get(0).getMessage().getContent();

String rawKey = diaries.stream()
.map(d -> d.getId() + ":" + d.getUpdatedAt().toString())
.sorted()
.collect(Collectors.joining(","));

String diaryKeyHash = generateSHA256(rawKey);

SummaryDiary summaryDiary = SummaryDiary.builder()
.date(day)
.content(content)
.users(user)
.diaryKeyHash(diaryKeyHash)
.build();

summaryDiaryRepository.save(summaryDiary);
return summaryDiary;
}
Comment on lines +87 to +119

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

새로 추가된 summarizeByDailySummaryAlarm 메소드는 기존의 summarize 메소드와 거의 동일한 로직을 가지고 있습니다. 코드 중복은 유지보수성을 저하시킬 수 있습니다.
공통 로직을 별도의 private 메소드로 추출하여 중복을 제거하는 리팩토링을 제안합니다. 예를 들어, Users 객체와 LocalDate를 인자로 받아 SummaryDiary를 생성하고 반환하는 private 메소드를 만들 수 있습니다.

@Override
public SummaryDiary summarize(DiarySummaryRequestDTO.SummarizeDTO request) {
    Long userId = SecurityUtil.getCurrentUserId();
    Users user = userRepository.findById(userId)
            .orElseThrow(() -> new ExceptionHandler(ErrorStatus.USER_NOT_FOUND));
    return createSummaryForUser(user, request.getDate());
}

@Override
public SummaryDiary summarizeByDailySummaryAlarm(Long userId, DiarySummaryRequestDTO.SummarizeDTO request) {
    Users user = userRepository.findById(userId)
            .orElseThrow(() -> new ExceptionHandler(ErrorStatus.USER_NOT_FOUND));
    return createSummaryForUser(user, request.getDate());
}

private SummaryDiary createSummaryForUser(Users user, LocalDate day) {
    // ... 공통 요약 생성 로직 ...
}

이렇게 하면 코드의 재사용성이 높아지고 유지보수가 용이해집니다.


@Override
public SummaryDiary reSummarize(DiarySummaryRequestDTO.SummarizeDTO request) {
Long userId = SecurityUtil.getCurrentUserId();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,60 +1,60 @@
package TtattaBackend.ttatta.service.OpenAiService;

import TtattaBackend.ttatta.domain.DailySummaryAlarm;
import TtattaBackend.ttatta.domain.Diaries;
import TtattaBackend.ttatta.repository.DailySummaryAlarmRepository;
import TtattaBackend.ttatta.repository.DiaryRepository;
import TtattaBackend.ttatta.web.dto.DiarySummaryRequestDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;

@Service
@Slf4j
@RequiredArgsConstructor
public class SummaryDiaryBatchService {
private final DailySummaryAlarmRepository dailySummaryAlarmRepository;
private final SummaryCommandService summaryCommandService;
private final DiaryRepository diaryRepository;
@Scheduled(cron = "0 * * * * *")
public void processDailySummaryDiary() {
LocalTime currentTime = LocalTime.now().withSecond(0).withNano(0);

List<DailySummaryAlarm> alarms = dailySummaryAlarmRepository.findByAlarmTime(currentTime);
for (DailySummaryAlarm alarm : alarms) {
try {
LocalDate today = LocalDate.now();
LocalDateTime todayStart = today.atStartOfDay();
LocalDateTime todayEnd = today.plusDays(1).atStartOfDay();
List<Diaries> todayDiaries = diaryRepository.findAllByUserIdAndDate(
alarm.getUsers(), todayStart, todayEnd);
if (todayDiaries.size() < 2) {
log.info("요약 건너뜀 - 사용자 ID: {}, 오늘 일기 수: {}",
alarm.getUsers().getId(), todayDiaries.size());
continue;
}
DiarySummaryRequestDTO.SummarizeDTO request = DiarySummaryRequestDTO.SummarizeDTO.builder()
.date(today)
.build();
summaryCommandService.summarize(request);
log.info("자동 요약 완료 - 사용자 ID: {}, 알람 시간: {}",
alarm.getUsers().getId(), alarm.getAlarmTime());
} catch (Exception e) {
log.error("자동 요약 실패 - 사용자 ID: {}, 에러: {}",
alarm.getUsers().getId(), e.getMessage());
}
}
}
}
//package TtattaBackend.ttatta.service.OpenAiService;
//
//import TtattaBackend.ttatta.domain.DailySummaryAlarm;
//import TtattaBackend.ttatta.domain.Diaries;
//import TtattaBackend.ttatta.repository.DailySummaryAlarmRepository;
//import TtattaBackend.ttatta.repository.DiaryRepository;
//import TtattaBackend.ttatta.web.dto.DiarySummaryRequestDTO;
//import lombok.RequiredArgsConstructor;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.scheduling.annotation.Scheduled;
//import org.springframework.stereotype.Service;
//
//import java.time.LocalDate;
//import java.time.LocalDateTime;
//import java.time.LocalTime;
//import java.util.List;
//
//@Service
//@Slf4j
//@RequiredArgsConstructor
//public class SummaryDiaryBatchService {
// private final DailySummaryAlarmRepository dailySummaryAlarmRepository;
// private final SummaryCommandService summaryCommandService;
// private final DiaryRepository diaryRepository;
//
// @Scheduled(cron = "0 * * * * *")
// public void processDailySummaryDiary() {
// LocalTime currentTime = LocalTime.now().withSecond(0).withNano(0);
//
// List<DailySummaryAlarm> alarms = dailySummaryAlarmRepository.findByAlarmTime(currentTime);
//
// for (DailySummaryAlarm alarm : alarms) {
// try {
// LocalDate today = LocalDate.now();
// LocalDateTime todayStart = today.atStartOfDay();
// LocalDateTime todayEnd = today.plusDays(1).atStartOfDay();
//
// List<Diaries> todayDiaries = diaryRepository.findAllByUserIdAndDate(
// alarm.getUsers(), todayStart, todayEnd);
//
// if (todayDiaries.size() < 2) {
// log.info("요약 건너뜀 - 사용자 ID: {}, 오늘 일기 수: {}",
// alarm.getUsers().getId(), todayDiaries.size());
// continue;
// }
//
// DiarySummaryRequestDTO.SummarizeDTO request = DiarySummaryRequestDTO.SummarizeDTO.builder()
// .date(today)
// .build();
//
// summaryCommandService.summarize(request);
// log.info("자동 요약 완료 - 사용자 ID: {}, 알람 시간: {}",
// alarm.getUsers().getId(), alarm.getAlarmTime());
// } catch (Exception e) {
// log.error("자동 요약 실패 - 사용자 ID: {}, 에러: {}",
// alarm.getUsers().getId(), e.getMessage());
// }
// }
// }
//}