pub enum PrimaryMessage {
StreamStart {
start_sequence: u64,
segment_start_sequence: u64,
anchor_hash: [u8; 32],
genesis_entries: Option<u64>,
epoch: u64,
},
NeedSnapshot,
HashMismatch,
SnapshotBegin {
snapshot_len: u64,
snap_sequence: u64,
snap_chain_hash: [u8; 32],
},
SnapshotChunk(Vec<u8>),
SnapshotEnd {
crc32c: u32,
},
Heartbeat {
sequence: u64,
},
Rotate {
boundary_seq: u64,
tail_hash: [u8; 32],
},
ChainCheck {
sequence: u64,
chain_hash: [u8; 32],
},
SegmentSeedBegin {
seed_len: u64,
},
}Expand description
Messages from primary to replica.
Variants§
StreamStart
Fields
segment_start_sequence: u64Header identity for the journal segment a fresh replica
should create before consuming the stream: the segment’s
starting_sequence and chain anchor_hash. For full
catch-up this is the primary’s oldest segment (lineage
origin); after a snapshot transfer it is snap_sequence + 1
anchored to the snapshot’s chain hash. Replicas with
existing local state ignore it.
genesis_entries: Option<u64>The lineage’s genesis length, from the primary’s journal
header (melin_journal::FileHeaderInfo::genesis_entries;
None: unknown, a lineage begun before the length was
recorded). Unlike the segment identity it concerns every
replica: a fresh one writes it into the journal it creates, so
it survives restarts and is there to check at promotion, and
one with a journal compares it with its own header’s — two
known values that differ are a lineage error.
epoch: u64The primary’s current fencing epoch. A replica that already
observed a higher epoch refuses to follow this (stale) primary;
a replica behind it adopts the epoch as the stream’s EpochBumps
replay. See crate::fence.
No ack policy rides here: the policy is lineage metadata, which
a replica learns from the AckPolicyChange entries it holds, so
it never believes a policy before it holds the entries behind
it.
NeedSnapshot
HashMismatch
SnapshotBegin
Start of a snapshot transfer. Sent after NeedSnapshot.
Fields
SnapshotChunk(Vec<u8>)
A chunk of snapshot data. Sent repeatedly after SnapshotBegin.
SnapshotEnd
End of snapshot transfer. Contains CRC32C of the entire snapshot file.
Heartbeat
Liveness on an idle link: the last sequence sent.
Rotate
Primary-driven segment rotation. Sent in-stream, after the last
entry of the outgoing segment (boundary_seq) and before the
first entry of the new one. The replica rotates its own journal
at exactly this boundary, and tail_hash — the primary’s chain
value at boundary_seq, which is also the new segment’s header
anchor — doubles as a divergence check: a healthy replica’s own
tail equals it. Replicas never rotate on local triggers; shared
boundaries are what make chain values comparable across nodes
(and healthy replica journals bitwise mirrors of the primary’s).
ChainCheck
Live-stream chain validation. chain_hash is the primary’s
chain value at sequence (an fsync-batch boundary); the replica
compares its own value at that sequence and treats a mismatch as
divergence. Extends the handshake-time check to the live stream,
catching corruption that creeps in mid-session.
SegmentSeedBegin
Start of a segment-seed transfer: the raw byte prefix (file
header through the snapshot’s last entry) of the primary segment
containing snap_sequence + 1. Sent between the snapshot
transfer and the post-snapshot StreamStart; the body rides
SnapshotChunk frames and ends with a SnapshotEnd carrying the
seed’s CRC32C. Writing it verbatim as the replica’s live segment
makes the replica’s segmentation a byte-copy of the primary’s
from birth, so chain values are comparable (and Rotate
verification holds) with no alignment grace period.