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