Skip to main content

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, MaxCut, 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
27#[cfg(feature = "low-mem-usage")]
28const COMMAND_SAMPLE_MAX: usize = 20;
29#[cfg(not(feature = "low-mem-usage"))]
30const COMMAND_SAMPLE_MAX: usize = 100;
31
32/// The maximum number of missing segments that can be requested
33/// in a single message
34#[cfg(feature = "low-mem-usage")]
35const REQUEST_MISSING_MAX: usize = 1;
36#[cfg(not(feature = "low-mem-usage"))]
37const REQUEST_MISSING_MAX: usize = 100;
38
39/// The maximum number of commands in a response
40#[cfg(feature = "low-mem-usage")]
41pub const COMMAND_RESPONSE_MAX: usize = 5;
42#[cfg(not(feature = "low-mem-usage"))]
43pub const COMMAND_RESPONSE_MAX: usize = 100;
44
45/// The maximum number of segments which can be stored to send
46#[cfg(feature = "low-mem-usage")]
47const SEGMENT_BUFFER_MAX: usize = 10;
48#[cfg(not(feature = "low-mem-usage"))]
49const SEGMENT_BUFFER_MAX: usize = 100;
50
51/// The maximum size of a sync message
52// TODO: Use postcard to calculate max size (which accounts for overhead)
53// https://docs.rs/postcard/latest/postcard/experimental/max_size/index.html
54pub const MAX_SYNC_MESSAGE_SIZE: usize = 1024 + MAX_COMMAND_LENGTH * COMMAND_RESPONSE_MAX;
55
56/// Represents high-level data of a command.
57#[derive(Serialize, Deserialize, Debug)]
58pub struct CommandMeta {
59    id: CmdId,
60    priority: Priority,
61    parent: Prior<Address>,
62    policy_length: u32,
63    length: u32,
64    max_cut: MaxCut,
65}
66
67impl CommandMeta {
68    pub fn address(&self) -> Address {
69        Address {
70            id: self.id,
71            max_cut: self.max_cut,
72        }
73    }
74}
75
76/// An error returned by the syncer.
77#[derive(Debug, thiserror::Error)]
78pub enum SyncError {
79    #[error("sync session ID does not match")]
80    SessionMismatch,
81    #[error("missing sync response")]
82    MissingSyncResponse,
83    #[error("syncer state not valid for this message")]
84    SessionState,
85    #[error("syncer not ready for operation")]
86    NotReady,
87    #[error("too many commands sent")]
88    CommandOverflow,
89    #[error("storage error: {0}")]
90    Storage(#[from] StorageError),
91    #[error("serialize error: {0}")]
92    Serialize(#[from] PostcardError),
93    #[error(transparent)]
94    Bug(#[from] Bug),
95}
96
97/// Sync command to be committed to graph.
98#[derive(Serialize, Deserialize, Debug)]
99pub struct SyncCommand<'a> {
100    priority: Priority,
101    id: CmdId,
102    parent: Prior<Address>,
103    policy: Option<&'a [u8]>,
104    data: &'a [u8],
105    max_cut: MaxCut,
106}
107
108impl<'a> Command for SyncCommand<'a> {
109    fn priority(&self) -> Priority {
110        self.priority.clone()
111    }
112
113    fn id(&self) -> CmdId {
114        self.id
115    }
116
117    fn parent(&self) -> Prior<Address> {
118        self.parent
119    }
120
121    fn policy(&self) -> Option<&'a [u8]> {
122        self.policy
123    }
124
125    fn bytes(&self) -> &'a [u8] {
126        self.data
127    }
128
129    fn max_cut(&self) -> Result<MaxCut, Bug> {
130        Ok(self.max_cut)
131    }
132}