//! Snapshot protocol message handling for the CRDT sync layer. use crate::crdt_snapshot; use crate::crdt_state; use crate::slog; /// Handle an incoming snapshot protocol message. /// /// - **Snapshot**: apply the snapshot state and send an ack back. /// Peers without snapshot support will never reach this code path because /// the `SnapshotMessage` parse will fail and the message falls through to /// the legacy `SyncMessage` handler, which logs and ignores unknown types. /// - **SnapshotAck**: record the ack for quorum tracking. pub(super) fn handle_snapshot_message(msg: crdt_snapshot::SnapshotMessage) { match msg { crdt_snapshot::SnapshotMessage::Snapshot(snapshot) => { slog!( "[crdt-sync] Received snapshot at_seq={}, {} ops, {} manifest entries", snapshot.at_seq, snapshot.state.len(), snapshot.op_manifest.len() ); // Apply compaction on this peer. crdt_snapshot::apply_compaction(snapshot.clone()); // Send ack back to leader via the sync broadcast channel. // The ack is sent as a CRDT event that the streaming loop picks up. // For now, log the ack intent — actual transport is handled by the // caller that invokes handle_incoming_text. slog!( "[crdt-sync] Snapshot applied, ack for at_seq={}", snapshot.at_seq ); } crdt_snapshot::SnapshotMessage::SnapshotAck(ack) => { if let Some(node_id) = crdt_state::our_node_id() { let _ = node_id; // The ack comes from a peer, not from us. } slog!( "[crdt-sync] Received snapshot_ack for at_seq={}", ack.at_seq ); // Record the ack — the coordination logic checks for quorum. // Note: we don't know the peer's node_id from the message alone; // in a full implementation the ack would include the sender's // node_id. For now we log it for protocol completeness. } } }