diff --git a/src/main/java/com/tryna/domain/external/service/GoogleCalendarClient.java b/src/main/java/com/tryna/domain/external/service/GoogleCalendarClient.java index 0184f68..98530df 100644 --- a/src/main/java/com/tryna/domain/external/service/GoogleCalendarClient.java +++ b/src/main/java/com/tryna/domain/external/service/GoogleCalendarClient.java @@ -39,19 +39,19 @@ public Map fetchEvents(String accessToken, LocalDateTime lastSyn headers.setBearerAuth(accessToken); HttpEntity request = new HttpEntity<>(headers); - String uriTemplate = calendarApiUrl + "?timeMin={timeMin}&timeMax={timeMax}&singleEvents=true&showDeleted=true"; + String uriTemplate = calendarApiUrl + "?singleEvents=true&showDeleted=true"; List uriVariables = new java.util.ArrayList<>(); - uriVariables.add(timeMin.toInstant().toString()); - uriVariables.add(timeMax.toInstant().toString()); if (lastSyncedAt != null) { - // 마지막 동기화 시간 이후에 변경된 데이터만 요청 (updatedMin) + // 증분 동기화 시 timeMin/timeMax 필터를 제외해야 구글이 삭제된(cancelled) 일정을 보내줍니다. String updatedMin = lastSyncedAt.atZone(ZoneId.of("Asia/Seoul")).toInstant().toString(); uriTemplate += "&updatedMin={updatedMin}"; uriVariables.add(updatedMin); } else { - // 최초 동기화 - uriTemplate += "&orderBy=startTime"; + // 최초 Full 동기화 시에는 해당 연도 데이터만 가져오도록 범위 지정 + uriTemplate += "&timeMin={timeMin}&timeMax={timeMax}&orderBy=startTime"; + uriVariables.add(timeMin.toInstant().toString()); + uriVariables.add(timeMax.toInstant().toString()); } // 페이지네이션 토큰이 존재하면 쿼리 파라미터 추가 diff --git a/src/main/resources/db/migration/V20__add_unique_index_for_holiday.sql b/src/main/resources/db/migration/V20__add_unique_index_for_holiday.sql new file mode 100644 index 0000000..976b910 --- /dev/null +++ b/src/main/resources/db/migration/V20__add_unique_index_for_holiday.sql @@ -0,0 +1,9 @@ +-- V20: 공휴일 다중 서버 동시성(Race Condition) 중복 삽입 방어 로직 추가 + +-- 1. 중복된 데이터가 남아있으면 Unique Index 생성이 실패하므로, 기존 공휴일 데이터를 깔끔하게 초기화 +DELETE FROM events WHERE source_type = 'HOLIDAY'; + +-- 2. DB 레벨에서 '동일한 외부 공휴일 ID'가 2번 들어오는 것을 원천 차단하는 방어막 생성 +CREATE UNIQUE INDEX uq_events_holiday_external_id + ON events (external_event_id) + WHERE source_type = 'HOLIDAY'; \ No newline at end of file