diff --git a/docs/RELEASE-NOTES.md b/docs/RELEASE-NOTES.md index 386935b..535dc8e 100644 --- a/docs/RELEASE-NOTES.md +++ b/docs/RELEASE-NOTES.md @@ -4,6 +4,10 @@ ## [Unreleased] +### 수정 +- cancelQuery idempotent 처리 — 완료된 쿼리 취소 시 에러 대신 정상 응답 +- parseTimestamp 실패 로깅 추가, isNightTimeContact 야간 판정 로직 단순화 + ## [2026-03-02.2] ### 변경 diff --git a/src/main/java/gc/mda/signal_batch/domain/gis/service/AreaSearchService.java b/src/main/java/gc/mda/signal_batch/domain/gis/service/AreaSearchService.java index b434963..02acce9 100644 --- a/src/main/java/gc/mda/signal_batch/domain/gis/service/AreaSearchService.java +++ b/src/main/java/gc/mda/signal_batch/domain/gis/service/AreaSearchService.java @@ -438,6 +438,7 @@ public class AreaSearchService { try { return Long.parseLong(timestamps.get(index)); } catch (NumberFormatException e) { + log.warn("Invalid timestamp at index {}: {}", index, timestamps.get(index)); return 0L; } } diff --git a/src/main/java/gc/mda/signal_batch/domain/gis/service/VesselContactService.java b/src/main/java/gc/mda/signal_batch/domain/gis/service/VesselContactService.java index 047aa6c..8b0f357 100644 --- a/src/main/java/gc/mda/signal_batch/domain/gis/service/VesselContactService.java +++ b/src/main/java/gc/mda/signal_batch/domain/gis/service/VesselContactService.java @@ -360,27 +360,15 @@ public class VesselContactService { * 접촉 구간이 22:00~06:00 KST에 포함되는지 판단. */ private boolean isNightTimeContact(long contactStartSec, long contactEndSec) { - Instant startInstant = Instant.ofEpochSecond(contactStartSec); - Instant endInstant = Instant.ofEpochSecond(contactEndSec); + ZonedDateTime startKst = Instant.ofEpochSecond(contactStartSec).atZone(KST); + ZonedDateTime endKst = Instant.ofEpochSecond(contactEndSec).atZone(KST); - ZonedDateTime startKst = startInstant.atZone(KST); - ZonedDateTime endKst = endInstant.atZone(KST); - - // 접촉 구간 내 모든 날짜에 대해 야간 시간대 겹침 체크 + // 각 날짜의 야간 구간(22:00~익일 06:00)과 접촉 구간 겹침 체크 LocalDate day = startKst.toLocalDate(); - LocalDate lastDay = endKst.toLocalDate().plusDays(1); - - while (!day.isAfter(lastDay)) { - // 해당 날짜의 야간: 전날 22:00 ~ 당일 06:00 - ZonedDateTime nightStart = day.atTime(LocalTime.of(22, 0)).atZone(KST).minusDays(1); - ZonedDateTime nightEnd = day.atTime(LocalTime.of(6, 0)).atZone(KST); - - // 당일 22:00 ~ 다음날 06:00 - ZonedDateTime nightStart2 = day.atTime(LocalTime.of(22, 0)).atZone(KST); - ZonedDateTime nightEnd2 = day.plusDays(1).atTime(LocalTime.of(6, 0)).atZone(KST); - - if (isOverlapping(startKst, endKst, nightStart, nightEnd) - || isOverlapping(startKst, endKst, nightStart2, nightEnd2)) { + while (!day.isAfter(endKst.toLocalDate())) { + ZonedDateTime nightStart = day.atTime(22, 0).atZone(KST); + ZonedDateTime nightEnd = day.plusDays(1).atTime(6, 0).atZone(KST); + if (startKst.isBefore(nightEnd) && endKst.isAfter(nightStart)) { return true; } day = day.plusDays(1); @@ -388,11 +376,6 @@ public class VesselContactService { return false; } - private boolean isOverlapping(ZonedDateTime s1, ZonedDateTime e1, - ZonedDateTime s2, ZonedDateTime e2) { - return s1.isBefore(e2) && s2.isBefore(e1); - } - // ── 추정 속도 계산 ── /** diff --git a/src/main/java/gc/mda/signal_batch/global/websocket/controller/StompTrackController.java b/src/main/java/gc/mda/signal_batch/global/websocket/controller/StompTrackController.java index 05ccc55..1b75ad8 100644 --- a/src/main/java/gc/mda/signal_batch/global/websocket/controller/StompTrackController.java +++ b/src/main/java/gc/mda/signal_batch/global/websocket/controller/StompTrackController.java @@ -113,10 +113,9 @@ public class StompTrackController { trackStreamingService.cancelQuery(queryId); chunkedTrackStreamingService.cancelQuery(queryId); activeSessions.remove(sessionId); - return QueryResponse.cancelled(queryId); } - - return QueryResponse.error(queryId, "Query not found"); + // 세션 없어도 취소 성공 반환 (idempotent — 이미 완료/취소된 쿼리) + return QueryResponse.cancelled(queryId); } /**