Add getAll+diff to syncGamesForMonth to skip no-op writes

- KBO에서 가져온 경기 일정을 기존 DB 데이터와 비교해 변경된 항목만 Firestore에 저장
- 변경 없는 경기의 반복 write를 제거해 월간 write 비용 대폭 감소
This commit is contained in:
윤정민 2026-05-28 17:19:17 +09:00
parent e76b752a41
commit 12f21803bc

View File

@ -52,26 +52,63 @@ export function toGameDoc(year: number, g: ScheduleGame): Game | null {
return doc;
}
/**
* game doc이 (merge write가 no-op이 ).
*
* `merge: true` doc에 ** ** . doc이
* (: scheduled `winningTeamCode`) merge가 .
* `time` Timestamp이므로 millis로 .
*/
function gameDocUnchanged(existing: Partial<Game>, doc: Game): boolean {
for (const [key, value] of Object.entries(doc) as Array<[keyof Game, unknown]>) {
if (key === "time") {
const a = existing.time?.toMillis();
const b = (value as Timestamp).toMillis();
if (a !== b) return false;
} else if (existing[key] !== value) {
return false;
}
}
return true;
}
/**
* · KBO fetch하여 Firestore `games` upsert한다.
*
* - `merge: true` (: 외부에서 `winningTeamCode`) .
* - gameId가 .
* - `getAll` read로 ** ** write한다
* write를 .
* ( `onGameCompleted` .)
* - gameId가 . gameId가 .
*
* @returns upsert한
* @returns write가
*/
export async function syncGamesForMonth(year: number, month: number): Promise<number> {
const result = await fetchScheduleFromKbo({ year, month });
const batch = firestore.batch();
let count = 0;
// gameId 기준 dedupe (마지막 엔트리 우선) — 순차 set의 "last wins"와 동일.
const byGameId = new Map<string, Game>();
for (const g of result.games) {
const doc = toGameDoc(year, g);
if (!doc) continue;
batch.set(firestore.collection(COLLECTION).doc(g.gameId as string), doc, {
merge: true,
});
count++;
byGameId.set(g.gameId as string, doc);
}
if (byGameId.size === 0) return 0;
const entries = [...byGameId.entries()];
const refs = entries.map(([gameId]) => firestore.collection(COLLECTION).doc(gameId));
const snaps = await firestore.getAll(...refs);
const batch = firestore.batch();
let count = 0;
snaps.forEach((snap, i) => {
const [gameId, doc] = entries[i];
const existing = snap.exists ? (snap.data() as Partial<Game>) : null;
if (existing && gameDocUnchanged(existing, doc)) return;
batch.set(firestore.collection(COLLECTION).doc(gameId), doc, { merge: true });
count++;
});
if (count > 0) await batch.commit();
return count;
}