Skip to content

[FIX] 마지막 타임박스 사회자 이탈 시 종료 알림 발송 및 공유 기록 정리 구조 개선 - #279

Merged
coli-geonwoo merged 4 commits into
developfrom
fix/sharing-expired-finish-notification
Oct 8, 2026
Merged

coli-geonwoo merged 4 commits into
developfrom
fix/sharing-expired-finish-notification

Conversation

@coli-geonwoo

@coli-geonwoo coli-geonwoo commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

🚩 연관 이슈

closed #

배경

  • 사회자가 마지막 타임박스에서 연결이 끊긴 뒤 돌아오지 않으면 기록은 FINISHED로 닫히지만, 종료 이벤트를 발행하지 않아 디스코드 알림이 오지 않았다.
  • 1분 주기 정리 작업이 진행 중인 공유가 없어도 매번 DB UPDATE를 실행했다(하루 1440회).
  • SharingLogService가 JPA 엔티티를 직접 다루고, 상태 판단 로직이 서비스 내부 record와 private 메서드에 흩어져 있었다.

작업

1. 유예 만료로 종료할 때도 종료 알림 발송 ([FIX])

  • 마지막 타임박스까지 진행한 공유가 재연결 유예(1분) 만료로 종료될 때도 SharingFinishedEvent를 발행한다.
  • 종료 시각과 공유 시간은 끊긴 시각 기준이다. 중단(ABANDONED)은 지금처럼 알리지 않는다.

2. 정리 작업 주기 분리

  • 1분 주기: 메모리의 진행 중인 공유만 정리한다. 진행 중인 공유가 없으면 바로 끝낸다.
  • 1시간 주기: 서버 재시작 등으로 추적이 끊긴 12시간 넘은 SHARING 기록을 ABANDONED로 정리한다. 기존 cleanupExpiredRooms에 붙였다.
  • 종료 처리와 알림 타이밍(이탈 후 1~2분)은 그대로이고, 줄어드는 건 공유가 없을 때 나가던 DB 쿼리뿐이다.

3. ActiveSharing 도메인 분리

  • 서비스 내부 record를 domain/sharing/ActiveSharing으로 옮긴다. 진행 순서 기록, 연결 끊김·재연결, 만료(isExpired), 완주(isCompleted), 종료 시각(endedAt)을 객체가 직접 판단한다.
  • 이전·다음 이벤트를 이동한 뒤 순서로 바꾸는 규칙은 TimerEventType.toDisplayedSequence로 옮긴다.
  • Instant 대신 LocalDateTime.now(clock)을 써 toLocalDateTime 변환을 없앤다.

4. SharingLogDomainRepository 도입과 단일 UPDATE

  • SharingLog 도메인을 추가하고, 서비스(SharingLogService, SharingStatsService)는 도메인으로만 소통한다. 두 서비스의 @Transactional은 제거하고 트랜잭션 경계는 DomainRepository가 갖는다.
  • 엔티티↔도메인 변환과 없는 기록 조회 시 예외(SHARING_LOG_NOT_FOUND)는 DomainRepository에서 처리한다.
  • 종료·중단은 WHERE id = ? AND status = 'SHARING' 조건의 단일 UPDATE로 처리한다. 한 행 단위라 행 잠금으로 동시 종료가 정리되고, 다른 경로(예: 1시간 주기 정리)에서 먼저 끝난 기록은 덮어쓰지 않으며 알림도 보내지 않는다.
  • 종료 이벤트가 트랜잭션 밖에서 발행되므로 SharingFinishedListener에 fallbackExecution = true를 켰다. 이게 없으면 AFTER_COMMIT 리스너가 이벤트를 받지 않는다.
  • CustomizeTableDomainRepository.getWithMemberById를 추가했다(@EntityGraph(attributePaths = "member")). 기존 getById는 그대로 두고, 트랜잭션 밖에서 회원 정보가 필요한 SharingLogService.start만 새 메서드를 쓴다.

테스트

  • 추가: ActiveSharingTest, SharingLogTest, SharingLogDomainRepositoryTest, TimerEventTypeTest$ToDisplayedSequence, CustomizeTableDomainRepositoryTest$GetWithMemberById
  • SharingLogServiceTest: ApplicationEventPublisher mock으로 유예 만료 종료 시 이벤트 발행/미발행, 이미 정리된 기록이면 미발행, 1시간 주기 정리를 검증
  • SharingLogEntityTest는 SharingLogTest(도메인)로 옮겼다.
  • 전체 ./gradlew test 통과, 커밋마다 관련 테스트 통과 확인

🗣️ 리뷰 요구사항 (선택)

  • 서버 재시작으로 메모리가 날아가면 그때 진행 중이던 공유는 마지막 순서였어도 12~13시간 뒤 ABANDONED로 정리돼 통계에서 빠진다. 이번 변경 전과 같은 동작이다.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • 새 기능
    • 라이브 공유의 연결 상태와 진행 상황을 추적하고, 재연결 유예 시간이 지나거나 공유가 오래 지속되면 상태를 정리합니다.
    • 공유 기록의 시작·종료 시각, 청중 수, 진행 시간과 완료·중단 상태를 관리합니다.
    • 종료된 공유 기록을 기간별로 조회하고 공유 통계에 반영합니다.
  • 개선 사항
    • 마지막 타임박스를 마친 뒤 복귀하지 않은 공유도 완료로 처리하고 종료 알림을 보냅니다.
    • 추적되지 않은 오래된 공유 기록을 별도로 정리합니다.
  • 오류 처리
    • 존재하지 않는 공유 기록 조회 시 찾을 수 없음 오류를 반환합니다.

coli-geonwoo and others added 4 commits October 9, 2026 01:17
사회자가 마지막 타임박스에서 연결이 끊긴 뒤 재연결 유예 시간이 지나면
기록은 FINISHED로 닫히지만 종료 이벤트를 발행하지 않아 디스코드 알림이 누락됐다.
유예 만료로 종료할 때도 명시적 종료와 같은 종료 이벤트를 발행한다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1분 주기 정리 작업이 진행 중인 공유가 없어도 매번 DB UPDATE를 실행했다.
- 1분 주기: 메모리의 진행 중인 공유만 정리하고, 진행 중인 공유가 없으면 바로 끝낸다
- 1시간 주기: 서버 재시작 등으로 추적이 끊긴 12시간 넘은 기록을 중단으로 정리한다

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
서비스 내부 record가 들고 있던 만료·완주 판단을 도메인 객체가 직접 하도록 옮긴다.
- ActiveSharing: 진행 순서 기록, 연결 끊김·재연결, 만료 여부, 완주 여부, 종료 시각 판단
- TimerEventType: 이전·다음 이벤트를 이동한 뒤 순서로 바꾸는 규칙
- Instant 대신 LocalDateTime을 써 시간 변환 로직을 없앤다

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
서비스가 JPA 엔티티 대신 SharingLog 도메인으로만 소통하도록 한다.
- SharingLogDomainRepository: 엔티티↔도메인 변환, 없는 기록 조회 시 예외, 트랜잭션 경계를 담당
- 종료·중단은 진행 중인 행만 바꾸는 단일 UPDATE로 처리해, 다른 경로에서 먼저 끝난 기록을 덮어쓰지 않고 알림도 보내지 않는다
- SharingLogService, SharingStatsService에서 @transactional 제거
- 종료 이벤트가 트랜잭션 밖에서 발행되므로 리스너에 fallbackExecution을 켠다
- 트랜잭션 밖에서 테이블 소유 회원 정보가 필요한 경우를 위해 CustomizeTableDomainRepository.getWithMemberById 추가

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 8, 2026

Copy link
Copy Markdown

Review in Change Stack →

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration
  • Configuration used: Repository: debate-timer/debate-timer-be/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: d8114ee1-ba96-4999-924d-44f9736d7fca
📥 Commits

Reviewing files that changed from the base of the PR and between 0a7e1eb and 46bae21.

📒 Files selected for processing (22)
  • src/main/java/com/debatetimer/domain/sharing/ActiveSharing.java
  • src/main/java/com/debatetimer/domain/sharing/SharingLog.java
  • src/main/java/com/debatetimer/domain/sharing/TimerEventType.java
  • src/main/java/com/debatetimer/domainrepository/customize/CustomizeTableDomainRepository.java
  • src/main/java/com/debatetimer/domainrepository/sharing/SharingLogDomainRepository.java
  • src/main/java/com/debatetimer/entity/sharing/SharingLogEntity.java
  • src/main/java/com/debatetimer/event/sharing/SharingFinishedEvent.java
  • src/main/java/com/debatetimer/event/sharing/SharingFinishedListener.java
  • src/main/java/com/debatetimer/exception/errorcode/ClientErrorCode.java
  • src/main/java/com/debatetimer/repository/customize/CustomizeTableRepository.java
  • src/main/java/com/debatetimer/repository/sharing/SharingLogRepository.java
  • src/main/java/com/debatetimer/scheduler/SharingRoomCleanupScheduler.java
  • src/main/java/com/debatetimer/service/admin/SharingStatsService.java
  • src/main/java/com/debatetimer/service/sharing/SharingLogService.java
  • src/test/java/com/debatetimer/domain/sharing/ActiveSharingTest.java
  • src/test/java/com/debatetimer/domain/sharing/SharingLogTest.java
  • src/test/java/com/debatetimer/domain/sharing/TimerEventTypeTest.java
  • src/test/java/com/debatetimer/domainrepository/customize/CustomizeTableDomainRepositoryTest.java
  • src/test/java/com/debatetimer/domainrepository/sharing/SharingLogDomainRepositoryTest.java
  • src/test/java/com/debatetimer/entity/sharing/SharingLogEntityTest.java
  • src/test/java/com/debatetimer/service/admin/SharingStatsServiceTest.java
  • src/test/java/com/debatetimer/service/sharing/SharingLogServiceTest.java
 ______________________________
< Here's looking at you, code. >
 ------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown

Test Results

199 files  199 suites   47s ⏱️
522 tests 522 ✅ 0 💤 0 ❌
538 runs  538 ✅ 0 💤 0 ❌

Results for commit 46bae21.

@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown

📝 Test Coverage Report

Overall Project 92.8% -0.07% 🍏
Files changed 99.07% 🍏

File Coverage
SharingFinishedListener.java 100% 🍏
SharingFinishedEvent.java 100% 🍏
SharingLogEntity.java 100% 🍏
SharingLogService.java 100% 🍏
SharingLog.java 100% 🍏
ActiveSharing.java 100% 🍏
TimerEventType.java 100% 🍏
SharingStatsService.java 100% 🍏
CustomizeTableDomainRepository.java 100% 🍏
ClientErrorCode.java 100% 🍏
SharingLogDomainRepository.java 100% 🍏
SharingLogRepository.java 100% 🍏
SharingRoomCleanupScheduler.java 100% 🍏
CustomizeTableRepository.java 86.49% -13.51% ❌

@coli-geonwoo
coli-geonwoo merged commit 90a99a1 into develop Oct 8, 2026
3 of 5 checks passed
@coli-geonwoo
coli-geonwoo deleted the fix/sharing-expired-finish-notification branch October 8, 2026 16:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant