Skip to content

HLC 시간 모델

🚧 설계 단계 — 아직 구현 안 됨

이 페이지는 ainote 의 향후 기능을 미리 문서화한 것입니다. 현재 @ainote/mcp v1.1.x 에는 vault / sync 도구가 포함돼 있지 않습니다. 도구 호출 시 Tool not found 에러를 받게 됩니다.

Hybrid Logical Clock — wall clock + counter 조합. 시계가 어긋나도 인과 순서 보장.

왜 wall clock 만은 안 되나

문제 시나리오:

맥미니 시계: 2026-05-07 14:00 (정상)
맥북 시계:    2026-05-08 14:00 (24시간 빠름, NTP 미동기화)

14:00 (맥미니): CLAUDE.md 에 줄 추가 → push
14:01 (맥북, 실제 14:01 이지만 시계는 +1일):
       같은 파일 다른 줄 추가 → push (timestamp = 2026-05-08 14:01)

LWW 적용:
  맥미니 변경 (timestamp 2026-05-07) < 맥북 변경 (timestamp 2026-05-08)
  → 맥북 변경이 이김 → 맥미니의 변경 24시간 후 push 해도 무시됨

HLC 알고리즘

각 spoke 가 (timestamp, counter, device_id) 트리플 유지.

로컬 이벤트 (write)

python
def event_local(now_wall_clock, last_hlc):
    if now_wall_clock > last_hlc.ts:
        return HLC(ts=now_wall_clock, counter=0, device=DEVICE_ID)
    else:
        return HLC(ts=last_hlc.ts, counter=last_hlc.counter+1, device=DEVICE_ID)

원격 이벤트 받음 (pull)

python
def event_received(now_wall_clock, last_hlc, remote_hlc):
    new_ts = max(now_wall_clock, last_hlc.ts, remote_hlc.ts)
    if new_ts == last_hlc.ts == remote_hlc.ts:
        new_counter = max(last_hlc.counter, remote_hlc.counter) + 1
    elif new_ts == last_hlc.ts:
        new_counter = last_hlc.counter + 1
    elif new_ts == remote_hlc.ts:
        new_counter = remote_hlc.counter + 1
    else:
        new_counter = 0
    return HLC(ts=new_ts, counter=new_counter, device=DEVICE_ID)

핵심 속성

  1. Monotonicity: 같은 spoke 의 다음 HLC 는 항상 이전보다 큼
  2. Causality: A 가 B 의 원인이면 HLC(A) < HLC(B)
  3. Bounded drift: 정상 NTP 환경에서 wall clock 과 거의 같음
  4. Tie-breaker: 같은 timestamp 면 counter, 같은 counter 면 device_id

비교 함수

python
def hlc_compare(a, b):
    if a.ts != b.ts: return a.ts - b.ts
    if a.counter != b.counter: return a.counter - b.counter
    return cmp(a.device, b.device)  # 알파벳 순

우리 시나리오 재현

HLC(맥미니, 2026-05-07 14:00, c=0, dev="macmini")  ← 변경
push

HLC(맥북, ?, ?, dev="macbook"):
  - 맥북 시계 2026-05-08 14:01
  - 마지막 본 hub HLC: (맥미니의 hlc above)
  - new_ts = max(맥북 wall, 마지막 본) = 2026-05-08 14:01
  - HLC(2026-05-08 14:01, c=0, dev="macbook")
push

비교:
  맥북 (2026-05-08 14:01) > 맥미니 (2026-05-07 14:00)
  → 맥북 이김 → 같은 결과처럼 보임

문제 같지만 — 이번엔 맥미니가 추가 변경 시:

맥미니 다시 작업:
  - wall = 2026-05-07 14:30
  - 마지막 본 hub HLC (맥북) = 2026-05-08 14:01
  - new_ts = max(14:30, 2026-05-08 14:01) = 2026-05-08 14:01
  - counter += 1
  - HLC(2026-05-08 14:01, c=1, dev="macmini")

맥북 (2026-05-08 14:01, c=0) < 맥미니 (2026-05-08 14:01, c=1)
→ 맥미니 이김 ✅

즉 — 시계 어긋나도 연속 변경의 인과 순서는 보존.

우리 시스템에서의 위치

state.json (각 spoke)
{
  "files": {
    "global/CLAUDE.md": {
      "hlc": "2026-05-08T14:01:00.000Z.1.macmini",
      ...
    }
  }
}

hlc 필드: {ISO timestamp}.{counter}.{device_id}.

hub 도 같은 형식 저장. push 시 비교.

더 읽기

다음

MIT License · ainote.dev