Skip to content

Commit

Permalink
[BE-Fix] 겹치는 개인 일정 삭제 시 비트맵 반영하지 않도록 수정 (#255)
Browse files Browse the repository at this point in the history
  • Loading branch information
kwon204 authored Feb 21, 2025
1 parent bd8478c commit 3033c89
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
import endolphin.backend.domain.personal_event.entity.PersonalEvent;
import endolphin.backend.domain.user.entity.User;
import endolphin.backend.global.redis.DiscussionBitmapService;
import endolphin.backend.global.util.TimeUtil;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.Map;
Expand All @@ -27,6 +29,7 @@ public class PersonalEventPreprocessor {

private final DiscussionBitmapService discussionBitmapService;
private final DiscussionParticipantService discussionParticipantService;
private final PersonalEventRepository personalEventRepository;

public void preprocess(List<PersonalEvent> personalEvents, Discussion discussion, User user) {
Long offset = discussionParticipantService.getDiscussionParticipantOffset(
Expand Down Expand Up @@ -72,8 +75,9 @@ && isTimeRangeOverlapping(discussion, personalEvent)) {
private void convert(PersonalEvent personalEvent, Discussion discussion, Long offset,
boolean value) {
long MINUTE_PER_DAY = 1440;

log.info("Convert personal eventId: {} to discussionId: {}", personalEvent.getId(), discussion.getId());
Long discussionId = discussion.getId();
Long userId = personalEvent.getUser().getId();

LocalDate discussionStartDate = discussion.getDateRangeStart();
LocalDate discussionEndDate = discussion.getDateRangeEnd();
Expand All @@ -95,7 +99,9 @@ private void convert(PersonalEvent personalEvent, Discussion discussion, Long of

while (currentDateTime < untilDateTime) {
while (currentDateTime % MINUTE_PER_DAY < maxTime && currentDateTime < untilDateTime) {
discussionBitmapService.setBitValue(discussionId, currentDateTime, offset, value);
if (value || !isDuplicateEvents(currentDateTime, currentDateTime + 30, userId)) {
discussionBitmapService.setBitValue(discussionId, currentDateTime, offset, value);
}
currentDateTime += 30;
}
currentDateTime = ++currentDate * MINUTE_PER_DAY + minTime;
Expand All @@ -109,4 +115,11 @@ private boolean isTimeRangeOverlapping(
return !eventStart.isAfter(discussion.getDateRangeEnd())
&& !eventEnd.isBefore(discussion.getDateRangeStart());
}

private boolean isDuplicateEvents(long start, long end, Long userId) {
return personalEventRepository.countByUserIdAndDateTimeRange(
userId,
TimeUtil.convertToLocalDateTime(start),
TimeUtil.convertToLocalDateTime(end)) > 1;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,14 @@ List<PersonalEvent> findAllByUsersAndDateTimeRange(
@Param("userIds") List<Long> userIds,
@Param("startDateTime") LocalDateTime start,
@Param("endDateTime") LocalDateTime end);

@Query("SELECT COUNT(p) "
+ "FROM PersonalEvent p "
+ "WHERE p.user.id = :userId "
+ "AND p.startTime <= :endDateTime "
+ "AND p.endTime >= :startDateTime")
Long countByUserIdAndDateTimeRange(
@Param("userId") Long userId,
@Param("startDateTime") LocalDateTime start,
@Param("endDateTime") LocalDateTime end);
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import endolphin.backend.global.google.enums.GoogleResourceState;
import endolphin.backend.global.google.event.GoogleEventChanged;
import endolphin.backend.global.util.RetryExecutor;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
Expand Down Expand Up @@ -251,7 +250,6 @@ public void syncWithCalendar(String calendarId, User user) {
throw new CalendarException((HttpStatus) response.getStatusCode(),
response.bodyTo(String.class));
});
log.info("[syncWithCalendar] result: {}", result);
List<GoogleEvent> events = extractEventList(result);
log.info("[syncWithCalendar] before publish event, calId: {}, userId: {}", calendarId, user.getId());
eventPublisher.publishEvent(new GoogleEventChanged(events, user, calendarId));
Expand Down Expand Up @@ -317,13 +315,7 @@ public void subscribeToCalendar(Calendar calendar, User user) {
response.bodyTo(String.class));
});
log.info("[subscribeToCalendar] success: {}", result);
log.info("Subscribed to {}", result.resourceUri());
log.info("Subscribed to {}", result.resourceId());
log.info("Token is {}", result.token());
LocalDateTime expiration = LocalDateTime.ofInstant(
Instant.ofEpochMilli(Long.parseLong(result.expiration())),
ZoneOffset.ofHours(9));
log.info("Expiration time is {}", expiration);

return true;
}, user, calendar.getCalendarId()
);
Expand Down Expand Up @@ -365,11 +357,7 @@ public ResponseEntity<String> processWebhookNotification(
// 성공 응답 (구글의 재시도를 방지하기 위해 204 반환)
return new ResponseEntity<>(HttpStatus.NO_CONTENT);

} catch (CalendarException e) {
log.error("[processWebhookNotification], {}", e.getMessage());
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
catch (Exception e) {
} catch (Exception e) {
// 5xx 에러 응답 시 구글 API가 재시도 (Exponential Backoff)
log.error("[processWebhookNotification], {}", e.getMessage());

Expand Down Expand Up @@ -416,18 +404,6 @@ private List<GoogleEvent> extractEventList(GoogleEventResponse result) {

List<GoogleEvent> events = new ArrayList<>();
for (EventItem item : result.items()) {
log.debug("[extractEventList] {}", item);
if (item != null) {
log.debug("[id]: {}", item.id());
log.debug("[start]: {}", item.start());
log.debug("[end]: {}", item.end());
if (item.start() != null) {
log.debug("[start time]: {}", item.start().dateTime());
}
if (item.end() != null) {
log.debug("[end time]: {}", item.end().dateTime());
}
}

String eventId = item.id();
GoogleEventStatus status = GoogleEventStatus.fromValue(item.status());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ void testPreprocessCallsSetBitValueWithCorrectTimes() {
given(personalEvent.getStartTime()).willReturn(LocalDateTime.of(2024, 3, 15, 13, 0));
given(personalEvent.getEndTime()).willReturn(LocalDateTime.of(2024, 3, 15, 14, 0));
given(personalEvent.getId()).willReturn(1L);
given(personalEvent.getUser()).willReturn(user);

// when
preprocessor.preprocess(List.of(personalEvent), discussion, user);
Expand Down Expand Up @@ -104,6 +105,7 @@ public void test3() {
given(personalEvent.getStartTime()).willReturn(LocalDateTime.of(2024, 3, 8, 8, 0, 0));
given(personalEvent.getEndTime()).willReturn(LocalDateTime.of(2024, 3, 12, 13, 0, 0));
given(personalEvent.getId()).willReturn(3L);
given(personalEvent.getUser()).willReturn(user);

// when
preprocessor.preprocess(List.of(personalEvent), discussion, user);
Expand All @@ -130,6 +132,7 @@ public void test4() {
given(personalEvent.getStartTime()).willReturn(LocalDateTime.of(2024, 3, 8, 20, 0, 0));
given(personalEvent.getEndTime()).willReturn(LocalDateTime.of(2024, 3, 30, 9, 0, 0));
given(personalEvent.getId()).willReturn(4L);
given(personalEvent.getUser()).willReturn(user);

// when
preprocessor.preprocess(List.of(personalEvent), discussion, user);
Expand All @@ -156,6 +159,7 @@ public void test5() {
given(personalEvent.getStartTime()).willReturn(LocalDateTime.of(2024, 3, 12, 13, 50, 0));
given(personalEvent.getEndTime()).willReturn(LocalDateTime.of(2024, 3, 18, 10, 11, 0));
given(personalEvent.getId()).willReturn(5L);
given(personalEvent.getUser()).willReturn(user);

// when
preprocessor.preprocess(List.of(personalEvent), discussion, user);
Expand Down Expand Up @@ -183,6 +187,7 @@ public void test6() {
given(personalEvent.getStartTime()).willReturn(LocalDateTime.of(2024, 3, 15, 23, 0, 0));
given(personalEvent.getEndTime()).willReturn(LocalDateTime.of(2024, 3, 16, 23, 40, 0));
given(personalEvent.getId()).willReturn(5L);
given(personalEvent.getUser()).willReturn(user);

// when
preprocessor.preprocess(List.of(personalEvent), discussion, user);
Expand Down Expand Up @@ -210,6 +215,7 @@ public void test7() {
given(personalEvent.getStartTime()).willReturn(LocalDateTime.of(2024, 3, 15, 20, 0, 0));
given(personalEvent.getEndTime()).willReturn(LocalDateTime.of(2024, 3, 16, 1, 0, 0));
given(personalEvent.getId()).willReturn(5L);
given(personalEvent.getUser()).willReturn(user);

// when
preprocessor.preprocess(List.of(personalEvent), discussion, user);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public void testInitializeAndBitOperations() {
bitmapService.initializeBitmap(discussionId, dateTime);

// 2. 오프셋 5의 비트를 true로 설정
Boolean previousValue = bitmapService.setBitValue(discussionId, dateTime, 5, true);
Boolean previousValue = bitmapService.setBitValue(discussionId, dateTime, 5, true);
// 초기화된 비트맵은 모두 0이므로 이전 값은 false여야 함
assertThat(previousValue).isFalse();

Expand All @@ -57,7 +57,7 @@ public void testDeleteDiscussionBitmapsUsingScan() throws Exception {

// 1. 초기화 및 데이터 삽입
bitmapService.initializeBitmap(discussionId, dateTime);
bitmapService.setBitValue(discussionId, dateTime, 3, true);
bitmapService.setBitValue(discussionId, dateTime, 3, true);

// 2. 데이터 존재 확인
byte[] beforeDelete = bitmapService.getBitmapData(discussionId, dateTime);
Expand Down Expand Up @@ -111,7 +111,7 @@ public void testGetDataOfDiscussionId() {
// 해당 시각에 대해 비트맵 초기화 및 특정 비트 설정
bitmapService.initializeBitmap(discussionId, dateTime);
// 예시로 offset 2의 비트를 true로 설정
bitmapService.setBitValue(discussionId, dateTime, 2, true);
bitmapService.setBitValue(discussionId, dateTime, 2, true);

// 테스트할 시간 범위: minuteKey를 중심으로 ±10분
long startRange = dateTime - 10;
Expand Down

0 comments on commit 3033c89

Please sign in to comment.