tele.crowny.org — P2 방로그 복제기 구현 (S2)
개요
크라우니메신저(tele.crowny.org:9619)의 P2P "복제 2/2" 표시를 데모가 아닌 실데이터로
채우기 위한 방로그 델타 복제기. 작업분해-분업계획.md §3 "복제 상태 PSV 계약"에 따라
S1(텔레서버.한선)과 파일 소유권 분리(단독 소유: 복제기.한선), API/데이터 계약만 공유.
무엇을 했는지
/Users/ef/crowny-tele/복제기.한선 신규 작성 (원샷 스크립트, 데몬 아님).
- 설계: Syncthing BEP 델타 복제 원리(p2p-통화-타사사례.md §2-1) 적용 — 방당 단일 writer라
벡터클록 불필요, "원본 줄수"를 그 방의 단조 seq로 취급.
1.
data/방로그_*.psv 각각을
replica/방로그_<방ID>.psv로 델타 복제 — 복제본 줄수를
세고 원본에서 그 이후 줄만 덧쓰기. 원본 줄수 < 복제본 줄수면 로그 회전으로 보고
전체 교체.
2. 복제 성공 판정 = 복제 후 원본·복제본 줄수 일치.
3.
data/복제상태.psv 갱신 —
방ID|복제본수|총목표|마지막성공ts (임시파일 작성 후
체계("mv ...") 원자 교체). 실패한 방은 이전 성공 ts를 이월(carry-forward)해
"마지막 성공 시각"이 실패로 덧씌워지지 않게 함.
4. 헬스비트:
체계()+curl -m 2 로
POST http://127.0.0.1:9619/api/nodes/beat
(S1이 병렬로 만드는 중인 라우트 — 404/실패 무시, 결선되면 자동으로 살아남).
5. 처리 결과 1줄 출력 후 종료. 스케줄링은 오케스트레이터가 LaunchAgent
StartInterval로 담당(본 파일은 상주 루프 없음).
- 파일목록() 내장함수는 불량(디렉토리 엔트리 전부 0) →
체계("ls ... | grep '^방로그_'") +
읽기() 우회로 디렉토리 스캔.
- 함수는 전방참조 위험 회피를 위해 모두 파일 상단에 호출 순서대로 정의 후, 최하단에
top-level 실행 블록 배치(텔레서버.한선과 동일 관례).
검증 (라이브 데이터 대상 실측)
- 컴파일:
CROWNY_STRICT=1 ./hanseonc_high 복제기.한선 > 복제기.toau → EXIT=0, 경고 0.
- 1회차(풀복제): 당시 존재하던 6개 방 전부 원본=복제 줄수 일치,
복제상태.psv 전부
2|2|<ts>.
- 2회차(델타 0): 변경 없는 방은 델타줄=0 확인(로그:
방=6 델타줄=0).
- 신규 방
방로그_s2test.psv(가짜 테스트 파일)로 3회차 풀복제 확인 → replica 2/2 줄
일치.
- 4회차: s2test에 1줄
echo >> 추가 후 실행 → 델타로 1줄만 복제(전체 재복사 아님,
replica/방로그_s2test.psv가 정확히 3줄로 증가) 확인. 테스트 후
data/·
replica/
양쪽에서 s2test 파일과
복제상태.psv의 해당 줄 삭제해 원상복구.
- 라이브 서버(9619) 재기동/수정 없음, 텔레서버.한선·tele-bridge.js 무접촉 확인.
- 테스트 도중 S1이 병렬로 실사용자 대화방(dm_ops, g_)을 계속 생성해 방 수가
6→7→10으로 늘었으나 복제기는 매 실행마다 정상 반영(라이브 동시성 문제 없음 실증).
관련 파일
/Users/ef/crowny-tele/복제기.한선 (신규, S2 단독 소유)
/Users/ef/crowny-tele/복제기.toau (컴파일 산출물)
/Users/ef/crowny-tele/replica/ (신규 디렉토리, 복제본 저장소)
/Users/ef/crowny-tele/data/복제상태.psv (신규, S1이 /api/room/repl에서 읽을 계약
파일)
- 참고:
/Users/ef/crowny-tele/docs/학습/p2p-통화-타사사례.md §2 (Syncthing BEP)
- 참고:
/Users/ef/crowny-tele/docs/작업분해-분업계획.md §3 (API/PSV 계약)
잔여 이슈
POST /api/nodes/beat 라우트는 이 작업 시점에 S1이 아직 구현 중이라 404
(
{"ok":false,"err":"not_found"}) — 결선 후 재검증 불필요(체계+curl 실패 무시
설계라 자동으로 살아남음), 단 결선 완료 여부는 별도 확인 권장.
- 스케줄링(LaunchAgent StartInterval)은 오케스트레이터 담당 — 이 작업 범위 밖.
GET /api/room/repl?room= (P3)이 data/복제상태.psv를 읽어 {copies,total} 응답하는
구현은 S1 담당 — 본 작업은 계약 파일만 정확히 채워 넘김.
- 복제노드는 현재 로컬 replica/ 1곳뿐(마스터=맥서버 자기 자신) — 실제 원격 VPS
read-replica pull은 로드맵(§2 적용포인트 원안)에 남아있음.