aranya_runtime/sync/
mod.rs

1//! Interface for syncing state between clients.
2
3use buggy::Bug;
4use postcard::Error as PostcardError;
5use serde::{Deserialize, Serialize};
6
7use crate::{
8    Address, Prior,
9    command::{CmdId, Command, Priority},
10    storage::{MAX_COMMAND_LENGTH, StorageError},
11};
12
13mod dispatcher;
14mod requester;
15mod responder;
16
17pub use dispatcher::{SubscribeResult, SyncHelloType, SyncType};
18pub use requester::{SyncRequestMessage, SyncRequester};
19pub use responder::{PeerCache, SyncResponder, SyncResponseMessage};
20
21// TODO: These should all be compile time parameters
22
23/// The maximum number of heads that will be stored for a peer.
24pub const PEER_HEAD_MAX: usize = 10;
25
26/// The maximum number of samples in a request
27const COMMAND_SAMPLE_MAX: usize = 100;
28
29/// The maximum number of missing segments that can be requested
30/// in a single message
31const REQUEST_MISSING_MAX: usize = 100;
32
33/// The maximum number of commands in a response
34pub const COMMAND_RESPONSE_MAX: usize = 100;
35
36/// The maximum number of segments which can be stored to send
37const SEGMENT_BUFFER_MAX: usize = 100;
38
39/// The maximum size of a sync message
40// TODO: Use postcard to calculate max size (which accounts for overhead)
41// https://docs.rs/postcard/latest/postcard/experimental/max_size/index.html
42pub const MAX_SYNC_MESSAGE_SIZE: usize = 1024 + MAX_COMMAND_LENGTH * COMMAND_RESPONSE_MAX;
43
44/// Represents high-level data of a command.
45#[derive(Serialize, Deserialize, Debug)]
46pub struct CommandMeta {
47    id: CmdId,
48    priority: Priority,
49    parent: Prior<Address>,
50    policy_length: u32,
51    length: u32,
52    max_cut: usize,
53}
54
55impl CommandMeta {
56    pub fn address(&self) -> Address {
57        Address {
58            id: self.id,
59            max_cut: self.max_cut,
60        }
61    }
62}
63
64/// An error returned by the syncer.
65#[derive(Debug, thiserror::Error)]
66pub enum SyncError {
67    #[error("sync session ID does not match")]
68    SessionMismatch,
69    #[error("missing sync response")]
70    MissingSyncResponse,
71    #[error("syncer state not valid for this message")]
72    SessionState,
73    #[error("syncer not ready for operation")]
74    NotReady,
75    #[error("too many commands sent")]
76    CommandOverflow,
77    #[error("storage error: {0}")]
78    Storage(#[from] StorageError),
79    #[error("serialize error: {0}")]
80    Serialize(#[from] PostcardError),
81    #[error(transparent)]
82    Bug(#[from] Bug),
83}
84
85/// Sync command to be committed to graph.
86#[derive(Serialize, Deserialize, Debug)]
87pub struct SyncCommand<'a> {
88    priority: Priority,
89    id: CmdId,
90    parent: Prior<Address>,
91    policy: Option<&'a [u8]>,
92    data: &'a [u8],
93    max_cut: usize,
94}
95
96impl<'a> Command for SyncCommand<'a> {
97    fn priority(&self) -> Priority {
98        self.priority.clone()
99    }
100
101    fn id(&self) -> CmdId {
102        self.id
103    }
104
105    fn parent(&self) -> Prior<Address> {
106        self.parent
107    }
108
109    fn policy(&self) -> Option<&'a [u8]> {
110        self.policy
111    }
112
113    fn bytes(&self) -> &'a [u8] {
114        self.data
115    }
116
117    fn max_cut(&self) -> Result<usize, Bug> {
118        Ok(self.max_cut)
119    }
120}