LabHub
배우기 러닝패스 코스

데이터 파이프라인 · 백필과 이중 계산 · 실습

지난 구간을 다시 돌린다 — 두 배가 되지 않게

LabHub 에서 이어서 보기

목표

구간을 받아 과거를 다시 돌리는 실행기 runner.py 를 만든다. 정기 실행과 같은 코드로 파티션 단위 치환을 하고, 구간 예약으로 정기 실행과의 충돌을 막고, 이미 내보낸 구간은 봉인해 정정으로 남기고, 누적 집계가 백필 때문에 두 배가 되는 것을 직접 재현한 뒤 고친다.

왜 중요한가

백필은 지난 구간을 다시 돌리는 일이지만, 어려운 부분은 계산이 아니라 조율이다. 백필이 도는 동안 정기 실행도 돈다. 둘이 같은 날짜를 동시에 쓰면 어느 쪽이 이겼는지 아무도 모른다.
같은 코스의 멱등 실습은 같은 행을 두 번 넣어도 결과가 같아지게 만드는 일이었다. 여기는 행이 아니라 구간이다. 파티션 표가 멱등해도 누적 표가 멱등하지 않으면 백필 한 번에 숫자가 부풀어 오른다. 더하는 누적은 백필을 만나면 반드시 틀리고, 파생시키는 누적은 몇 번을 돌려도 같은 값을 낸다.
그리고 되돌아가면 안 되는 자리가 있다. 이미 보낸 보고서와 이미 나간 알림은 자료가 아니라 사건이다. 그 구간은 봉인하고, 새 값이 나오면 덮어쓰는 대신 정정으로 따로 기록해야 "그때 우리가 무엇을 보냈는가" 와 "지금 무엇이 맞는가" 를 둘 다 말할 수 있다.
채점기는 여러분의 문구를 믿지 않는다. 임시 디렉터리에 채점기가 만든 파티션을 차려 놓고 환경 변수로 그 저장소를 가리킨 뒤 여러분의 실행기를 실제로 실행하고, sqlite 표를 직접 열어 대조한다. 날짜와 금액은 실행마다 바뀝니다.

단계

1. /root/backfill/gen_events.py 를 만들어 실행해 /root/backfill/events 아래 dt=2026-02-01.jsonl 부터 dt=2026-02-14.jsonl 까지 열나흘치 파티션을 만드세요.
2. /root/backfill/runner.pyinitrun <시작일> <끝일> <주인> 을 만들어 구간의 파티션을 세어 daily 에 넣게 하세요.
3. run 이 파티션을 통째로 치환하게 고치고, 통째로 돌린 답과 하루씩 돌린 답과 재실행 결과를 /root/backfill/split.json 에 적으세요.
4. rollup-add <시작일> <끝일>rollup 을 더하고, 백필 뒤에 두 방식이 얼마나 벌어지는지를 /root/backfill/double.json 에 적으세요.
5. claim <시작일> <끝일> <주인>release <시작일> <끝일> <주인> 을 더해 구간을 예약하게 하세요.
6. run 이 남이 잡고 있는 파티션을 건너뛰고 skipped 로 보고하게 하세요. 건너뛴 것이 있으면 종료 코드는 5 입니다.
7. seal <시작일> <끝일>amend <날짜> <사유> 를 더하세요. 봉인된 파티션은 run 이 건드리지 않고, 늦게 온 전표는 corrections 에 정정으로 남습니다.
8. /root/backfill/backfill_report.json/root/backfill/backfill_report.md 로 한 장을 남기세요.

참고

단계 8개

  1. 열나흘치 파티션 만들기
  2. 구간을 받아 돌리는 실행기 만들기
  3. 파티션 단위로 치환하기
  4. 누적 집계가 두 배가 되는 것 재현하기
  5. 구간을 먼저 예약하기
  6. 남의 구간은 건너뛰고 보고하기
  7. 이미 내보낸 구간은 정정으로 남기기
  8. 재실행 한 판을 한 장으로 보고하기