leaf_protocol/
store.rs

1//! Backend stores that may be used with the [`Leaf`] struct.
2
3use std::{fmt::Debug, future::Future};
4
5use anyhow::Result;
6use futures::Stream;
7
8use crate::{
9    types::{ExactLink, NamespaceId, NamespaceSecretKey, SubspaceId, SubspaceSecretKey},
10    Digest,
11};
12
13#[cfg(feature = "backend_iroh")]
14pub mod iroh;
15
16pub trait KeyResolverImpl<KeyId> {
17    /// Returns the `EncryptionAlgorithmId` that this implements.
18    fn id(&self) -> KeyId;
19    /// Resolve the given data to a key using this algorithm.
20    fn resolve(&self, data: &[u8]) -> KeyId;
21}
22
23pub trait EncryptionAlgorithmImpl<Digest> {
24    /// Returns the `EncryptionAlgorithmId` that this implements.
25    fn id(&self) -> Digest;
26    /// Encrypts the data using the provided key.
27    fn encrypt(&self, key_id: [u8; 32], data: &[u8]) -> Vec<u8>;
28    /// Decrypts the data using the provided key.
29    fn decrypt(&self, key_id: [u8; 32], data: &[u8]) -> Vec<u8>;
30}
31
32// TODO: Find way to avoid leaking blobs in the garbage collector.
33//
34// Right now the garbage collector cleans up data by the fact that every time you overwrite an
35// entity, it will look at the previous components of the entity, and remove all of the GC pins for
36// those components.
37//
38// The problem is that if a sync comes and inserts an update in between the time that I read the
39// previous version of the entity, and the time that I overwrite the previous version, I will have
40// missed the newly inserted entity, and replace it, without ever having removed it's garbage
41// collector pins.
42//
43// This situation means that live data should never have a problem getting deleted, but some dead
44// data might get left in the `_leaf_gc_` table forever.
45
46pub trait LeafStore: Debug {
47    /// Get an iterator over key resolver algorithms implemented by this backend.
48    // TODO: try avoid allocating while still being object safe.
49    fn key_resolvers(&self) -> Box<dyn Iterator<Item = &dyn KeyResolverImpl<Digest>> + '_>;
50    /// Get an iterator over encryption algorithms implemented by this backend.
51    fn encryption_algorithms(
52        &self,
53    ) -> Box<dyn Iterator<Item = &dyn EncryptionAlgorithmImpl<Digest>> + '_>;
54
55    fn create_subspace(&self) -> impl Future<Output = Result<SubspaceId>>;
56    fn get_subspace_secret(
57        &self,
58        subspace: SubspaceId,
59    ) -> impl Future<Output = Result<Option<SubspaceSecretKey>>>;
60    fn list_subspaces(
61        &self,
62    ) -> impl Future<Output = Result<impl Stream<Item = anyhow::Result<SubspaceId>>>>;
63    fn import_subspace_secret(
64        &self,
65        subspace_secret: SubspaceSecretKey,
66    ) -> impl Future<Output = Result<SubspaceId>>;
67
68    fn create_namespace(&self) -> impl Future<Output = Result<NamespaceId>>;
69    fn list_namespaces(
70        &self,
71    ) -> impl Future<Output = Result<impl Stream<Item = anyhow::Result<NamespaceId>>>>;
72    fn get_namespace_secret(
73        &self,
74        namespace: NamespaceId,
75    ) -> impl Future<Output = Result<Option<NamespaceSecretKey>>>;
76    fn import_namespace_secret(
77        &self,
78        secret: [u8; 32],
79    ) -> impl Future<Output = Result<NamespaceId>>;
80
81    /// Store a blob for an entity snapshot.
82    ///
83    /// You must specify a namespace to associate the blob to, an entity path, and an entity
84    /// snapshot.
85    ///
86    /// You can use the same namespace, entity path, and snapshot to delete the blob pins associated
87    /// to it with [`LeafStore::del_blobs()`].
88    fn store_blob(
89        &self,
90        data: &[u8],
91        link: &ExactLink,
92        entity_snapshot_id: Digest,
93    ) -> impl Future<Output = Result<Digest>>;
94    /// Delete a blob. This doesn't necessarily delete the blob immediately, but it removes the
95    /// garbage collector pin for the entity snapshot.
96    ///
97    /// Returns the number of blobs deleted.
98    fn del_blobs(
99        &self,
100        link: &ExactLink,
101        entity_snapshot_id: Digest,
102    ) -> impl Future<Output = Result<usize>>;
103    /// Get's a blob from the local store.
104    fn get_blob(&self, digest: Digest) -> impl Future<Output = Result<Vec<u8>>>;
105
106    fn store_entity(&self, link: &ExactLink, data: Vec<u8>)
107        -> impl Future<Output = Result<Digest>>;
108    fn del_entity(&self, link: &ExactLink) -> impl Future<Output = Result<()>>;
109    fn get_entity(&self, link: &ExactLink) -> impl Future<Output = Result<Option<Digest>>>;
110
111    fn list(
112        &self,
113        link: ExactLink,
114        limit: Option<u64>,
115        offset: Option<u64>,
116    ) -> impl Future<Output = Result<impl Stream<Item = anyhow::Result<ExactLink>>>>;
117}