#[non_exhaustive]pub enum ReplicaError {
HandshakeRejected,
AckMalformed,
Truncated,
Frame(WireError),
OffsetGap {
expected: u64,
got: u64,
},
UnexpectedInSnapshot,
SnapshotInProgress,
Io(Error),
}Expand description
Errors a replica client can surface to its driver loop.
use kevy_replicate::replica::{ReplicaClient, ReplicaError};
let mut client = ReplicaClient::connect(addr, "replica-a", 0)?;
match client.next_event() {
Some(Err(ReplicaError::OffsetGap { .. })) => { /* resync through a snapshot */ }
Some(Err(e)) => return Err(e.into()), // drop the link and reconnect
other => panic!("unexpected {other:?}"),
}Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
HandshakeRejected
Primary closed the connection or never replied during the
handshake / +ACK exchange.
use kevy_replicate::replica::{ReplicaClient, ReplicaError};
// the primary hangs up without an `+ACK`
let err = ReplicaClient::connect(addr, "replica-a", 0).unwrap_err();
assert!(matches!(err, ReplicaError::HandshakeRejected));AckMalformed
+ACK line was malformed (didn’t start with +ACK , didn’t
parse the offset).
use kevy_replicate::replica::{ReplicaClient, ReplicaError};
let err = ReplicaClient::connect(addr, "replica-a", 0).unwrap_err();
assert!(matches!(err, ReplicaError::AckMalformed));Truncated
Peer closed the connection mid-frame; reconnect to resume.
use kevy_replicate::replica::{ReplicaClient, ReplicaError};
let mut client = ReplicaClient::connect(addr, "replica-a", 0)?;
assert!(matches!(client.next_event(), Some(Err(ReplicaError::Truncated))));Frame(WireError)
Wire-level decode error (envelope shape wrong, payload malformed, etc.).
use kevy_replicate::replica::{ReplicaClient, ReplicaError};
use kevy_replicate::wire::WireError;
let mut client = ReplicaClient::connect(addr, "replica-a", 0)?;
let event = client.next_event();
assert!(matches!(event, Some(Err(ReplicaError::Frame(WireError::BadEnvelope)))));OffsetGap
Frame arrived with an offset other than the expected next. Caller should trigger a full snapshot resync.
use kevy_replicate::replica::{ReplicaClient, ReplicaError};
let mut client = ReplicaClient::connect(addr, "replica-a", 10)?;
let Some(Err(ReplicaError::OffsetGap { expected, got })) = client.next_event() else { panic!() };
assert_eq!((expected, got), (10, 12)); // frames 10 and 11 never arrivedFields
expected: u64The offset the client expected next (= last_seen + 1).
use kevy_replicate::replica::{ReplicaClient, ReplicaError};
let mut client = ReplicaClient::connect(addr, "replica-a", 10)?;
let Some(Err(ReplicaError::OffsetGap { expected, .. })) = client.next_event() else {
panic!("expected a gap")
};
assert_eq!(expected, 10);got: u64The offset the primary actually sent.
use kevy_replicate::replica::{ReplicaClient, ReplicaError};
let mut client = ReplicaClient::connect(addr, "replica-a", 10)?;
let Some(Err(ReplicaError::OffsetGap { got, .. })) = client.next_event() else {
panic!("expected a gap")
};
assert_eq!(got, 12);UnexpectedInSnapshot
While streaming a snapshot, the primary sent bytes that were
neither a snapshot chunk nor +SNAPSHOT_END. Interleaving live
frames inside a snapshot is forbidden (see docs/snapshot.md).
use kevy_replicate::replica::{ReplicaClient, ReplicaError};
use kevy_replicate::wire;
let mut client = ReplicaClient::connect(addr, "replica-a", 0)?;
client.next_event(); // SnapshotBegin
assert!(matches!(client.next_event(), Some(Err(ReplicaError::UnexpectedInSnapshot))));SnapshotInProgress
next_frame was called but the next event is a snapshot
marker / chunk. Callers that want the snapshot-aware surface
must use crate::replica::ReplicaClient::next_event.
use kevy_replicate::replica::{ReplicaClient, ReplicaError};
let mut client = ReplicaClient::connect(addr, "replica-a", 0)?;
assert!(matches!(client.next_frame(), Some(Err(ReplicaError::SnapshotInProgress))));Io(Error)
Underlying socket I/O failure.
use kevy_replicate::replica::{ReplicaClient, ReplicaError};
// nothing listens on a port whose listener was just dropped
let addr = std::net::TcpListener::bind("127.0.0.1:0")?.local_addr()?;
let err = ReplicaClient::connect(addr, "replica-a", 0).unwrap_err();
let ReplicaError::Io(io) = err else { panic!("expected an I/O error, got {err}") };
assert_eq!(io.kind(), std::io::ErrorKind::ConnectionRefused);Trait Implementations§
Source§impl Debug for ReplicaError
impl Debug for ReplicaError
Source§impl Display for ReplicaError
impl Display for ReplicaError
Source§impl Error for ReplicaError
impl Error for ReplicaError
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
use the Display impl or to_string()