Document season settlement write patterns
- 백엔드 쓰기 패턴 문서에 시즌 정산(seasonHistory) 섹션 추가 - tierPoints 초기화·rankSnapshot 삭제·아카이브가 동일 배치로 묶이는 규칙과 멱등 재실행 동작 명시
This commit is contained in:
parent
477fcabc78
commit
ad38a47a64
@ -18,8 +18,8 @@
|
||||
| 항목 | 내용 |
|
||||
|---|---|
|
||||
| 주요 필드 | `displayName, email, provider, knowledgeLevel, photoUrl, favoriteTeamCode, createdAt` (생성), `currentStreak, highestStreak, tierPoints, lastJudgedDate, rankSnapshot, notifications` (운영 중 갱신) |
|
||||
| Writer / 위치 | `createUser` `userRepository.ts:128-139` · `updateUser` `:145-150` · `applyDailyJudgmentTx` `:182-254` · `deleteUser` `:155-157` · `snapshotRankForUser` `rankSnapshotService.ts:26-54` |
|
||||
| Trigger | 생성=POST `/user`(`createMe`, userService.ts:120) · 갱신=PATCH `/user`(`updateMe`), PATCH `/user/notifications`, **GET `/user`(`getMe`) 의 photoUrl 자동 동기화**(userService.ts:101-105) · 판정=`dailyArchive` cron→`judgeDay`→`applyDailyJudgmentTx` · rankSnapshot=`dailyArchive` cron(judge **이전**) · 삭제=DELETE `/user` |
|
||||
| Writer / 위치 | `createUser` `userRepository.ts:128-139` · `updateUser` `:145-150` · `applyDailyJudgmentTx` `:182-254` · `deleteUser` `:155-157` · `snapshotRankForUser` `rankSnapshotService.ts:26-54` · `settleUsers` `seasonRepository.ts`(tierPoints=0 리셋 + rankSnapshot 삭제) |
|
||||
| Trigger | 생성=POST `/user`(`createMe`, userService.ts:120) · 갱신=PATCH `/user`(`updateMe`), PATCH `/user/notifications`, **GET `/user`(`getMe`) 의 photoUrl 자동 동기화**(userService.ts:101-105) · 판정=`dailyArchive` cron→`judgeDay`→`applyDailyJudgmentTx` · rankSnapshot=`dailyArchive` cron(judge **이전**) · 시즌 리셋=`dailyArchive` cron→`maybeSettleSeason`(시즌 endDate 다음 날 1회, §1.8) · 삭제=DELETE `/user` |
|
||||
| Mechanism | 생성 `set({merge:false})`; 일반 갱신 `set({merge:true})`; 판정 `runTransaction`+`set(merge:true)`+`FieldValue.serverTimestamp()`(createdAt); 삭제 `recursiveDelete`(서브컬렉션 voteHistory/attendance/pointLedger 포함) |
|
||||
| 빈도/볼륨 | 가입 1회/유저 · 프로필 수정 드묾 · **rankSnapshot + 판정 = 유저당 매일 2회 write** (전체 활성 유저 N명 × 매일) |
|
||||
| 비용 관찰 | ⚠️ **`getMe`(읽기 경로)에서 토큰 사진이 다르면 매 요청 write 발생** — 사진 변경이 잦은 토큰이면 read마다 hot write. ⚠️ `rankSnapshot` write(archive 중)와 `applyDailyJudgmentTx` write가 **같은 doc을 같은 cron run에서 2번** 건드림 → 1 write로 합칠 여지. |
|
||||
@ -89,6 +89,17 @@
|
||||
|
||||
---
|
||||
|
||||
### 1.8 `users/{uid}/seasonHistory/{seasonId}` (시즌 최종 성적 아카이브)
|
||||
|
||||
| 항목 | 내용 |
|
||||
|---|---|
|
||||
| 데이터 | `{ seasonId, tierPoints, tier, rank, totalRanked, settledAt }` (문서 ID = seasonId) |
|
||||
| Writer | `settleUsers` `seasonRepository.ts` — 유저별 아카이브 `set` + 루트 doc `tierPoints=0`/`rankSnapshot` 삭제를 **같은 배치**로 커밋(200유저/배치) |
|
||||
| Trigger | `dailyArchive` cron → `maybeSettleSeason` (seasonService.ts) — `config/season.endDate` 다음 날, `settledAt` 마커가 없을 때 1회 |
|
||||
| Mechanism | 부분 실패 재실행 시 collectionGroup(`seasonId ==`) 조회로 기정산 유저 점수를 순위 산정에 합류시켜 rank 보존(멱등). `settledAt` 마커는 전원 완료 후 `config/season`에 기록 |
|
||||
| 빈도/볼륨 | **시즌당 1회** × 랭킹 대상 유저 수(유저당 2 write). append-only, 시즌 수만큼만 증가 |
|
||||
| 읽기 | GET `/stats/seasons` (`listUserSeasonHistory`, seasonId desc) — 클라이언트 마이페이지 "지난 시즌 기록" |
|
||||
|
||||
## 2. Realtime Database 쓰기 대상
|
||||
|
||||
### 2.1 `/votes/{gameId}/counts/{homeCount|awayCount}` — 🔴 핫 카운터
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user