1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//! The events a [`crate::replica::ReplicaClient`] yields — split from
//! `replica.rs` so each file stays under the 500-LOC house rule.
//! Re-exported from [`crate::replica`], so caller paths are unchanged.
use crateFeedPosition;
use crateDecodedFrame;
/// Event yielded by [`ReplicaClient::next_event`](crate::replica::ReplicaClient::next_event). A driver loop
/// pattern-matches and applies each:
/// - [`Self::Frame`] → run through the local dispatcher.
/// - [`Self::SnapshotBegin`] → caller should reset / prepare the
/// local store for a fresh-from-snapshot fill.
/// - [`Self::SnapshotChunk`] → append the bytes to the caller's
/// accumulating snapshot buffer.
/// - [`Self::SnapshotEnd`] → caller hands the accumulated buffer to
/// `kevy_persist::load_snapshot`; [`ReplicaClient`](crate::replica::ReplicaClient) has already
/// advanced `expected_offset` to `ack_offset`, so the next
/// [`Self::Frame`] arrives at `ack_offset` with no gap.
///
/// A replica joining through a snapshot sees the whole sequence:
///
/// ```
/// # mod doc { include!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/support/doc_primary.rs")); } use doc::*;
/// use kevy_replicate::replica::{ReplicaClient, ReplicaEvent};
/// use kevy_replicate::wire;
///
/// # let mut stream = wire::encode_snapshot_begin();
/// # stream.extend(wire::encode_snapshot_chunk(b"dump"));
/// # stream.extend(wire::encode_snapshot_end(9));
/// # stream.extend(wire::encode_frame(9, &argv(&["SET", "k", "v"])));
/// # let (addr, _primary) = fake_primary(b"+ACK 1 0\r\n", stream);
/// let mut client = ReplicaClient::connect(addr, "replica-a", 0)?;
/// let mut snapshot = Vec::new();
/// while let Some(event) = client.next_event() {
/// match event? {
/// ReplicaEvent::SnapshotBegin => snapshot.clear(),
/// ReplicaEvent::SnapshotChunk(bytes) => snapshot.extend(bytes),
/// ReplicaEvent::SnapshotEnd { ack_offset } => assert_eq!(ack_offset, 9),
/// ReplicaEvent::Frame(frame) => assert_eq!(frame.offset, 9),
/// _ => {}
/// }
/// }
/// assert_eq!(snapshot, b"dump");
/// # Ok::<(), Box<dyn std::error::Error>>(())
/// ```