Development Documentation (main branch) - For stable release docs, see docs.rs/eidetica
Skip to main content

eidetica/instance/backend/
local.rs

1//! [`LocalBackend`]: the seam backed by a concrete in-process storage engine.
2
3use std::sync::Arc;
4
5use async_trait::async_trait;
6
7use super::Backend;
8use crate::{
9    Result,
10    backend::{BackendImpl, CacheScope, InstanceMetadata, VerificationStatus},
11    entry::{Entry, ID},
12    instance::WriteSource,
13    snapshot::Snapshot,
14};
15
16/// A [`Backend`] backed by a local [`BackendImpl`] (e.g. `InMemory`, SQLx).
17///
18/// Seam methods forward directly to the engine. The CRDT-state cache serves the
19/// trusted [`CacheScope::Shared`] scope (the daemon's own in-process path); the
20/// scope-keyed variants used by the service handlers reach the engine directly
21/// via [`Backend::local_engine`].
22#[derive(Clone)]
23pub struct LocalBackend(Arc<dyn BackendImpl>);
24
25impl LocalBackend {
26    pub fn new(engine: Arc<dyn BackendImpl>) -> Self {
27        Self(engine)
28    }
29}
30
31impl std::fmt::Debug for LocalBackend {
32    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33        f.debug_tuple("LocalBackend").finish()
34    }
35}
36
37#[async_trait]
38impl Backend for LocalBackend {
39    async fn get(&self, id: &ID) -> Result<Entry> {
40        self.0.get(id).await
41    }
42
43    async fn snapshot(&self, tree: &ID) -> Result<Snapshot> {
44        self.0.snapshot(tree).await
45    }
46
47    async fn store_snapshot(&self, tree: &ID, store: &str) -> Result<Snapshot> {
48        self.0.store_snapshot(tree, store).await
49    }
50
51    async fn store_snapshot_at(
52        &self,
53        tree: &ID,
54        store: &str,
55        main_snapshot: &Snapshot,
56    ) -> Result<Snapshot> {
57        self.0.store_snapshot_at(tree, store, main_snapshot).await
58    }
59
60    async fn store_at(&self, tree: &ID, store: &str, snapshot: &Snapshot) -> Result<Vec<Entry>> {
61        self.0.store_at(tree, store, snapshot).await
62    }
63
64    async fn find_merge_base(&self, tree: &ID, store: &str, entry_ids: &[ID]) -> Result<ID> {
65        self.0.find_merge_base(tree, store, entry_ids).await
66    }
67
68    async fn get_path_from_to(
69        &self,
70        tree: &ID,
71        store: &str,
72        from_id: &ID,
73        to_ids: &[ID],
74    ) -> Result<Vec<ID>> {
75        self.0.get_path_from_to(tree, store, from_id, to_ids).await
76    }
77
78    async fn get_cached_crdt_state(
79        &self,
80        _tree: &ID,
81        entry_id: &ID,
82        store: &str,
83    ) -> Result<Option<Vec<u8>>> {
84        self.0
85            .get_cached_crdt_state(&CacheScope::Shared, entry_id, store)
86            .await
87    }
88
89    async fn cache_crdt_state(
90        &self,
91        _tree: &ID,
92        entry_id: &ID,
93        store: &str,
94        state: Vec<u8>,
95    ) -> Result<()> {
96        self.0
97            .cache_crdt_state(CacheScope::Shared, entry_id, store, state)
98            .await
99    }
100
101    async fn put(&self, entry: Entry) -> Result<()> {
102        self.0.put(entry).await
103    }
104
105    async fn write_entry(
106        &self,
107        verification: VerificationStatus,
108        entry: Entry,
109        _source: WriteSource,
110    ) -> Result<()> {
111        let entry_id = entry.id();
112        self.0.put(entry).await?;
113        if verification != VerificationStatus::Unverified {
114            self.0
115                .update_verification_status(&entry_id, verification)
116                .await?;
117        }
118        Ok(())
119    }
120
121    async fn get_instance_metadata(&self) -> Result<Option<InstanceMetadata>> {
122        self.0.get_instance_metadata().await
123    }
124
125    async fn set_instance_metadata(&self, metadata: &InstanceMetadata) -> Result<()> {
126        self.0.set_instance_metadata(metadata).await
127    }
128
129    fn local_engine(&self) -> Option<Arc<dyn BackendImpl>> {
130        Some(Arc::clone(&self.0))
131    }
132}