/* * backfill 이 이미 있는 사실을 다시 앉히지 않게 하는 부분. * * ── 무엇이 있었나 (2026-09-06 측정) ───────────────────────────────────────── * 중복 판정 기억은 프로세스 안에만 있다. 재기동하면 비워지고, 그 뒤 backfill 을 돌리면 이미 저널에 * 있는 사실도 「처음 본 것」이 된다. * * ``` * mes-line-a 를 재기동 뒤 backfill * 저널 44 → 83건 · 서로 다른 것 39가지 · 중복 44가지 * 같은 프로세스에서 다시 돌리면 applied 0 (기억이 살아 있어서) * ``` * * 저널 조회는 DB 를 물어야 해서 여기서 다루지 않는다. 확인하는 것은 **어느 구간을 읽을지 정하는 * 판정**이다 — 그것이 틀리면 조회가 엉뚱한 곳을 보고 기억이 안 찬다. */ import { test } from 'node:test' import assert from 'node:assert/strict' import { spanOf } from '../server/service/reference/fill-span.js' const at = (s: string) => ({ subjectId: 'L', decision: 'scrap', at: s }) test('★ 레코드가 덮는 구간을 정한다', () => { const span = spanOf([at('2026-09-01T00:00:00.000Z'), at('2026-09-03T12:00:00.000Z'), at('2026-09-02T00:00:00.000Z')]) assert.ok(span) assert.equal(span!.from.toISOString(), '2026-08-31T23:59:59.000Z') assert.equal(span!.to.toISOString(), '2026-09-03T12:00:01.000Z') }) test('★ 양쪽을 1초씩 넓힌다 — 좁게 읽으면 경계의 사실이 다시 앉는다', () => { /* * 저장된 시각은 밀리초까지 있고 경계에서 같은 값이 갈릴 수 있다. 넓게 읽는 것은 기억이 조금 더 * 차는 것뿐이라 손해가 없다. */ const one = '2026-09-01T00:00:00.000Z' const span = spanOf([at(one)])! assert.equal(span.to.getTime() - span.from.getTime(), 2000) }) test('★ 하나도 시각을 안 말하면 구간이 없다 — 저널 전체를 읽지 않는다', () => { /* * 구간을 못 정하면 채우지 않는다. 저널 전체를 읽는 쪽으로 넓히면 2백만 줄을 훑게 되고, 그것이 * 필요한 상황이면 조회가 아니라 정체 색인으로 풀어야 한다. */ assert.equal(spanOf([{ subjectId: 'L', decision: 'scrap' }]), undefined) assert.equal(spanOf([]), undefined) }) test('시각을 말하는 것과 안 말하는 것이 섞이면 말하는 것으로 정한다', () => { const span = spanOf([{ subjectId: 'A' }, at('2026-09-01T00:00:00.000Z'), { subjectId: 'B' }]) assert.ok(span, '한 줄이라도 말하면 구간이 있다') }) test('★ 이 테스트가 실제로 무언가를 잰다 — 견준 것이 0이면 빨강', () => { const narrow = spanOf([at('2026-09-01T00:00:00.000Z')])! const wide = spanOf([at('2026-09-01T00:00:00.000Z'), at('2026-09-10T00:00:00.000Z')])! assert.ok(wide.to.getTime() > narrow.to.getTime(), '구간이 레코드를 안 따라간다') })