dreamwell_runtime/authority/protocol.rs
1//! Authority protocol — trait contract for local and remote authority backends.
2//!
3//! Both LocalAuthority and RemoteAuthorityClient implement AuthorityClient.
4//! The runtime holds `Box<dyn AuthorityClient>` and calls it at phase boundaries,
5//! never in hot inner loops.
6
7use dreamwell_fabric::packets::ClientIntent;
8
9/// Connection state for the authority backend.
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum ConnectionState {
12 /// No connection attempt.
13 Disconnected,
14 /// Connection in progress.
15 Connecting,
16 /// Connected and synchronized.
17 Connected,
18 /// Connected but state diverged — needs resync.
19 Desynced,
20}
21
22/// Event received from the authority backend.
23#[derive(Debug, Clone)]
24pub enum AuthorityEvent {
25 /// Acknowledgment of a submitted intent.
26 Ack { seq: u64 },
27 /// Rejection of a submitted intent.
28 Reject { seq: u64, reason: String },
29 /// Canonical event from the authority.
30 CanonEvent {
31 tick: u64,
32 event_type: String,
33 payload: Vec<u8>,
34 },
35 /// Snapshot chunk for initial or re-sync.
36 SnapshotChunk {
37 chunk_id: u32,
38 total_chunks: u32,
39 data: Vec<u8>,
40 },
41}
42
43/// Authority client contract. Implemented by LocalAuthority and RemoteAuthorityClient.
44/// Called at phase boundaries (PollAuthority, StageAuthorityEvents), never in hot loops.
45pub trait AuthorityClient: Send {
46 /// Submit client intents to the authority for processing.
47 fn submit_intents(&mut self, intents: &[ClientIntent]);
48
49 /// Poll for authority events (non-blocking).
50 fn poll_events(&mut self, out: &mut Vec<AuthorityEvent>);
51
52 /// Request a full state snapshot for initial sync or resync.
53 fn request_snapshot(&mut self);
54
55 /// Current connection state.
56 fn connection_state(&self) -> ConnectionState;
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62
63 #[test]
64 fn connection_state_variants() {
65 let states = [
66 ConnectionState::Disconnected,
67 ConnectionState::Connecting,
68 ConnectionState::Connected,
69 ConnectionState::Desynced,
70 ];
71 assert_eq!(states.len(), 4);
72 }
73
74 #[test]
75 fn authority_event_variants() {
76 let _ack = AuthorityEvent::Ack { seq: 1 };
77 let _reject = AuthorityEvent::Reject {
78 seq: 2,
79 reason: "test".into(),
80 };
81 let _canon = AuthorityEvent::CanonEvent {
82 tick: 100,
83 event_type: "move".into(),
84 payload: vec![],
85 };
86 let _snapshot = AuthorityEvent::SnapshotChunk {
87 chunk_id: 0,
88 total_chunks: 1,
89 data: vec![],
90 };
91 }
92}