/* * 영속 스냅샷이 **사실을 이기지 않는다** — 쓸 수 있는 조건을 못 박는다. * * 멈춘 트윈을 조회할 때마다 저널을 전량 계산하고 있었다(23,731건짜리 트윈에서 4.6초). 스냅샷은 같은 * 폴드의 결과이므로 그 뒤로 아무 일도 없었다면 다시 계산해 봐야 같은 값이다 — 그래서 쓴다. * * 위험은 하나다: **낡은 스냅샷을 "지금" 이라고 내는 것.** 그래서 쓰는 조건을 좁게 잡았고, 그 조건을 * 여기서 고정한다. 엔진 본체는 DB 를 물고 있어 부를 수 없으므로 판정식만 떼어 시험한다 — * 엔진이 쓰는 식과 **같은 식**이어야 의미가 있으므로, 식이 바뀌면 이 시험이 먼저 깨진다. */ import { test } from 'node:test' import assert from 'node:assert/strict' /** 엔진의 조건과 같은 식(twin-engine.recover 의 스냅샷 사용 조건). */ const usable = ( cached: { revision?: number; structureRev?: number | null; state?: any } | null, tip: { revision: number; structureRev: number | null }, asOfNow: boolean ): boolean => !!(asOfNow && cached?.state && (cached.revision ?? 0) === tip.revision && (cached.structureRev ?? null) === tip.structureRev) const TIP = { revision: 23731, structureRev: 2 } const FRESH = { revision: 23731, structureRev: 2, state: { locations: [] } } test('끝에 있고 구조도 같으면 쓴다 — 다시 계산해도 같은 값이다', () => { assert.equal(usable(FRESH, TIP, true), true) }) test('이벤트가 더 있으면 쓰지 않는다 — 그 사이의 사실이 빠진다', () => { assert.equal(usable({ ...FRESH, revision: 23730 }, TIP, true), false) }) test('구조가 바뀌었으면 쓰지 않는다 — 이벤트가 안 늘어도 공장이 달라졌다', () => { /* 재프로비저닝이 정확히 이 모양이다: 부스를 넷 늘렸는데 새 이벤트는 아직 없다. 리비전만 보면 "끝" 이라 새 설비가 없는 옛 상태를 지금으로 내게 된다. */ assert.equal(usable({ ...FRESH, structureRev: 1 }, TIP, true), false) }) test('구조 이력이 없던 시절의 스냅샷은 쓰지 않는다 — 모르는 것을 같다고 하지 않는다', () => { const legacy = { revision: 23731, state: { locations: [] } } // structureRev 없음 assert.equal(usable(legacy, TIP, true), false) }) test('구조가 양쪽 다 없으면 그것은 같은 것이다 — 없는 것끼리는 어긋나지 않는다', () => { assert.equal(usable({ revision: 5, structureRev: null, state: {} }, { revision: 5, structureRev: null }, true), true) assert.equal(usable({ revision: 5, state: {} }, { revision: 5, structureRev: null }, true), true) }) test('시간여행에는 쓰지 않는다 — 그 시점까지 계산해야 한다', () => { assert.equal(usable(FRESH, TIP, false), false) }) test('상태가 비어 있는 스냅샷은 쓰지 않는다 — 빈 공장을 지금으로 내지 않는다', () => { assert.equal(usable({ revision: 23731, structureRev: 2, state: null }, TIP, true), false) assert.equal(usable(null, TIP, true), false) }) test('이벤트가 하나도 없는 트윈도 성립한다 — 0 과 0 은 같다', () => { assert.equal(usable({ revision: 0, structureRev: null, state: { locations: [] } }, { revision: 0, structureRev: null }, true), true) })