Conversation
- ChatService에 남아 있던 direct, SYSTEM_ADMIN, club group, group 메시지 응답 조립을 ChatMessageReadService로 이동 - readAt 갱신과 presence 기록 순서는 기존 서비스 흐름에 남겨 조회 side effect 순서를 유지 - 메시지 조회 단위/통합 테스트를 재실행해 가시 범위와 페이징 응답 동작을 보존
|
Warning Rate limit exceeded
To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthrough채팅 메시지 조회 응답 조립 책임을 별도의 Changes
Sequence Diagram(s)sequenceDiagram
actor Client
participant ChatService
participant ChatMessageReadService
participant Repo as MessageRepository
participant Access as ChatDirectRoomAccessService
Client->>ChatService: getMessages(request)
ChatService->>ChatMessageReadService: request with user, room, page, limit
alt direct room
ChatMessageReadService->>Access: resolve visibleMessageFrom(user, room)
end
ChatMessageReadService->>Repo: query messages (page, limit, visibleMessageFrom?)
ChatMessageReadService->>Repo: query room members / lastRead timestamps
ChatMessageReadService->>ChatMessageReadService: build sorted read baselines, compute unreadCount (binary search)
ChatMessageReadService->>ChatService: return ChatMessagePageResponse
ChatService->>Client: return response
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
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 |
🧪 JaCoCo Coverage Report (Changed Files)Summary
Coverage by File
|
There was a problem hiding this comment.
Pull request overview
ChatService에 남아 있던 “메시지 조회 응답 조립” 로직을 별도 서비스(ChatMessageReadService)로 분리해, 조회 부수효과(readAt 갱신/presence 기록)는 ChatService에 유지하면서 응답 조립 책임을 정리한 PR입니다.
Changes:
- 메시지 조회 응답 조립 로직을
ChatMessageReadService로 이동(direct / SYSTEM_ADMIN 문의방 / club group / group) ChatService.getMessages()에서 신규 read 서비스로 위임하도록 연결ChatServiceTest에서 신규 read 서비스를 실제 객체로 구성하도록 세팅 변경
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/main/java/gg/agit/konect/domain/chat/service/ChatService.java | getMessages에서 응답 조립 로직을 ChatMessageReadService로 위임하도록 변경 |
| src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java | 메시지 페이지 응답 조립 책임을 담당하는 신규 서비스 추가 |
| src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java | ChatService 생성 시 ChatMessageReadService를 실제 객체로 주입하도록 테스트 구성 변경 |
- develop에 병합된 초대/메시지 전송 책임 분리 변경을 메시지 조회 책임 분리 브랜치에 반영 - direct 메시지 조회 중 방 복원이 커밋되도록 getDirectChatRoomMessages를 쓰기 트랜잭션으로 고정 - SYSTEM_ADMIN 마스킹 판단에서 이미 조회한 room members를 재사용해 중복 멤버 조회를 제거
This reverts commit 2a3b87d.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java (1)
153-177:⚠️ Potential issue | 🟠 Major[LEVEL: medium] 새 읽기 서비스로 이동한 핵심 응답 규칙의 회귀 테스트가 빠져 있습니다.
문제:
ChatMessageReadService를 주입만 하고 이번 PR에서 이동한 문의방 sender masking,visibleMessageFrom, unreadCount 집계 규칙을 직접 검증하는 테스트가 없습니다. 영향: 응답 조립이 바뀌어도 현재 테스트는readAt/presence 호출 위주로만 확인해 메시지 노출 정책 회귀를 놓칠 수 있습니다. 제안: 일반 사용자·관리자 각각의 문의방 조회 응답에 대해 masking, 가시 범위, unreadCount를 검증하는 케이스를 이 PR에 추가하세요.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java` around lines 153 - 177, Add unit tests in ChatServiceTest that explicitly verify the migrated read/visibility rules now enforced by ChatMessageReadService: create two test cases (regular member and system admin) that set up a chat room with messages from multiple senders, appropriate readAt/presence states and unread events, then call the same ChatService API used in other tests (the room fetch/response assembler invoked via chatService) and assert three things: (1) sender masking behavior for inquiry-type rooms (masked vs unmasked depending on role), (2) correct visibleMessageFrom window (messages outside the visibility window are absent), and (3) unreadCount aggregation matches expected counts based on readAt/presence; use ChatMessageReadService, ChatService, and existing repositories/mocks to arrange the data and verify results so regressions in masking/visibility/unreadCount are caught.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/main/java/gg/agit/konect/domain/chat/service/ChatService.java`:
- Around line 262-280: The ChatService still contains private message-assembly
methods for direct/SYSTEM_ADMIN/club/group which duplicate logic now in
ChatMessageReadService; remove those private assembly methods from ChatService
and fully delegate message response construction to ChatMessageReadService by
calling its methods (e.g., chatMessageReadService.getDirectChatRoomMessages,
getAdminSystemDirectChatRoomMessages, getClubMessagesByRoom,
getGroupMessagesByRoom) from getMessages(), and move/ensure the single
authoritative implementations of visibleMessageFrom, unreadCount and
SYSTEM_ADMIN handling exist in ChatMessageReadService so all callers use that
central logic; update any test or caller expectations to use the new centralized
behavior.
---
Outside diff comments:
In `@src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java`:
- Around line 153-177: Add unit tests in ChatServiceTest that explicitly verify
the migrated read/visibility rules now enforced by ChatMessageReadService:
create two test cases (regular member and system admin) that set up a chat room
with messages from multiple senders, appropriate readAt/presence states and
unread events, then call the same ChatService API used in other tests (the room
fetch/response assembler invoked via chatService) and assert three things: (1)
sender masking behavior for inquiry-type rooms (masked vs unmasked depending on
role), (2) correct visibleMessageFrom window (messages outside the visibility
window are absent), and (3) unreadCount aggregation matches expected counts
based on readAt/presence; use ChatMessageReadService, ChatService, and existing
repositories/mocks to arrange the data and verify results so regressions in
masking/visibility/unreadCount are caught.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: bd95be75-b1ab-4a40-b56a-6e75e0067555
📒 Files selected for processing (3)
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatService.javasrc/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: coverage
- GitHub Check: Analyze (java-kotlin)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.java
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.java: Java 코드에서 import로 해결할 수 있는 경우 FQCN(Full Qualified Class Name)을 사용하지 않도록 지적한다
JPA/QueryDSL 조회 변경 시 N+1, 잘못된 fetch join, count 쿼리 왜곡, pagination 깨짐, distinct 누락을 확인한다
권한 로직은 관리자 우회, 요청자와 대상자 관계, 클럽/채팅방/공지/일정의 소속 검증이 빠지지 않았는지 확인한다
soft delete, 탈퇴 사용자, 차단/제외 조건, 중복 제거가 필요한 조회에서는 응답에 노출되면 안 되는 데이터가 포함되는지 확인한다
DTO 응답 변경은 기존 클라이언트가 기대하는 필드명, nullability, enum/string 값, 정렬 순서를 깨지 않는지 확인한다
조건이 2개 이상 결합된 비즈니스 규칙, 권한 조건, soft delete 제외, 중복 제거, fallback 우선순위, 대표값 선택, DTO 변환, count 쿼리 분리, fetch join 선택 이유처럼 코드만으로 의도가 숨겨지는 지점에는 주석을 권장한다
단순 생성자 호출, 필드 매핑, 컬렉션 반환, 이름만으로 명확한 분기에는 주석을 요구하지 않는다
Files:
src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatService.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
**/*.{sql,java}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
데이터베이스 변경에서는 마이그레이션 순서, 기존 데이터 호환성, nullable/default 처리, 롤백 난이도, 인덱스 필요성을 확인한다
Files:
src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatService.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
**/*
⚙️ CodeRabbit configuration file
**/*: 공통 리뷰 톤 가이드:
- 모든 코멘트는 첫 줄에
[LEVEL: ...]태그를 포함한다.- 과장된 표현 없이 사실 기반으로 작성한다.
- 한 코멘트에는 하나의 이슈만 다룬다.
- 코드 예시가 필요하면 최소 수정 예시를 제시한다.
- 가독성/단순화/확장성 이슈를 발견하면 우선순위를 높여 코멘트한다.
Files:
src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatService.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
src/main/java/**/*.java
⚙️ CodeRabbit configuration file
src/main/java/**/*.java: 아래 원칙으로 리뷰 코멘트를 작성한다.
- 코멘트는 반드시 한국어로 작성한다.
- 반드시 수정이 필요한 항목만 코멘트로 남기고, 단순 취향 차이는 지적하지 않는다.
- 각 코멘트 첫 줄에 심각도를
[LEVEL: high|medium|low]형식으로 반드시 표기한다.- 심각도 기준: high=운영 장애 가능, medium=품질 저하, low=개선 권고.
- 각 코멘트는 "문제 -> 영향 -> 제안" 순서로 3문장 이내로 간결하게 작성한다.
- 가능하면 재현 조건 및 실패 시나리오도 포함한다.
- 제안은 현재 코드베이스(Spring Boot + JPA + Flyway) 패턴과 일치해야 한다.
- 보안, 트랜잭션 경계, 예외 처리, N+1, 성능 회귀 가능성을 우선 점검한다.
- 가독성: 변수/메서드 이름이 의도를 바로 드러내는지, 중첩과 메서드 길이가 과도하지 않은지 점검한다.
- 단순화: 불필요한 추상화, 중복 로직, 과한 방어 코드가 있으면 더 단순한 대안을 제시한다.
- 확장성: 새 요구사항 추가 시 변경 범위가 최소화되는 구조인지(하드코딩 분기/값 여부 포함) 점검한다.
Files:
src/main/java/gg/agit/konect/domain/chat/service/ChatService.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
🧠 Learnings (31)
📓 Common learnings
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message}/**/*.{ts,tsx} : When modifying message storage logic, verify that last message metadata, direct room restoration conditions, sender's read status updates, list summary sorting, inquiry room special handling, and notification/event side effects remain consistent
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Before modifying chat domain code, answer whether the change breaks direct's leave->restore->reopen policy, misaligns last message with unreadCount, exposes invisible messages, overgeneralizes direct/group policies, breaks SYSTEM_ADMIN reuse, leaks message existence info, or omits list metadata
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member}/**/*.{ts,tsx} : When modifying read status logic, ensure unreadCount calculation, direct room visibility range consistency, list badge and summary values, and inquiry room SYSTEM_ADMIN read status handling remain aligned
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,service}/**/chat.service.{ts,tsx} : Chat service must be the central point where message sending, list summaries, access handling, and membership changes interact, coordinating all state updates
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member,message}/**/{unread,count}*.{ts,tsx} : UnreadCount calculation for direct chat rooms must consider both lastReadAt and actual visible message range (visibleMessageFrom), not just lastReadAt alone
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,service}/**/chat.service.{ts,tsx} : Chat service must be the central point where message sending, list summaries, access handling, and membership changes interact, coordinating all state updates
Applied to files:
src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatService.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-25T06:58:54.393Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/notification/AGENTS.md:0-0
Timestamp: 2026-04-25T06:58:54.393Z
Learning: Applies to src/main/java/gg/agit/konect/domain/notification/**/*IntegrationTest*.java : Add regression tests for: club application event rollback resulting in zero notifications created (AFTER_COMMIT integration test), inbox list/unread count/bulk read excluding chat-related types (repository integration test), Expo push partial ticket failures logged without whole-request exception propagation, group chat token vs target user count mismatch in current policy.
Applied to files:
src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message}/**/*.{ts,tsx} : When modifying message storage logic, verify that last message metadata, direct room restoration conditions, sender's read status updates, list summary sorting, inquiry room special handling, and notification/event side effects remain consistent
Applied to files:
src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatService.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-25T06:58:54.393Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/notification/AGENTS.md:0-0
Timestamp: 2026-04-25T06:58:54.393Z
Learning: Applies to src/main/java/gg/agit/konect/domain/notification/**/*ChatPresenceService*.java : Chat presence service tracks which users are currently viewing specific chat rooms. During chat push notification sending, check presence state to exclude users already present in the target chatroom from receiving push notifications.
Applied to files:
src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatService.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member,service}/**/chat-room-membership*.{ts,tsx} : ChatRoomMembershipService must handle club_group member guarantee, direct/group membership updates, inquiry room read status exceptions, and concurrent creation/duplicate membership absorption
Applied to files:
src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatService.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-25T06:58:54.393Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/notification/AGENTS.md:0-0
Timestamp: 2026-04-25T06:58:54.393Z
Learning: Applies to src/main/java/gg/agit/konect/domain/notification/**/*.java : When modifying chat notification logic, verify: ChatPresenceService presence filtering, NotificationMuteSetting CHAT_ROOM mute filtering, sender exclusion for group chat, Unicode code point basis (not Java string length) for 30-character preview limit, payload path format `chats/{roomId}`, and that exceptions are caught in async boundary.
Applied to files:
src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
📚 Learning: 2026-04-25T06:58:54.393Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/notification/AGENTS.md:0-0
Timestamp: 2026-04-25T06:58:54.393Z
Learning: Applies to src/main/java/gg/agit/konect/domain/notification/**/*.java : When modifying inbox functionality, verify: chat-related type exclusion set (`CHAT_MESSAGE`, `GROUP_CHAT_MESSAGE`, `UNREAD_CHAT_COUNT`), page size default of 20, sort order `createdAt DESC, id DESC`, userId ownership check for single read, and chat-type exclusion in bulk read operations.
Applied to files:
src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatService.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member}/**/*.{ts,tsx} : When modifying read status logic, ensure unreadCount calculation, direct room visibility range consistency, list badge and summary values, and inquiry room SYSTEM_ADMIN read status handling remain aligned
Applied to files:
src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatService.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,repository}/**/*.{ts,tsx} : Repository layer must implement optimized queries for latest message retrieval, unreadCount calculation, list optimization, and distinct handling of direct vs group list logic
Applied to files:
src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,room,list}/**/{list,summary}*.{ts,tsx} : Chat room list summaries must combine last message, last send time, unreadCount, room name, and mute status consistently without treating direct and group room construction separately
Applied to files:
src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatService.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,room,message}/**/{repository,query,list,search}*.{ts,tsx} : When modifying list/search queries, verify custom room name priority, mute status composition, search target room type scope, direct room visible message criteria, messageId page calculation sort consistency, and inquiry room list optimization query conditions remain correct
Applied to files:
src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member,message}/**/*{inquiry,admin,system}*.{ts,tsx} : Inquiry room (SYSTEM_ADMIN type) unreadCount and read status must be aggregated/updated by SYSTEM_ADMIN user record, not by individual admin users
Applied to files:
src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatService.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member}/**/chat-room-member*.{ts,tsx} : ChatRoomMember must maintain direct room visibility state (lastReadAt, visibleMessageFrom, leftAt, custom name, owner flag) with coordinated updates
Applied to files:
src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatService.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,room,list}/**/{query,construct,list}*.{ts,tsx} : Direct and group room types have fundamentally different list construction logic - direct uses chat_room.last_message_* directly while group/club_group combines latest message queries - these must not be unified into identical query paths
Applied to files:
src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,club,member}/**/*.{ts,tsx} : When club membership changes (add/remove), chat room membership must be synchronized to maintain consistent access guarantees for club_group rooms
Applied to files:
src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,room,message,search}/**/{list,summary,search}*.{ts,tsx} : Direct chat rooms must not expose invisible messages (based on visibleMessageFrom) in list summaries or search results
Applied to files:
src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message,inquiry,admin,system}/**/{send,create}*.{ts,tsx} : Inquiry room (SYSTEM_ADMIN) message send by general admin must not add the admin as a room member and must use special handling
Applied to files:
src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatService.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member,message}/**/{unread,count}*.{ts,tsx} : UnreadCount calculation for direct chat rooms must consider both lastReadAt and actual visible message range (visibleMessageFrom), not just lastReadAt alone
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatService.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message,direct}/**/{send,create}*.{ts,tsx} : Sending a message in a direct room must update the sender's lastReadAt to the new message timestamp and may restore the room visibility if the sender was in leftAt state
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatService.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message,group,club}/**/{send,create}*.{ts,tsx} : Sending a message in group or club_group room must update the sender's read status (lastReadAt) immediately upon send
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatService.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,room,list,inquiry,admin}/**/*.{ts,tsx} : Admin inquiry room list must use separate optimized query returning only rooms where the admin has actually sent responses, distinct from regular direct list logic
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatService.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/chat/**/*{inquiry,admin,system}*.{ts,tsx} : SYSTEM_ADMIN inquiry room reuse policy (SYSTEM_ADMIN + regular user pair) must not be broken by adding general admins as room members
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatService.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/chat/**/*direct*member*.{ts,tsx} : When modifying direct membership policy, verify that leftAt, visibleMessageFrom, lastReadAt states, room re-exposure conditions, past message visibility range, search/message jump visibility, and list re-exposure conditions remain consistent
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatService.javasrc/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-13T00:26:23.225Z
Learnt from: dh2906
Repo: BCSDLab/KONECT_BACK_END PR: 533
File: src/main/java/gg/agit/konect/domain/chat/service/ChatService.java:1511-1516
Timestamp: 2026-04-13T00:26:23.225Z
Learning: In ChatService.java (Spring Boot + JPA, MySQL InnoDB), within a `Transactional(readOnly = true)` method, retrying a repository count query (e.g., `countNewerMessagesByChatRoomId`) to handle concurrent inserts is ineffective under REPEATABLE READ isolation: the same DB snapshot is used throughout the transaction, so the retry always returns the same result. A new transaction (`Propagation.REQUIRES_NEW`) would be required for a true retry, but accepting a 1-page offset as a UX tradeoff is preferred for search navigation in this codebase.
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message,direct}/**/{send,receive,create}*.{ts,tsx} : Direct room visibility may be restored when a new message arrives even if the receiving user has leftAt set
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/chat/**/*direct*member*.{ts,tsx} : Direct chat room states (leftAt, visibleMessageFrom, lastReadAt) must not be treated as independent values and must move together according to the leave->restore->reopen policy
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message,direct}/**/*.{ts,tsx} : Direct chat room message visibility must be determined by visibleMessageFrom combined with leftAt status, not by simple member existence
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,room,member}/**/*.{ts,tsx} : The direct chat room leave->restore->reopen policy must not be generalized to group or club_group room types
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-25T07:51:26.474Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/notice/AGENTS.md:0-0
Timestamp: 2026-04-25T07:51:26.474Z
Learning: Applies to src/main/java/gg/agit/konect/domain/notice/**/*NoticeService.java : Notice detail endpoint GET /councils/notices/{id} must use a write transaction (not read-only) to enable read history creation
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message,page,jump}/**/*.{ts,tsx} : MessageId page calculation must validate room access permission and message visibility range before calculating pagination position to prevent information disclosure
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
- members 기반 SYSTEM_ADMIN 포함 여부 판단은 유지하면서 반환 흐름만 한 줄로 정리 - 리뷰 반영 코드의 의도를 바꾸지 않고 중복 분기만 줄임
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java`:
- Around line 199-228: The unread baseline calculation currently uses only
ChatRoomMember::getLastReadAt (in toSortedReadBaselines and
toAdminChatReadBaselines), which causes stale messages to be counted for
direct/SYSTEM_ADMIN rooms; update both methods to compute each member's baseline
as the later of member.getLastReadAt() and member.getVisibleMessageFrom() (i.e.,
max(lastReadAt, visibleMessageFrom)) when forming the per-representative
baselines (keep the admin vs user separation in toAdminChatReadBaselines), then
sort and return those baselines so unreadCount honors actual visibleMessageFrom
ranges for direct chats.
- Around line 62-69: The code currently computes visibleMessageFrom using
resolveAdminSystemRoomVisibleMessageFrom (based on SYSTEM_ADMIN member) which
causes incorrect visibility for a requester who left and rejoined; change logic
in ChatMessageReadService so visibleMessageFrom is derived from the requesting
user's ChatRoomMember (use members.find by user id and consider that member's
visibleMessageFrom and leftAt) and pass that per-requester visibleMessageFrom
into buildDirectChatRoomMessages; retain
resolveAdminSystemRoomVisibleMessageFrom/toAdminChatReadBaselines and
getMaskedAdminId for unread/read aggregation only (i.e., use SYSTEM_ADMIN
baseline solely for aggregate counts, not for determining which messages the
requester may see).
- Around line 168-173: The isMine calculation incorrectly ties to maskedAdminId;
in ChatMessageReadService separate sender masking from ownership check: keep
senderId assignment using maskedAdminId and resolveDirectSenderId(message,
maskedAdminId), but compute isMine first as message.isSentBy(user.getId()), and
only override it with shouldDisplayAsOwnMessage(user, message, true) when this
is an admin-view scenario (i.e. maskedAdminId != null AND the current request is
an admin view — use the existing admin flag on the user/context if available);
update the same pattern where else-applied (the block referenced around 254-263)
so admin-only branching is used for shouldDisplayAsOwnMessage.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 53650a4f-3562-43a7-895e-9f837519a07c
📒 Files selected for processing (1)
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Code Style Check
- GitHub Check: Analyze (java-kotlin)
- GitHub Check: coverage
🧰 Additional context used
📓 Path-based instructions (4)
**/*.java
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.java: Java 코드에서 import로 해결할 수 있는 경우 FQCN(Full Qualified Class Name)을 사용하지 않도록 지적한다
JPA/QueryDSL 조회 변경 시 N+1, 잘못된 fetch join, count 쿼리 왜곡, pagination 깨짐, distinct 누락을 확인한다
권한 로직은 관리자 우회, 요청자와 대상자 관계, 클럽/채팅방/공지/일정의 소속 검증이 빠지지 않았는지 확인한다
soft delete, 탈퇴 사용자, 차단/제외 조건, 중복 제거가 필요한 조회에서는 응답에 노출되면 안 되는 데이터가 포함되는지 확인한다
DTO 응답 변경은 기존 클라이언트가 기대하는 필드명, nullability, enum/string 값, 정렬 순서를 깨지 않는지 확인한다
조건이 2개 이상 결합된 비즈니스 규칙, 권한 조건, soft delete 제외, 중복 제거, fallback 우선순위, 대표값 선택, DTO 변환, count 쿼리 분리, fetch join 선택 이유처럼 코드만으로 의도가 숨겨지는 지점에는 주석을 권장한다
단순 생성자 호출, 필드 매핑, 컬렉션 반환, 이름만으로 명확한 분기에는 주석을 요구하지 않는다
Files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
**/*.{sql,java}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
데이터베이스 변경에서는 마이그레이션 순서, 기존 데이터 호환성, nullable/default 처리, 롤백 난이도, 인덱스 필요성을 확인한다
Files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
src/main/java/**/*.java
⚙️ CodeRabbit configuration file
src/main/java/**/*.java: 아래 원칙으로 리뷰 코멘트를 작성한다.
- 코멘트는 반드시 한국어로 작성한다.
- 반드시 수정이 필요한 항목만 코멘트로 남기고, 단순 취향 차이는 지적하지 않는다.
- 각 코멘트 첫 줄에 심각도를
[LEVEL: high|medium|low]형식으로 반드시 표기한다.- 심각도 기준: high=운영 장애 가능, medium=품질 저하, low=개선 권고.
- 각 코멘트는 "문제 -> 영향 -> 제안" 순서로 3문장 이내로 간결하게 작성한다.
- 가능하면 재현 조건 및 실패 시나리오도 포함한다.
- 제안은 현재 코드베이스(Spring Boot + JPA + Flyway) 패턴과 일치해야 한다.
- 보안, 트랜잭션 경계, 예외 처리, N+1, 성능 회귀 가능성을 우선 점검한다.
- 가독성: 변수/메서드 이름이 의도를 바로 드러내는지, 중첩과 메서드 길이가 과도하지 않은지 점검한다.
- 단순화: 불필요한 추상화, 중복 로직, 과한 방어 코드가 있으면 더 단순한 대안을 제시한다.
- 확장성: 새 요구사항 추가 시 변경 범위가 최소화되는 구조인지(하드코딩 분기/값 여부 포함) 점검한다.
Files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
**/*
⚙️ CodeRabbit configuration file
**/*: 공통 리뷰 톤 가이드:
- 모든 코멘트는 첫 줄에
[LEVEL: ...]태그를 포함한다.- 과장된 표현 없이 사실 기반으로 작성한다.
- 한 코멘트에는 하나의 이슈만 다룬다.
- 코드 예시가 필요하면 최소 수정 예시를 제시한다.
- 가독성/단순화/확장성 이슈를 발견하면 우선순위를 높여 코멘트한다.
Files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
🧠 Learnings (26)
📓 Common learnings
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Before modifying chat domain code, answer whether the change breaks direct's leave->restore->reopen policy, misaligns last message with unreadCount, exposes invisible messages, overgeneralizes direct/group policies, breaks SYSTEM_ADMIN reuse, leaks message existence info, or omits list metadata
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,service}/**/chat.service.{ts,tsx} : Chat service must be the central point where message sending, list summaries, access handling, and membership changes interact, coordinating all state updates
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member,message}/**/*{inquiry,admin,system}*.{ts,tsx} : Inquiry room (SYSTEM_ADMIN type) unreadCount and read status must be aggregated/updated by SYSTEM_ADMIN user record, not by individual admin users
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member}/**/*.{ts,tsx} : When modifying read status logic, ensure unreadCount calculation, direct room visibility range consistency, list badge and summary values, and inquiry room SYSTEM_ADMIN read status handling remain aligned
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member,message}/**/{unread,count}*.{ts,tsx} : UnreadCount calculation for direct chat rooms must consider both lastReadAt and actual visible message range (visibleMessageFrom), not just lastReadAt alone
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message}/**/*.{ts,tsx} : When modifying message storage logic, verify that last message metadata, direct room restoration conditions, sender's read status updates, list summary sorting, inquiry room special handling, and notification/event side effects remain consistent
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message,group,club}/**/{send,create}*.{ts,tsx} : Sending a message in group or club_group room must update the sender's read status (lastReadAt) immediately upon send
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/notification/AGENTS.md:0-0
Timestamp: 2026-04-25T06:58:54.405Z
Learning: Applies to src/main/java/gg/agit/konect/domain/notification/**/*.java : When modifying inbox functionality, verify: chat-related type exclusion set (`CHAT_MESSAGE`, `GROUP_CHAT_MESSAGE`, `UNREAD_CHAT_COUNT`), page size default of 20, sort order `createdAt DESC, id DESC`, userId ownership check for single read, and chat-type exclusion in bulk read operations.
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,repository}/**/*.{ts,tsx} : Repository layer must implement optimized queries for latest message retrieval, unreadCount calculation, list optimization, and distinct handling of direct vs group list logic
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member,service}/**/chat-room-membership*.{ts,tsx} : ChatRoomMembershipService must handle club_group member guarantee, direct/group membership updates, inquiry room read status exceptions, and concurrent creation/duplicate membership absorption
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member,message}/**/{unread,count}*.{ts,tsx} : UnreadCount calculation for direct chat rooms must consider both lastReadAt and actual visible message range (visibleMessageFrom), not just lastReadAt alone
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member}/**/*.{ts,tsx} : When modifying read status logic, ensure unreadCount calculation, direct room visibility range consistency, list badge and summary values, and inquiry room SYSTEM_ADMIN read status handling remain aligned
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message,direct}/**/{send,create}*.{ts,tsx} : Sending a message in a direct room must update the sender's lastReadAt to the new message timestamp and may restore the room visibility if the sender was in leftAt state
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message,group,club}/**/{send,create}*.{ts,tsx} : Sending a message in group or club_group room must update the sender's read status (lastReadAt) immediately upon send
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member,message}/**/*{inquiry,admin,system}*.{ts,tsx} : Inquiry room (SYSTEM_ADMIN type) unreadCount and read status must be aggregated/updated by SYSTEM_ADMIN user record, not by individual admin users
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message}/**/*.{ts,tsx} : When modifying message storage logic, verify that last message metadata, direct room restoration conditions, sender's read status updates, list summary sorting, inquiry room special handling, and notification/event side effects remain consistent
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,service}/**/chat.service.{ts,tsx} : Chat service must be the central point where message sending, list summaries, access handling, and membership changes interact, coordinating all state updates
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,room,list}/**/{list,summary}*.{ts,tsx} : Chat room list summaries must combine last message, last send time, unreadCount, room name, and mute status consistently without treating direct and group room construction separately
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member}/**/chat-room-member*.{ts,tsx} : ChatRoomMember must maintain direct room visibility state (lastReadAt, visibleMessageFrom, leftAt, custom name, owner flag) with coordinated updates
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member,service}/**/chat-room-membership*.{ts,tsx} : ChatRoomMembershipService must handle club_group member guarantee, direct/group membership updates, inquiry room read status exceptions, and concurrent creation/duplicate membership absorption
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-13T00:26:23.225Z
Learnt from: dh2906
Repo: BCSDLab/KONECT_BACK_END PR: 533
File: src/main/java/gg/agit/konect/domain/chat/service/ChatService.java:1511-1516
Timestamp: 2026-04-13T00:26:23.225Z
Learning: In ChatService.java (Spring Boot + JPA, MySQL InnoDB), within a `Transactional(readOnly = true)` method, retrying a repository count query (e.g., `countNewerMessagesByChatRoomId`) to handle concurrent inserts is ineffective under REPEATABLE READ isolation: the same DB snapshot is used throughout the transaction, so the retry always returns the same result. A new transaction (`Propagation.REQUIRES_NEW`) would be required for a true retry, but accepting a 1-page offset as a UX tradeoff is preferred for search navigation in this codebase.
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message,direct}/**/{send,receive,create}*.{ts,tsx} : Direct room visibility may be restored when a new message arrives even if the receiving user has leftAt set
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/chat/**/*direct*member*.{ts,tsx} : When modifying direct membership policy, verify that leftAt, visibleMessageFrom, lastReadAt states, room re-exposure conditions, past message visibility range, search/message jump visibility, and list re-exposure conditions remain consistent
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/chat/**/*direct*member*.{ts,tsx} : Direct chat room states (leftAt, visibleMessageFrom, lastReadAt) must not be treated as independent values and must move together according to the leave->restore->reopen policy
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message,direct}/**/*.{ts,tsx} : Direct chat room message visibility must be determined by visibleMessageFrom combined with leftAt status, not by simple member existence
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,room,member}/**/*.{ts,tsx} : The direct chat room leave->restore->reopen policy must not be generalized to group or club_group room types
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/chat/**/*{inquiry,admin,system}*.{ts,tsx} : SYSTEM_ADMIN inquiry room reuse policy (SYSTEM_ADMIN + regular user pair) must not be broken by adding general admins as room members
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,room,list,inquiry,admin}/**/*.{ts,tsx} : Admin inquiry room list must use separate optimized query returning only rooms where the admin has actually sent responses, distinct from regular direct list logic
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message,inquiry,admin,system}/**/{send,create}*.{ts,tsx} : Inquiry room (SYSTEM_ADMIN) message send by general admin must not add the admin as a room member and must use special handling
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,room,message}/**/{repository,query,list,search}*.{ts,tsx} : When modifying list/search queries, verify custom room name priority, mute status composition, search target room type scope, direct room visible message criteria, messageId page calculation sort consistency, and inquiry room list optimization query conditions remain correct
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-25T07:51:26.486Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/notice/AGENTS.md:0-0
Timestamp: 2026-04-25T07:51:26.486Z
Learning: Applies to src/main/java/gg/agit/konect/domain/notice/**/*NoticeService.java : Notice detail endpoint GET /councils/notices/{id} must use a write transaction (not read-only) to enable read history creation
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-27T00:51:24.941Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/inquiry/AGENTS.md:0-0
Timestamp: 2026-04-27T00:51:24.941Z
Learning: 채팅 도메인의 SYSTEM_ADMIN 문의방 정책, 채팅방 reopen, 마지막 메시지 갱신 정책을 문의 도메인에 섞으면 안 된다
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message,page,jump}/**/*.{ts,tsx} : MessageId page calculation must validate room access permission and message visibility range before calculating pagination position to prevent information disclosure
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,repository}/**/*.{ts,tsx} : Repository layer must implement optimized queries for latest message retrieval, unreadCount calculation, list optimization, and distinct handling of direct vs group list logic
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-25T06:58:54.405Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/notification/AGENTS.md:0-0
Timestamp: 2026-04-25T06:58:54.405Z
Learning: Applies to src/main/java/gg/agit/konect/domain/notification/**/*NotificationInboxService*.java : Inbox list retrieval: default page 1, page size 20, sort by `createdAt DESC, id DESC`. Exclude chat-related types (`CHAT_MESSAGE`, `GROUP_CHAT_MESSAGE`, `UNREAD_CHAT_COUNT`) from list queries, unread count queries, and bulk read operations. Single read operation only allows reading user's own notification; other users' notification ids are treated as not found. Bulk read operation only marks unread notifications of non-chat types as read.
Applied to files:
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
- ChatService에 남아 있던 메시지 응답 조립 메서드를 제거해 ChatMessageReadService가 단일 구현을 갖도록 정리 - 일반 사용자 문의방 조회에서도 관리자 발신자가 SYSTEM_ADMIN으로 보이도록 masking 기준을 read service에서 적용 - 일반 사용자와 관리자 문의방 조회 테스트로 가시 범위, unreadCount, sender 표시 정책 회귀를 막음 - 전체 테스트는 통과했으며 checkstyleTest는 기존 club/notification/chat 테스트 장문 라인 위반이 남아 있어 별도 정리가 필요함
Addressed: |
- direct 계열 메시지의 unread baseline을 lastReadAt 단독 기준에서 visibleMessageFrom을 함께 보는 기준으로 정리 - 나갔다가 복원된 멤버가 볼 수 없는 과거 메시지가 unreadCount에 포함되지 않도록 방지 - 문의방 조회 테스트에 visibleMessageFrom이 lastReadAt보다 늦은 멤버를 포함해 회귀를 검증
🔍 개요
🚀 주요 변경 내용
💬 참고 사항
checkstyleTest는 기존 테스트 파일의 120자 초과 위반 12건으로 실패합니다. 이번 변경 파일에서는 신규 위반이 없습니다.✅ Checklist (완료 조건)