Skip to main content

heddle_thread_api/replication/
store.rs

1//! Async durable-store boundary shared by device and hosted replication.
2use std::{collections::BTreeSet, future::Future};
3
4use crypto::{
5    thread_authority_admission::SignedAuthorityAdmission, thread_operation::SignedOperation,
6};
7use heddle_object_model::object::{
8    ContentHash,
9    thread_replication::{Admission, ThreadFacet},
10};
11
12/// Original immutable bytes plus optional independently signed first-authority
13/// admission. A receipt never replaces the original signature or current courier
14/// authorization, and remains attached across later peer relays.
15#[derive(Clone, Debug, PartialEq, Eq)]
16pub struct ReceivedOperation {
17    pub original: SignedOperation,
18    pub authority_admission: Option<SignedAuthorityAdmission>,
19}
20impl From<SignedOperation> for ReceivedOperation {
21    fn from(original: SignedOperation) -> Self {
22        Self {
23            original,
24            authority_admission: None,
25        }
26    }
27}
28
29/// Implementations commit before returning receipts. A store is bound to one
30/// authorized Thread; operations and peer metadata may never escape that scope.
31/// Notification delivery is separate from this durable contract.
32pub trait ReplicaStore: Clone + Send + Sync + 'static {
33    type Error: std::error::Error + Send + Sync + 'static;
34    fn thread_id(&self) -> ContentHash;
35    fn generation(&self) -> impl Future<Output = Result<i64, Self::Error>> + Send;
36    fn sharing(
37        &self,
38        destination: [u8; 32],
39    ) -> impl Future<Output = Result<BTreeSet<ThreadFacet>, Self::Error>> + Send;
40    fn frontier_page(
41        &self,
42        facet: ThreadFacet,
43        after: Option<ContentHash>,
44        limit: usize,
45    ) -> impl Future<Output = Result<Vec<ContentHash>, Self::Error>> + Send;
46    fn operation(
47        &self,
48        id: ContentHash,
49    ) -> impl Future<Output = Result<Option<(ReceivedOperation, Admission)>, Self::Error>> + Send;
50    fn receive(
51        &self,
52        operation: ReceivedOperation,
53    ) -> impl Future<Output = Result<Admission, Self::Error>> + Send;
54    fn remember_peer_heads(
55        &self,
56        peer: [u8; 32],
57        heads: Vec<(ThreadFacet, ContentHash)>,
58    ) -> impl Future<Output = Result<(), Self::Error>> + Send;
59    fn record_peer_receipt(
60        &self,
61        peer: [u8; 32],
62        id: ContentHash,
63        admission: Admission,
64    ) -> impl Future<Output = Result<(), Self::Error>> + Send;
65    fn settled_peer_heads(
66        &self,
67        peer: [u8; 32],
68        facets: BTreeSet<ThreadFacet>,
69        limit: usize,
70    ) -> impl Future<Output = Result<Vec<(ContentHash, Admission)>, Self::Error>> + Send;
71    fn needed_from_peer(
72        &self,
73        peer: [u8; 32],
74        facets: BTreeSet<ThreadFacet>,
75        limit: usize,
76    ) -> impl Future<Output = Result<Vec<ContentHash>, Self::Error>> + Send;
77}