Expand description
Replication — synchronous input-stream streaming from primary to replica.
The primary’s JournalStage encodes each InputSlot it just durably
journaled into a wire-ready InputBatch frame in the replication ring
(separately from the journal-codec bytes it writes to disk). The
ReplicationSender thread forwards those frames as-is over TCP/DPDK
— no decode + re-encode on the hot path. The replica decodes the
frames straight back into InputSlots, publishes them to its local
input disruptor with the primary’s pre-assigned sequences and
timestamps, and the replica’s JournalStage re-encodes them through
its own writer for byte-exact-on-replay durability.
§Wire Protocol
Length-prefixed frames, little-endian, over a dedicated TCP connection
(or DPDK pipe). The full InputBatch payload layout lives in
melin_transport_core::replication::protocol /
melin_transport_core::replication_wire.
§Auth (before handshake)
- Challenge (Primary → Replica):
[len:u32][0x03][nonce:[u8;32]] - ChallengeResponse (Replica → Primary):
[len:u32][0x04][signature:[u8;64]][pubkey:[u8;32]] - AuthOk (Primary → Replica):
[len:u32][0x05] - AuthFailed (Primary → Replica):
[len:u32][0x06]
§Replica → Primary
- Handshake:
[len:u32][0x01][last_sequence:u64][chain_hash:[u8;32]] - Ack:
[len:u32][0x02][acked_sequence:u64][in_memory_sequence:u64]
§Primary → Replica
- StreamStart:
[len:u32][0x10][start_sequence:u64][genesis_len:u32][genesis_bytes...] - NeedSnapshot:
[len:u32][0x11] - HashMismatch:
[len:u32][0x12] - SnapshotBegin:
[len:u32][0x13][snapshot_len:u64][snap_sequence:u64][snap_chain_hash:[u8;32]] - SnapshotChunk:
[len:u32][0x14][data...] - SnapshotEnd:
[len:u32][0x15][crc32c:u32] - InputBatch:
[len:u32][0x21][count:u16][slot...]— seetransport-core::replication_wirefor the per-slot layout - Heartbeat:
[len:u32][0x30][sequence:u64]
§v1 Limitations
- No handshake chain hash validation (HashMismatch never sent)
- Dual replication (up to 2 replicas in parallel)
See docs/replication.md for the full design document and limitation details.
Structs§
- Ack
- Ack message sent by the replica.
- Handshake
- Handshake message sent by the replica on connection.
- Pending
Ack - Pending ack waiting for journal durability confirmation.
- Pending
AckQueue - Fixed-capacity circular buffer of pending acks. Decouples TCP receives
from journal fsync by allowing up to
capbatches to be submitted to the journal stage before any ack is sent. Acks are flushed in FIFO order as the journal cursor advances. - Replication
Metrics - Per-slot replication metrics exposed via the health endpoint.
- Sender
- Owned state for the replication sender thread.
Enums§
- Primary
Message - Messages from primary to replica.
- Replica
Message - Messages from replica to primary.
Functions§
- run_
receiver - run_
sender - Run the replication sender. Listens for replica connections, streams journal data batches, processes acks, and updates the replication cursor.
- try_
flush_ dual_ track - Build the next replica → primary
Ackto fire under the dual-track model. ReturnsSome(Ack)when one of the two cursor tracks has advanced beyond the last value sent on the wire. - update_
dual_ replication_ cursor - Update both replication cursors after an ack or disconnect.
- wait_
for_ journal_ cursor - Wait until the journal cursor crosses
target.busy_spin=truekeeps the wait on the CPU (production default — ack RTT is on the primary’s response-gate critical path, where ayield_nowscheduler tick adds ~1ms to client p99).busy_spin=falseyields after a short spin so a stalled cursor doesn’t peg a core under--yield-idle(tests / CI / shared boxes).
Type Aliases§
- Receiver
Result - Outcome of
run_receiver:None= clean shutdown,Some= promotion.