noosphere_storage/
key_value.rs

1use std::fmt::Display;
2
3use anyhow::{anyhow, Result};
4use async_trait::async_trait;
5use noosphere_common::{ConditionalSend, ConditionalSync};
6use serde::{de::DeserializeOwned, Serialize};
7
8/// A [KeyValueStore] is a construct that is suitable for persisting generic
9/// key/value data to a storage backend.
10#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
11#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
12pub trait KeyValueStore: Clone + ConditionalSync {
13    /// Given some key that can be realized as bytes, persist a serializable
14    /// value to storage so that it can later be retrieved by that key
15    async fn set_key<K, V>(&mut self, key: K, value: V) -> Result<()>
16    where
17        K: AsRef<[u8]> + ConditionalSend,
18        V: Serialize + ConditionalSend;
19
20    /// Given some key that can be realized as bytes, retrieve some data that
21    /// can be deserialized as the intended data structure
22    async fn get_key<K, V>(&self, key: K) -> Result<Option<V>>
23    where
24        K: AsRef<[u8]> + ConditionalSend,
25        V: DeserializeOwned + ConditionalSend;
26
27    /// Given some key that can be realized as bytes, unset the value stored
28    /// against that key (if any)
29    async fn unset_key<K>(&mut self, key: K) -> Result<()>
30    where
31        K: AsRef<[u8]> + ConditionalSend;
32
33    /// Same as get_key, but returns an error if no value is found to be stored
34    /// against the key
35    async fn require_key<K, V>(&self, key: K) -> Result<V>
36    where
37        K: AsRef<[u8]> + ConditionalSend + Display,
38        V: DeserializeOwned + ConditionalSend,
39    {
40        let required = key.to_string();
41
42        match self.get_key(key).await? {
43            Some(value) => Ok(value),
44            None => Err(anyhow!("No value found for '{required}'")),
45        }
46    }
47
48    /// Flushes pending writes if there are any
49    async fn flush(&self) -> Result<()> {
50        Ok(())
51    }
52}