Merge pull request 'fix: L2 워밍업 범위 확장 — Daily Job 전 기동 시 어제 데이터 포함' (#78) from develop into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 3m8s

This commit is contained in:
htlee 2026-02-21 00:43:44 +09:00
커밋 51780b80bb

파일 보기

@ -68,6 +68,10 @@ public class CacheWarmupService {
LocalDateTime currentHour = now.withMinute(0).withSecond(0).withNano(0); LocalDateTime currentHour = now.withMinute(0).withSecond(0).withNano(0);
LocalDateTime todayStart = now.toLocalDate().atStartOfDay(); LocalDateTime todayStart = now.toLocalDate().atStartOfDay();
// Daily Job(01:00) 이전 기동 어제 데이터도 L2에 필요
boolean beforeDailyJob = now.getHour() < 1;
LocalDateTime l2Start_time = beforeDailyJob ? todayStart.minusDays(1) : todayStart;
// 1. L1 워밍업: 현재 시간대 5min 트랙 (: 12:00~12:50) // 1. L1 워밍업: 현재 시간대 5min 트랙 (: 12:00~12:50)
long l1Start = System.currentTimeMillis(); long l1Start = System.currentTimeMillis();
try { try {
@ -77,10 +81,10 @@ public class CacheWarmupService {
} }
long l1Elapsed = System.currentTimeMillis() - l1Start; long l1Elapsed = System.currentTimeMillis() - l1Start;
// 2. L2 워밍업: 오늘 정각 이전 hourly 트랙 (: 00:00~12:00) // 2. L2 워밍업: 00:00~01:00 기동 어제+오늘, 이후는 오늘만
long l2Start = System.currentTimeMillis(); long l2Start = System.currentTimeMillis();
try { try {
warmUpHourlyCache(todayStart, currentHour); warmUpHourlyCache(l2Start_time, currentHour);
} catch (Exception e) { } catch (Exception e) {
log.error("[CACHE-MONITOR] L2(hourly) 워밍업 실패 — 계속 진행: {}", e.getMessage()); log.error("[CACHE-MONITOR] L2(hourly) 워밍업 실패 — 계속 진행: {}", e.getMessage());
} }
@ -123,12 +127,13 @@ public class CacheWarmupService {
} }
/** /**
* L2 워밍업: t_vessel_tracks_hourly에서 오늘 정각 이전 DB 로드 * L2 워밍업: t_vessel_tracks_hourly에서 DB 로드
* : 12:54 기동 00:00~12:00 (최대 12건/MMSI) 로드 * - 01:00 이후 기동: 오늘 00:00 ~ 현재 정각 (최대 24건/MMSI)
* - 00:00~01:00 기동: 어제 00:00 ~ 현재 정각 (Daily Job용 어제 데이터 포함)
*/ */
private void warmUpHourlyCache(LocalDateTime todayStart, LocalDateTime currentHour) { private void warmUpHourlyCache(LocalDateTime rangeStart, LocalDateTime currentHour) {
if (!currentHour.isAfter(todayStart)) { if (!currentHour.isAfter(rangeStart)) {
log.info("[CACHE-MONITOR] L2 워밍업: 자정 직후 — 건너뜀"); log.info("[CACHE-MONITOR] L2 워밍업: 범위 없음 [{}, {}) — 건너뜀", rangeStart, currentHour);
return; return;
} }
@ -138,15 +143,15 @@ public class CacheWarmupService {
"FROM signal.t_vessel_tracks_hourly " + "FROM signal.t_vessel_tracks_hourly " +
"WHERE time_bucket >= ? AND time_bucket < ?"; "WHERE time_bucket >= ? AND time_bucket < ?";
List<VesselTrack> tracks = loadVesselTracksFromDb(sql, todayStart, currentHour); List<VesselTrack> tracks = loadVesselTracksFromDb(sql, rangeStart, currentHour);
if (!tracks.isEmpty()) { if (!tracks.isEmpty()) {
long distinctMmsi = tracks.stream().map(VesselTrack::getMmsi).distinct().count(); long distinctMmsi = tracks.stream().map(VesselTrack::getMmsi).distinct().count();
hourlyTrackCache.putAll(tracks); hourlyTrackCache.putAll(tracks);
log.info("[CACHE-MONITOR] L2 워밍업 완료: [{}, {}) → {} 건, {} MMSI, cacheSize={}", log.info("[CACHE-MONITOR] L2 워밍업 완료: [{}, {}) → {} 건, {} MMSI, cacheSize={}",
todayStart, currentHour, tracks.size(), distinctMmsi, hourlyTrackCache.size()); rangeStart, currentHour, tracks.size(), distinctMmsi, hourlyTrackCache.size());
} else { } else {
log.info("[CACHE-MONITOR] L2 워밍업: [{}, {}) → 데이터 없음 (정상)", log.info("[CACHE-MONITOR] L2 워밍업: [{}, {}) → 데이터 없음 (정상)",
todayStart, currentHour); rangeStart, currentHour);
} }
} }