HarperFast / HarperFast/harper-pro

Replication applies the origin's log key as the record version for source fills (cross-replica fill-version divergence)

Open
#790 1 comment 0 reactions 1 assignee Claimed by @kriszyp View on GitHub
Dominant language
JavaScript
Stars
3
Forks
0
Avg merge
1d 21h
Merged PRs (30d)
80

Description

## Problem

Since core #2065 separated a source fill's stored record version from its fill transaction's commit timestamp (the transaction-log key), replication has applied the origin's LOG KEY as the record version on peers for every replicated source fill: `replication/replicationConnection.ts` puts `auditRecord.version` (the log key on RocksDB today) on the apply event as `timestamp` (~:5759), core adopts it as the apply transaction's timestamp (`Table.ts` ~1046 → `transaction.ts` ~52), and that timestamp becomes the record version.

Result: the origin stores the fill at its source-derived record version while every peer stores it at the origin's commit key. Cross-replica fill-version divergence, exactly the class of inconsistency #2065 set out to fix. Silent: nothing alarms; it surfaces later as spurious conflict-resolution outcomes.

## Fix direction (stage 0b of [harper#2412](https://github.com/HarperFast/harper/issues/2412), rewritten 2026-09-02)

Under the settled model, the receiver adopts two things from the origin separately:

- **First word / log key**: set the apply transaction's timestamp from `AuditRecord.localTime` (the origin's first word, which is also the origin's log key). This is the one legitimate `setTimestamp` caller besides crash replay. The destination's per-origin log keeps the origin clock, so the "version === audit-log key" resume-cursor invariant (~:4085 in the old numbering) is preserved. Do NOT reuse the applied record version as the destination's per-origin log key: that would fix leaf state while breaking relayed/proxied resume ordering.
- **Record version**: apply `AuditRecord.version` (normalized to the record version in stage 0b; `recordVersion ?? version` until then) per write. In stage 2 this lands in the second word when it differs from the first word; until then it is the record's stored version.

Cursor sites move to `localTime`. Wire format carries both words (it already carries the record version in-band per #2409).

## Scope

Main-line (unreleased) only: #2065 is on core main (v5.3), not on a cut release branch. Needs the two-node replication leg for verification: a fill replicates with its version preserved and its first word equal to the origin's log key; disconnect; resume from the origin cursor; receiver restart.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.