docs(dm): MESSAGE race 검증을 기록한다

This commit is contained in:
2026-06-18 22:57:48 +09:00
parent 482d517145
commit a6485292e4

View File

@@ -650,7 +650,7 @@
- 2026-06-18: `DmChatRoomViewModelTest`에 requestId 기반 독립 pending, `SEND_ACK` requestId 매칭, `ERROR` 실패, timeout 실패, retry 새 requestId, 중복 ACK 무시 테스트를 먼저 추가했다. 수정 전 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatRoomViewModelTest" --max-workers=1` 실행 시 `DmChatMessageUiItem.requestId` 미정의 컴파일 오류로 RED를 확인했고, timeout 테스트는 구현 전 `DmChatRoomViewModelTest.kt:270` assertion failure로 RED를 확인했다.
- 2026-06-18: `DmChatMessageUiItem``requestId`를 추가하고, `DmChatRoomViewModel`의 단일 `isSending` 제한을 제거해 각 텍스트 전송이 새 `requestId`와 pending map으로 관리되도록 변경했다. `SEND_TEXT`는 WebSocket으로 전송하고, `SEND_ACK`/`ERROR`/send false/10초 timeout은 해당 requestId의 local item만 확정 또는 실패 처리한다. retry는 기존 `localId` item을 유지하면서 새 `requestId`를 발급하도록 변경했다. 이후 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatRoomViewModelTest" --max-workers=1` PASS를 확인했다.
- [ ] **Task 10.4: SEND_ACK보다 MESSAGE가 먼저 도착하는 race 처리**
- [x] **Task 10.4: SEND_ACK보다 MESSAGE가 먼저 도착하는 race 처리**
- Files:
- Modify: `app/src/main/java/kr/co/vividnext/sodalive/v2/main/chat/dm/DmChatRoomViewModel.kt`
- Modify: `app/src/test/java/kr/co/vividnext/sodalive/v2/main/chat/dm/DmChatRoomViewModelTest.kt`
@@ -662,8 +662,11 @@
- 검증:
- Run: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatRoomViewModelTest" --max-workers=1`
- Expected: MESSAGE 선도착, ACK 후도착, timeout 후 ACK 복구, 중복 `messageId` 방지 테스트가 PASS.
- 검증 기록:
- 2026-06-18: `DmChatSocketParserTest``MESSAGE` payload의 nullable `requestId` 보존 테스트를 추가하고, `DmChatRoomViewModelTest``MESSAGE(requestId)` 선도착 시 pending local item 확정, `MESSAGE``requestId`가 없는 경우 후도착 `SEND_ACK``messageId` 중복 방지, timeout 실패 후 늦은 `SEND_ACK`의 같은 local item 복구 테스트를 추가했다. 수정 전 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatSocketParserTest" --max-workers=1` 및 ViewModel 대상 테스트 실행에서 `DmChatSocketParserTest.kt:61``DmChatSocketEvent.Message.requestId` 미정의 컴파일 오류로 RED를 확인했다. 이후 `DmChatSocketEvent.Message`와 parser가 nullable `requestId`를 보존하도록 변경하고, ViewModel이 `MESSAGE(requestId)``SEND_ACK`와 동일한 pending 확정 경로로 처리하며 timeout 후 실패 requestId도 늦은 ACK로 복구할 수 있도록 변경했다. 재실행 결과 `DmChatSocketParserTest``DmChatRoomViewModelTest`가 PASS했다. 병렬 Gradle 실행 중 1회 `kspDebugUnitTestKotlin``StreamCorruptedException`이 발생했으나, 같은 ViewModel 테스트 단독 재실행에서 PASS를 확인했다.
- 2026-06-18: 리뷰에서 timeout된 `request-1`이 실패 기록에 남은 상태로 같은 local item을 `request-2`로 retry하고 `request-2` ACK 성공 후 늦은 `request-1` ACK가 도착하면 최신 성공 메시지를 오래된 ACK로 덮을 수 있다는 blocker를 확인했다. `DmChatRoomViewModelTest``retry 성공 후 이전 timeout request ACK는 같은 local item을 덮어쓰지 않는다` 테스트를 추가했고, 수정 전 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatRoomViewModelTest" --max-workers=1` 실행 결과 `DmChatRoomViewModelTest.kt:466` assertion failure로 RED를 확인했다. 이후 retry 시작 및 ACK 성공 확정 시 같은 `localId`에 묶인 stale failed request 기록을 제거하도록 변경했고, 같은 ViewModel 테스트 재실행 결과 PASS를 확인했다.
- [ ] **Task 10.5: Phase 9 코드 리뷰 결과 회귀 테스트 반영**
- [x] **Task 10.5: Phase 9 코드 리뷰 결과 회귀 테스트 반영**
- Files:
- Modify: `app/src/test/java/kr/co/vividnext/sodalive/v2/main/chat/dm/DmChatRoomViewModelTest.kt`
- Modify: `docs/20260610_DM_채팅화면/plan-task.md`
@@ -675,6 +678,9 @@
- 검증:
- Run: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatRoomViewModelTest" --max-workers=1`
- Expected: Phase 9 리뷰 3개 항목 중 ViewModel 세션/전송 항목은 Phase 10 테스트로 고정되고, leave/close 항목은 부정확한 테스트 제거 또는 Task 11.1 이관 기록으로 남는다.
- 검증 기록:
- 2026-06-18: Phase 9 리뷰 항목 중 `JOINED` 전 connected 미확정은 Task 10.1의 `roomId가 있으면 realtime 연결 후 connected callback에서 최신 메시지를 동기화한다` 테스트에서 `JOINED``isRealtimeConnected=false`, `JOINED``true`로 고정되어 있음을 확인했다. requestId 단위 독립 pending은 Task 10.3의 `서로 다른 텍스트는 각각 requestId로 독립 pending 전송한다` 테스트로 고정되어 있음을 확인했다. `LEAVE_ROOM + close` lifecycle 상세 검증은 Task 11.1 범위로 남기고, 실제 연결 없이 `closeCount == 0`만 확인하던 `realtime leave 중 중복 요청은 close를 반복할 수 있다` 테스트는 부정확한 회귀 테스트로 제거했다. Task 10.4까지 포함한 `DmChatRoomViewModelTest`는 이후 재실행해 PASS를 확인한다.
- 2026-06-18: Phase 10 전체 단위 코드 리뷰로 `DmChatRoomViewModel`, `DmChatSocketModels`, `DmChatRoomViewModelTest`, `DmChatSocketParserTest`의 diff를 재검토했다. `MESSAGE(requestId)` 선도착 시 pending local item 확정, requestId 없는 `MESSAGE`와 후도착 `SEND_ACK``messageId` 중복 제거, timeout 후 늦은 `SEND_ACK` 복구, retry 성공 후 이전 timeout request ACK 무시, Phase 9 리뷰 회귀 테스트 반영 상태를 확인했고 blocking issue는 발견하지 못했다. fresh 검증으로 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatRoomViewModelTest" --max-workers=1`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatSocketParserTest" --max-workers=1`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.chat.dm.*" --max-workers=1`, `./gradlew :app:compileDebugKotlin --max-workers=1`, `./gradlew :app:ktlintCheck --max-workers=1`, `git diff --check` PASS를 확인했다. 최초 샌드박스 Gradle 실행은 `~/.gradle` wrapper lock 파일 접근 제한으로 실패해 승인된 Gradle 실행으로 재검증했다. Gradle deprecation warning은 출력됐지만 실패는 없었다.
### Phase 11: Lifecycle, reconnect, heartbeat, token 갱신 처리