Conversation
🐰 변경사항 분석WalkthroughSpring Scheduling을 활성화하고, 매치룸 상태를 자동으로 업데이트하는 스케줄러를 구현했습니다. 저장소에 두 개의 상태 전환 쿼리를 추가하고, 매분 실행되는 스케줄 컴포넌트를 생성하여 OPEN/FULL → CLOSED와 CLOSED → COMPLETED 전환을 자동화합니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Scheduler as Spring Scheduler
participant Task as MatchStatusScheduler
participant Repo as MatchRoomRepository
participant DB as Database
Scheduler->>Task: updateMatchStatuses() (매분 실행)
Task->>Repo: closeStartedMatches()
Repo->>DB: UPDATE match_rooms SET status=CLOSED<br/>(WHERE status IN (OPEN, FULL)<br/>AND scheduled_at <= NOW())
DB-->>Repo: 업데이트된 행 개수 반환
Repo-->>Task: closedCount 반환
Task->>Repo: completeFinishedMatches()
Repo->>DB: UPDATE match_rooms SET status=COMPLETED<br/>(WHERE status=CLOSED<br/>AND scheduled_at + duration <= NOW())
DB-->>Repo: 업데이트된 행 개수 반환
Repo-->>Task: completedCount 반환
Task->>Task: 변경사항 로깅 (건수 > 0인 경우)
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (4)
src/main/java/com/be/sportizebe/domain/match/repository/MatchRoomRepository.java (2)
50-57: @Modifying에 clearAutomatically 옵션 고려 필요벌크 UPDATE 쿼리 실행 후 영속성 컨텍스트에 이미 로드된
MatchRoom엔티티들은 자동으로 갱신되지 않습니다. 동일 트랜잭션 내에서 변경된 엔티티를 다시 조회할 경우 stale 데이터가 반환될 수 있습니다.현재 스케줄러에서는 별도 조회 로직이 없어 당장 문제는 없지만, 향후 확장성을 위해
clearAutomatically = true옵션 추가를 권장합니다.♻️ 권장 수정안
- `@Modifying` + `@Modifying`(clearAutomatically = true) `@Query`(value = """ UPDATE match_rooms SET status = 'CLOSED' WHERE status IN ('OPEN', 'FULL') AND scheduled_at <= NOW() """, nativeQuery = true) int closeStartedMatches();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/be/sportizebe/domain/match/repository/MatchRoomRepository.java` around lines 50 - 57, The `@Modifying` bulk update in MatchRoomRepository (method closeStartedMatches()) can leave stale entities in the persistence context; update the `@Modifying` annotation to include clearAutomatically = true so the EntityManager clears managed MatchRoom entities after the UPDATE. Locate the `@Modifying` on closeStartedMatches() and add clearAutomatically = true to ensure subsequent reads in the same transaction return fresh data.
60-67: 데이터 증가 시 성능을 위한 인덱스 고려두 쿼리 모두
status와scheduled_at컬럼을 조건으로 사용합니다. 매치 데이터가 증가하면 전체 테이블 스캔으로 인해 성능 저하가 발생할 수 있습니다.복합 인덱스 추가를 권장합니다:
CREATE INDEX idx_match_rooms_status_scheduled_at ON match_rooms(status, scheduled_at);또한 이 메서드에도 동일하게
@Modifying(clearAutomatically = true)적용을 권장합니다.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/be/sportizebe/domain/match/repository/MatchRoomRepository.java` around lines 60 - 67, Add a composite index on (status, scheduled_at) to prevent full table scans as match_rows grow (e.g., CREATE INDEX idx_match_rooms_status_scheduled_at ON match_rooms(status, scheduled_at);) and update the repository method annotation for int completeFinishedMatches() in MatchRoomRepository to use `@Modifying`(clearAutomatically = true) so the persistence context is cleared after the bulk update.src/main/java/com/be/sportizebe/domain/match/scheduler/MatchStatusScheduler.java (2)
22-31: 예외 처리 추가 권장스케줄러에서 예외 발생 시 해당 실행은 실패하지만 다음 주기에는 다시 실행됩니다. 그러나 디버깅과 모니터링을 위해 예외 로깅을 추가하는 것이 좋습니다.
♻️ 예외 처리 추가 제안
`@Scheduled`(fixedRate = 60_000) `@Transactional` public void updateMatchStatuses() { + try { int closed = matchRoomRepository.closeStartedMatches(); int completed = matchRoomRepository.completeFinishedMatches(); if (closed > 0 || completed > 0) { log.info("[MatchScheduler] CLOSED: {}건, COMPLETED: {}건", closed, completed); } + } catch (Exception e) { + log.error("[MatchScheduler] 상태 업데이트 중 오류 발생", e); + } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/be/sportizebe/domain/match/scheduler/MatchStatusScheduler.java` around lines 22 - 31, The updateMatchStatuses method in MatchStatusScheduler should catch and log any unexpected exceptions from matchRoomRepository.closeStartedMatches() and matchRoomRepository.completeFinishedMatches() to aid debugging and monitoring; wrap the body of updateMatchStatuses in a try-catch, keep the `@Transactional` behavior, and on exception call log.error with a clear message (e.g., "[MatchScheduler] failed to update match statuses") plus the exception/stacktrace and any contextual info (closed/completed when available) so failures are recorded without preventing future scheduled runs.
24-26: 서비스 레이어와의 동시성 고려스케줄러의 벌크 UPDATE가 서비스 레이어(
MatchServiceImpl의 join, leave, cancel 등)와 동시에 실행될 경우, 사용자 액션으로 인한 상태 변경과 충돌할 수 있습니다.현재 쿼리는
status컬럼을 WHERE 조건으로 사용하므로 대부분의 경우 안전하지만, 엣지 케이스에서 예상치 못한 동작이 발생할 수 있습니다. 향후 문제 발생 시 낙관적 락(@Version) 또는 쿼리에updated_at조건 추가를 고려해 주세요.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/be/sportizebe/domain/match/scheduler/MatchStatusScheduler.java` around lines 24 - 26, The bulk updater updateMatchStatuses calls matchRoomRepository.closeStartedMatches() and completeFinishedMatches() which can race with service-layer methods (MatchServiceImpl.join/leave/cancel); to fix, add concurrency protection either by enabling optimistic locking on the MatchRoom entity (add a `@Version` field and ensure repository update queries respect version) or modify the repository update SQL to include an updated_at (or last_modified) condition so you only update rows that haven't changed since a read—pick one approach and implement it for both closeStartedMatches and completeFinishedMatches so scheduler updates won't overwrite concurrent user actions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In
`@src/main/java/com/be/sportizebe/domain/match/repository/MatchRoomRepository.java`:
- Around line 50-57: The `@Modifying` bulk update in MatchRoomRepository (method
closeStartedMatches()) can leave stale entities in the persistence context;
update the `@Modifying` annotation to include clearAutomatically = true so the
EntityManager clears managed MatchRoom entities after the UPDATE. Locate the
`@Modifying` on closeStartedMatches() and add clearAutomatically = true to ensure
subsequent reads in the same transaction return fresh data.
- Around line 60-67: Add a composite index on (status, scheduled_at) to prevent
full table scans as match_rows grow (e.g., CREATE INDEX
idx_match_rooms_status_scheduled_at ON match_rooms(status, scheduled_at);) and
update the repository method annotation for int completeFinishedMatches() in
MatchRoomRepository to use `@Modifying`(clearAutomatically = true) so the
persistence context is cleared after the bulk update.
In
`@src/main/java/com/be/sportizebe/domain/match/scheduler/MatchStatusScheduler.java`:
- Around line 22-31: The updateMatchStatuses method in MatchStatusScheduler
should catch and log any unexpected exceptions from
matchRoomRepository.closeStartedMatches() and
matchRoomRepository.completeFinishedMatches() to aid debugging and monitoring;
wrap the body of updateMatchStatuses in a try-catch, keep the `@Transactional`
behavior, and on exception call log.error with a clear message (e.g.,
"[MatchScheduler] failed to update match statuses") plus the
exception/stacktrace and any contextual info (closed/completed when available)
so failures are recorded without preventing future scheduled runs.
- Around line 24-26: The bulk updater updateMatchStatuses calls
matchRoomRepository.closeStartedMatches() and completeFinishedMatches() which
can race with service-layer methods (MatchServiceImpl.join/leave/cancel); to
fix, add concurrency protection either by enabling optimistic locking on the
MatchRoom entity (add a `@Version` field and ensure repository update queries
respect version) or modify the repository update SQL to include an updated_at
(or last_modified) condition so you only update rows that haven't changed since
a read—pick one approach and implement it for both closeStartedMatches and
completeFinishedMatches so scheduler updates won't overwrite concurrent user
actions.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 8fce4c7a-aec5-4921-950f-d16bede337c7
📒 Files selected for processing (3)
src/main/java/com/be/sportizebe/SportizeBeApplication.javasrc/main/java/com/be/sportizebe/domain/match/repository/MatchRoomRepository.javasrc/main/java/com/be/sportizebe/domain/match/scheduler/MatchStatusScheduler.java
#️⃣ Issue Number
📝 요약(Summary)
🛠️ PR 유형
어떤 변경 사항이 있나요?
📸스크린샷 (선택)
💬 공유사항 to 리뷰어
✅ PR Checklist
PR이 다음 요구 사항을 충족하는지 확인하세요.
Summary by CodeRabbit
릴리즈 노트