Skip to main content

ReplicaEvent

Enum ReplicaEvent 

Source
#[non_exhaustive]
pub enum ReplicaEvent { Frame(DecodedFrame), Ping(FeedPosition), SnapshotBegin, SnapshotChunk(Vec<u8>), SnapshotEnd { ack_offset: u64, }, }
Expand description

Event yielded by 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 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:

use kevy_replicate::replica::{ReplicaClient, ReplicaEvent};
use kevy_replicate::wire;

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");

Variants (Non-exhaustive)§

This enum is marked as non-exhaustive
Non-exhaustive enums could have additional variants added in future. Therefore, when matching against variants of non-exhaustive enums, an extra wildcard arm must be added to account for any future variants.
§

Frame(DecodedFrame)

A live mutation frame.

use kevy_replicate::replica::{DecodedFrame, ReplicaClient, ReplicaEvent};

let mut client = ReplicaClient::connect(addr, "replica-a", 0)?;
let expected = DecodedFrame::new(0, argv(&["SET", "k", "v"]));
assert_eq!(client.next_event().transpose()?, Some(ReplicaEvent::Frame(expected)));
§

Ping(FeedPosition)

In-stream heartbeat: the primary’s tail at send time — its feed generation (the REPL.TOKEN / REPL.WAIT gen truth; 0 = the primary spoke the legacy one-number heartbeat, “unknown”) and its next_offset. Lets the replica compute lag (applied vs primary) and judge link liveness. Occupies no offset space.

use kevy_replicate::feed::FeedPosition;
use kevy_replicate::replica::{ReplicaClient, ReplicaEvent};

let mut client = ReplicaClient::connect(addr, "replica-a", 100)?;
let Some(ReplicaEvent::Ping(tail)) = client.next_event().transpose()? else { panic!() };
assert_eq!(tail.offset - client.expected_offset(), 20); // frames behind the primary
§

SnapshotBegin

Snapshot ship begin marker (+SNAPSHOT\r\n).

use kevy_replicate::replica::{ReplicaClient, ReplicaEvent};

let mut client = ReplicaClient::connect(addr, "replica-a", 0)?;
assert_eq!(client.next_event().transpose()?, Some(ReplicaEvent::SnapshotBegin));
§

SnapshotChunk(Vec<u8>)

One snapshot chunk’s payload bytes (RESP bulk string body).

use kevy_replicate::replica::{ReplicaClient, ReplicaEvent};
use kevy_replicate::wire;

let mut client = ReplicaClient::connect(addr, "replica-a", 0)?;
client.next_event(); // SnapshotBegin
let chunk = ReplicaEvent::SnapshotChunk(b"part-1".to_vec());
assert_eq!(client.next_event().transpose()?, Some(chunk));
§

SnapshotEnd

Snapshot ship end marker carrying the offset the next live frame will have.

use kevy_replicate::replica::{ReplicaClient, ReplicaEvent};
use kevy_replicate::wire;

let mut client = ReplicaClient::connect(addr, "replica-a", 0)?;
client.next_event(); // SnapshotBegin
let end = client.next_event().transpose()?;
assert_eq!(end, Some(ReplicaEvent::SnapshotEnd { ack_offset: 57 }));

Fields

§ack_offset: u64

The offset the primary’s next_offset was at when the snapshot started. After this event, ReplicaClient::expected_offset equals this value.

use kevy_replicate::replica::{ReplicaClient, ReplicaEvent};
use kevy_replicate::wire;

let mut client = ReplicaClient::connect(addr, "replica-a", 0)?;
client.next_event(); // SnapshotBegin
let Some(ReplicaEvent::SnapshotEnd { ack_offset }) = client.next_event().transpose()? else {
    panic!("expected the end marker")
};
assert_eq!(client.expected_offset(), ack_offset); // the next live frame is 57

Trait Implementations§

Source§

impl Clone for ReplicaEvent

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ReplicaEvent

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Eq for ReplicaEvent

Source§

impl Hash for ReplicaEvent

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for ReplicaEvent

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for ReplicaEvent

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.