finance.crowny.org — WAL 컴팩션 (스냅샷+WAL테일 체크포인트)
개요 (개선 #3, 근본·장기)
초대 WAL이 append-only 무한증가 → 부팅 replay O(전체이력)·디스크 무한. 정통 체크포인트 패턴(Redis AOF rewrite / 이벤트소싱 스냅샷)으로 근본 해결. 울트라 워크플로우(설계2→구축→검증2) + 딥리서치 병행.
설계 (정통 스냅샷+WAL테일 체크포인트)
- 스냅샷 = materialized 상태 전체 라인덤프, 파트분할(<14KB, STR_MAX 16KB 안전): C레코드(셀 id 1..초대수 인덱스순회) + K레코드(맵키목록 "_"접두 메타키). manifest=invite-snap.meta.dat=
snap_seq|num_parts.
- 원자 커밋: 파트 .tmp 쓰기 → mv(원자 rename) → manifest를 마지막에 mv = 커밋포인트.
- 불변식 I0: 스냅샷이 완전히 로드가능하다 검증되기 전엔 WAL 절대 삭제 금지.
- 부팅: manifest 유효→스냅샷 로드(사전검증 1패스로 원자적)→WAL은 seq>snap_seq 테일만 멱등 replay. manifest 무/손상→전체 WAL 폴백.
- 트리거: 부팅 시 WAL파트≥8 자동 + 수동 POST /api/invite/compact.
검증에서 발견·수정한 버그 2건
- 비원자 스냅로드(PASS검증이 수정): 파트 점진 적용 중 중간 손상 발견 시 초대DB 오염+폴백→부분상태. → 사전검증 1패스(전 파트 무결 확인 후 적용).
- 0바이트 파트 → 전손실(내가 수정): 쓰기 버그로 0바이트 파트 발생 시 manifest만 확인하면 WAL 삭제 후 부팅 폴백→WAL부재→전손실. → ①writer가 빈 버퍼 파트 미작성, ②
스냅샷검증()(read-only, 전 파트 비어있지않음 확인)을 WAL 은퇴 직전 호출 → verify-before-retire. 검증 실패 시 WAL 보존.
검증 (실측, 내 수정 후)
- compact →
{ok:1, snapSeq:183, parts:12, walRetired:1}, manifest 183|12, WAL 0파트(전이력 스냅샷 흡수).
- 재시작 →
초대WAL 0레코드 replay — 부팅 replay O(테일)=0, 전 history 스냅샷서 복원.
- rewards 영속(momEarned:1), 재유입 join → 무재지급(firstJoin:false, rewarded:[]).
- 크래시안전: manifest 없/부분파트 → 스냅 무시·WAL 폴백 무손실(검증 PASS).
발견한 근본 한계 → 다음 과제
- crownyc 맵 729(3⁶) 캡: 초대DB 단일 맵이 ~729 엔트리서 silent drop(맵키목록 1023상한). finance 초대는 ~300연락처서 도달. 컴팩션 reload가 노출했으나 컴팩션 무관 기존 VM 한계. 규칙승격
feedback_crownyc_map_729_cap.md. 다음 단위: 샤딩 or VM캡 상향(공유 VM 재빌드, 신중).
관련 파일
- src/크라우니파이낸스.한선: 스냅샷쓰기/스냅샷로드/스냅샷검증/컴팩션실행/스냅C적용/스냅K적용, 초대로드 재설계, POST /api/invite/compact, GET /api/invite/stats(walParts/snapSeq).
- data/invite-snap.pN.dat + invite-snap.meta.dat (스냅샷), invite-wal.pN.dat (테일).