본문 바로가기
C.W.K.
Stream
Lesson 02 of 04 · published

purge 하고 replay

~10 min · recovery, purge-and-replay, schema-version, migration

Level 0차가운 쇠
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"mirror 가 틀리면 mirror 를 고치지 않아. 버리고 log 가 다시 그리게 둬."

단 하나의 복구 동작

SQLite 가 derived 니까, 복구는 정확히 한 모양이야. purge and replay. mirror 가 틀리거나 손상되면, Forge 는 영향받은 row 를 drop 하고 JSONL 에서 다시 지어. diff-and-patch 도, incremental reconciliation 로직도 시스템 어디에도 없어. 이건 cwkPippa 가 가장 비싸게 배운 규칙에서 곧장 상속돼. derived state 를 패치하지 마. 패치는 두 store 가 어긋날 수 있는 모든 방법을 열거하는 거야. 넌 항상 하나를 놓치고. 그 놓친 케이스가 mirror 를 전보다 더 조용히 오염시키는 버그가 돼.

스키마 변경도 같은 동작이야

우아한 부분은, 스키마 변경이랑 손상 복구가 같은 연산 이라는 거야. mirror 의 모양이 바뀌어야 하면 Forge 는 db.SCHEMA_VERSION 을 bump 하고, 그 bump 이 migration 이야. mirror 를 drop 하고 log 를 새 모양으로 replay 하는 것. 이걸 이미 이름 없이 두 번 봤어. meal_slot 추가가 SCHEMA_VERSION=3 drop-and-replay 였어. module kind 필드 추가는 SCHEMA_VERSION=4 였고, pre-kind 이벤트는 그냥 workout 으로 replay 됐고. 손으로 쓴 ALTER 도, 미묘하게 틀릴 backfill 스크립트도 없이. log 가 이미 truth 를 쥐고 있으니, 새 mirror 는 그것의 fresh projection 일 뿐이야.

복구는 purge-and-replay 지 절대 patch-and-reconcile 이 아냐. SCHEMA_VERSION bump 이 곧 migration 이야. derived mirror 를 drop 하고 JSONL 을 새 모양으로 replay. incremental 복구 로직은 어디에도 없어, incremental 복구가 바로 미묘하고 조용한 손상이 사는 곳이니까.

왜 구조적으로 안전한가

replay 는 결정론적이고 idempotent 야. 같은 log 를 같은 스키마로 fold 하면 몇 번 돌리든 매번 같은 mirror 를 내. 그게 DB 를 drop 하는 걸 무서운 게 아니라 차분한 연산으로 만들어. 데이터를 지우는 게 아니라 언제나 다시 만들 수 있는 cache 를 버리는 거니까. 원래 말, 날짜, reading 은 append-only log 에 손대지 않은 채 살아. mirror 가 틀려도 되는 건 정확히 그게 네가 지키는 대상이 절대 아니라서야.

Code

purge-and-replay, 그리고 왜 patch-and-reconcile 금지인가·python
# BANNED: diff the two stores and patch the differences
def reconcile(sqlite, jsonl):
    for row in sqlite:
        if diverges(row, jsonl):
            patch(row)          # EVERY divergence case 다뤄야 함
    # 하나 놓치면 -> 시작보다 더 조용한 손상

# THE ONLY MOVE: drop the mirror, replay the log
def rebuild(jsonl, schema_version):
    drop_all_derived_tables()
    create_tables(schema_version)
    for event in read_jsonl(jsonl):    # deterministic, idempotent
        fold(event)                    # same log -> same mirror

# 스키마 변경은 특별하지 않아 - 새 schema_version 의 rebuild().
# SCHEMA_VERSION bump 이 곧 migration.

External links

Exercise

스키마 변경이 mirror 에 새 derived 필드를 더해야 해. Forge 가 어떻게 migrate 하는지 서술하고, 흔한 ALTER TABLE 더하기 backfill 스크립트와 대조해. drop-and-replay 접근이 구조적으로 불가능하게 만드는 버그 한 부류를 대봐.
Hint
Forge 는 SCHEMA_VERSION 을 bump 하고 log 에서 mirror 를 다시 지어. ALTER 도 backfill 도 없이. 없애는 버그는, 새 필드를 살짝 틀리게 계산한 backfill 이 mirror 를 영구히 inconsistent 하게 두고 대조할 깨끗한 source 도 없는 거야.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.