During dailyArchive, reconcileDayVotes may call processGameEndWithGame
per unjudged game, each invalidating every voter's stats cache. Since
dailyArchive already invalidates each archived user once at the end of
its per-user loop, the per-game fan-out is redundant. Add an opt-in
skipInvalidate flag and use it from reconcile. The live onGameCompleted
trigger path keeps invalidating as before. Stale data is impossible:
getStats also self-invalidates on the daily forDate rollover.
- KBO 경기 결과 파싱 시 무승부(`draw`) 상황의 점수도 추출할 수 있도록 정규표현식을 개선하여 경기 상태가 'scheduled'로 오분류되는 문제를 해결했습니다.
- 승리 팀 코드(`winningTeamCode`)가 없는 무승부 경기에서도 결과 처리가 정상적으로 수행되도록 서비스 레이어의 예외 처리를 수정했습니다.
- 무승부 시 어느 팀에 투표했더라도 모두 정답(`result: true`)으로 처리되도록 투표 결과 정산 및 자가 치유(reconcile) 로직을 업데이트했습니다.
- Firestore 트리거(`onGameCompleted`)를 도입하여 경기 종료(`completed`) 및 취소(`cancelled`) 시 투표 결과 판정과 데이터 정리를 자동화했습니다.
- `dailyArchive` 과정에 자가치유(self-healing) 로직인 `reconcileDayVotes`를 추가하여, 트리거 누락이나 지연된 상태 변경 건을 아카이빙 시점에 보정합니다.
- `markGameEnded`가 직접 로직을 수행하는 대신 Firestore 문서만 업데이트하도록 변경하여, 결과 처리 흐름을 트리거로 일원화했습니다.
- 경기 일정 수집부터 통계 산출까지의 전체 투표 파이프라인과 운영 방법을 상세히 기술한 `VOTE_FLOW.md` 문서를 작성했습니다.
- `GameStatus` 타입을 `scheduled`, `live`, `completed`, `cancelled`로 변경하여 상태 관리의 일관성을 높였습니다.
- 사용자 프로필의 `favoriteTeamCode`를 선택 사항으로 변경하고, null 또는 undefined 입력에 대한 처리를 추가했습니다.
- KBO 데이터 병합 과정에 상세 로그를 도입하여 실시간 데이터 매칭 및 외부 API 호출 실패 상황에 대한 가시성을 확보했습니다.
- 상태 값 변경에 따라 영향받는 서비스 로직과 테스트 코드를 일괄 업데이트했습니다.