eidetica/instance/backend/
remote.rs1use async_trait::async_trait;
4
5use super::Backend;
6use crate::{
7 Result,
8 auth::SigKey,
9 backend::{InstanceMetadata, VerificationStatus},
10 entry::{Entry, ID},
11 instance::WriteSource,
12 service::{client::RemoteConnection, protocol::ReadScope},
13 snapshot::Snapshot,
14};
15
16#[derive(Debug, Clone)]
35pub struct RemoteBackend {
36 conn: RemoteConnection,
37 identity: Option<SigKey>,
38}
39
40impl RemoteBackend {
41 pub fn new(conn: RemoteConnection, identity: Option<SigKey>) -> Self {
42 Self { conn, identity }
43 }
44
45 fn identity(&self) -> SigKey {
48 self.identity
49 .clone()
50 .or_else(|| self.conn.session_identity())
51 .unwrap_or_default()
52 }
53}
54
55#[async_trait]
56impl Backend for RemoteBackend {
57 async fn get(&self, id: &ID) -> Result<Entry> {
58 self.conn
62 .db_get_entry(ID::default(), self.identity(), id.clone())
63 .await
64 }
65
66 async fn snapshot(&self, tree: &ID) -> Result<Snapshot> {
67 match self
68 .conn
69 .get_verified_tips(tree.clone(), self.identity())
70 .await
71 {
72 Ok(snapshot) => Ok(snapshot),
73 Err(e) if e.is_not_found() => Ok(Snapshot::EMPTY),
74 Err(e) => Err(e),
75 }
76 }
77
78 async fn store_snapshot(&self, tree: &ID, store: &str) -> Result<Snapshot> {
79 let tree_tips = match self
80 .conn
81 .get_verified_tips(tree.clone(), self.identity())
82 .await
83 {
84 Ok(tips) => tips,
85 Err(e) if e.is_not_found() => return Ok(Snapshot::EMPTY),
86 Err(e) => return Err(e),
87 };
88 if tree_tips.is_empty() {
89 return Ok(Snapshot::EMPTY);
90 }
91 match self
92 .conn
93 .store_snapshot_at(
94 tree.clone(),
95 self.identity(),
96 store.to_string(),
97 tree_tips.into_tips(),
98 )
99 .await
100 {
101 Ok(snapshot) => Ok(snapshot),
102 Err(e) if e.is_not_found() => Ok(Snapshot::EMPTY),
103 Err(e) => Err(e),
104 }
105 }
106
107 async fn store_snapshot_at(
108 &self,
109 tree: &ID,
110 store: &str,
111 main_snapshot: &Snapshot,
112 ) -> Result<Snapshot> {
113 match self
114 .conn
115 .store_snapshot_at(
116 tree.clone(),
117 self.identity(),
118 store.to_string(),
119 main_snapshot.tips().to_vec(),
120 )
121 .await
122 {
123 Ok(snapshot) => Ok(snapshot),
124 Err(e) if e.is_not_found() => Ok(Snapshot::EMPTY),
125 Err(e) => Err(e),
126 }
127 }
128
129 async fn store_at(&self, tree: &ID, store: &str, snapshot: &Snapshot) -> Result<Vec<Entry>> {
130 self.conn
131 .get_store_entries(
132 tree.clone(),
133 self.identity(),
134 store.to_string(),
135 snapshot.tips().to_vec(),
136 ReadScope::Verified,
137 )
138 .await
139 }
140
141 async fn find_merge_base(&self, tree: &ID, store: &str, entry_ids: &[ID]) -> Result<ID> {
142 let state = self
143 .conn
144 .compute_merge_state(
145 tree.clone(),
146 self.identity(),
147 store.to_string(),
148 entry_ids.to_vec(),
149 )
150 .await?;
151 Ok(state.merge_base)
152 }
153
154 async fn get_path_from_to(
155 &self,
156 tree: &ID,
157 store: &str,
158 _from_id: &ID,
159 to_ids: &[ID],
160 ) -> Result<Vec<ID>> {
161 let state = self
164 .conn
165 .compute_merge_state(
166 tree.clone(),
167 self.identity(),
168 store.to_string(),
169 to_ids.to_vec(),
170 )
171 .await?;
172 Ok(state.path)
173 }
174
175 async fn get_cached_crdt_state(
176 &self,
177 tree: &ID,
178 entry_id: &ID,
179 store: &str,
180 ) -> Result<Option<Vec<u8>>> {
181 if let Some(blob) = self.conn.cache_get(tree, entry_id, store) {
183 return Ok(Some(blob));
184 }
185 let blob = self
187 .conn
188 .get_cached_crdt_state_remote(
189 tree.clone(),
190 self.identity(),
191 store.to_string(),
192 entry_id.clone(),
193 )
194 .await?;
195 if let Some(b) = &blob {
196 self.conn
197 .cache_put(tree.clone(), entry_id.clone(), store.to_string(), b.clone());
198 }
199 Ok(blob)
200 }
201
202 async fn cache_crdt_state(
203 &self,
204 tree: &ID,
205 entry_id: &ID,
206 store: &str,
207 state: Vec<u8>,
208 ) -> Result<()> {
209 self.conn.cache_put(
212 tree.clone(),
213 entry_id.clone(),
214 store.to_string(),
215 state.clone(),
216 );
217 self.conn
219 .cache_crdt_state_remote(
220 tree.clone(),
221 self.identity(),
222 store.to_string(),
223 entry_id.clone(),
224 state,
225 )
226 .await
227 }
228
229 async fn put(&self, entry: Entry) -> Result<()> {
230 let tree_root = entry.root().unwrap_or_else(|| entry.id());
231 self.conn
232 .submit_signed_entry(tree_root, self.identity(), entry)
233 .await
234 }
235
236 async fn write_entry(
237 &self,
238 _verification: VerificationStatus,
239 entry: Entry,
240 _source: WriteSource,
241 ) -> Result<()> {
242 let tree_root = entry.root().unwrap_or_else(|| entry.id());
245 self.conn
246 .submit_signed_entry(tree_root, self.identity(), entry)
247 .await
248 }
249
250 async fn get_instance_metadata(&self) -> Result<Option<InstanceMetadata>> {
251 self.conn.get_instance_metadata().await
252 }
253
254 async fn set_instance_metadata(&self, metadata: &InstanceMetadata) -> Result<()> {
255 self.conn.set_instance_metadata(metadata).await
256 }
257
258 fn remote_connection(&self) -> Option<RemoteConnection> {
259 Some(self.conn.clone())
260 }
261}