Skip to content

Commit

Permalink
Merge pull request #28 from cowlicks/from-hc
Browse files Browse the repository at this point in the history
Add a method to make hyperbee from hypercore
  • Loading branch information
cowlicks authored Apr 1, 2024
2 parents cbee87e + 33af785 commit 00ad3e7
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 29 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

###Changed
- Added `Hyperbee::from_hypercore`.

### Changed


### Removed

- Removed some types that should not have been public:
* `HyperbeeBuilder` this was impossible to use anyway because it required a private type (`Tree`).
* `HyperbeeBuilderError` consumers should use `HyperbeeError` instead.


## [0.4.0] - 2024-03-31
Expand Down
2 changes: 1 addition & 1 deletion release.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ pre-release-replacements = [
{file="CHANGELOG.md", search="Unreleased", replace="{{version}}"},
{file="CHANGELOG.md", search="\\.\\.\\.HEAD", replace="...{{tag_name}}", exactly=1},
{file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}"},
{file="CHANGELOG.md", search="<!-- next-header -->", replace="<!-- next-header -->\n\n## [Unreleased] - ReleaseDate\n\n### Added\n\n###Changed\n\n### Removed\n\n", exactly=1},
{file="CHANGELOG.md", search="<!-- next-header -->", replace="<!-- next-header -->\n\n## [Unreleased] - ReleaseDate\n\n### Added\n\n### Changed\n\n### Removed\n\n", exactly=1},
{file="CHANGELOG.md", search="<!-- next-url -->", replace="<!-- next-url -->\n[Unreleased]: https://github.com/cowlicks/hyperbee/compare/{{tag_name}}...HEAD", exactly=1},
]
33 changes: 20 additions & 13 deletions src/hb.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
use std::{path::Path, sync::Arc};
use std::{fmt::Debug, path::Path, sync::Arc};

use derive_builder::Builder;
use futures_lite::Stream;
use hypercore::AppendOutcome;
use hypercore::{AppendOutcome, Hypercore};
use random_access_storage::RandomAccess;
use tokio::sync::RwLock;

use crate::{
error::HyperbeeError,
messages::header::Metadata,
prefixed::{Prefixed, PrefixedConfig},
traverse::{KeyDataResult, TraverseConfig},
tree, KeyValueData,
tree::Tree,
KeyValueData, Shared,
};

use super::{tree::Tree, Shared};

/// An append only B-Tree built on [`Hypercore`](hypercore::Hypercore). It provides a key-value
/// store API, with methods for [inserting](Hyperbee::put), [getting](Hyperbee::get), and
/// [deleting](Hyperbee::del) key-value pair. As well as creating [sorted
Expand Down Expand Up @@ -123,26 +123,33 @@ impl Hyperbee {
self.tree.read().await.traverse(conf).await
}

/// Helper for creating a Hyperbee
/// Create a [`Hyperbee`] from a storage directory
/// # Panics
/// when storage path is incorrect
/// when Hypercore failse to build
/// when Hypercore fails to build
/// when Blocks fails to build
///
/// # Errors
/// when Hyperbee fails to build
pub async fn from_storage_dir<T: AsRef<Path>>(
path_to_storage_dir: T,
) -> Result<Hyperbee, HyperbeeError> {
let tree = tree::Tree::from_storage_dir(path_to_storage_dir).await?;
Ok(HyperbeeBuilder::default()
.tree(Arc::new(RwLock::new(tree)))
.build()?)
Self::from_tree(Tree::from_storage_dir(path_to_storage_dir).await?)
}

/// Helper for creating a Hyperbee in RAM
/// Create a [`Hyperbee`] in RAM
pub async fn from_ram() -> Result<Hyperbee, HyperbeeError> {
let tree = tree::Tree::from_ram().await?;
Self::from_tree(Tree::from_ram().await?)
}

/// Helper for creating a [`Hyperbee`] from a [`Hypercore`]
pub fn from_hypercore<T: RandomAccess + Debug + Send + 'static>(
hypercore: Hypercore<T>,
) -> Result<Self, HyperbeeError> {
Self::from_tree(Tree::from_hypercore(hypercore)?)
}

fn from_tree(tree: Tree) -> Result<Self, HyperbeeError> {
Ok(HyperbeeBuilder::default()
.tree(Arc::new(RwLock::new(tree)))
.build()?)
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use messages::yolo_index;
use tree::Tree;

pub use error::HyperbeeError;
pub use hb::{Hyperbee, HyperbeeBuilder, HyperbeeBuilderError};
pub use hb::Hyperbee;
pub use messages::header::Metadata;

type Shared<T> = Arc<RwLock<T>>;
Expand Down
47 changes: 34 additions & 13 deletions src/tree.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use derive_builder::Builder;
use futures_lite::{Stream, StreamExt};
use hypercore::{AppendOutcome, HypercoreBuilder, Storage};
use hypercore::{AppendOutcome, Hypercore, HypercoreBuilder, Storage};
use prost::Message;
use random_access_storage::RandomAccess;

use crate::{
blocks::{Blocks, BlocksBuilder},
Expand All @@ -12,6 +13,7 @@ use crate::{
Node, Shared, PROTOCOL,
};
use std::{
fmt::Debug,
path::{Path, PathBuf},
sync::Arc,
};
Expand Down Expand Up @@ -144,33 +146,34 @@ impl Tree {
Ok(stream.map(move |kv_and_node| kv_and_node.0))
}

/// Helper for creating a Hyperbee
/// # Panics
/// when storage path is incorrect
/// when Hypercore failse to build
/// when Blocks fails to build
///
/// # Errors
/// when Hyperbee fails to build
pub async fn from_storage_dir<T: AsRef<Path>>(
path_to_storage_dir: T,
) -> Result<Tree, HyperbeeError> {
let p: PathBuf = path_to_storage_dir.as_ref().to_owned();
let storage = Storage::new_disk(&p, false).await?;
let hc = Arc::new(Mutex::new(HypercoreBuilder::new(storage).build().await?));
let blocks = BlocksBuilder::default().core(hc).build()?;
Ok(TreeBuilder::default()
.blocks(Arc::new(RwLock::new(blocks)))
.build()?)
Self::from_blocks(blocks)
}
/// Helper for creating a Hyperbee in RAM
pub async fn from_ram() -> Result<Tree, HyperbeeError> {
let hc = Arc::new(Mutex::new(
HypercoreBuilder::new(Storage::new_memory().await?)
.build()
.await?,
));
let blocks = BlocksBuilder::default().core(hc).build()?;
Self::from_blocks(blocks)
}

pub fn from_hypercore<T: RandomAccess + Debug + Send + 'static>(
hypercore: Hypercore<T>,
) -> Result<Self, HyperbeeError> {
let hc = Arc::new(Mutex::new(hypercore));
let blocks = BlocksBuilder::default().core(hc).build()?;
Self::from_blocks(blocks)
}

fn from_blocks(blocks: Blocks) -> Result<Self, HyperbeeError> {
Ok(TreeBuilder::default()
.blocks(Arc::new(RwLock::new(blocks)))
.build()?)
Expand All @@ -185,6 +188,24 @@ impl Clone for Tree {
}
}

#[cfg(test)]
mod test {
use super::*;

#[tokio::test]
async fn from_hc() -> Result<(), HyperbeeError> {
let hc = HypercoreBuilder::new(Storage::new_memory().await?)
.build()
.await?;
let tree = Tree::from_hypercore(hc)?;
assert_eq!((None, 1), tree.put(b"hello", Some(b"world")).await?);
assert_eq!(
tree.get(b"hello").await?,
Some((1u64, Some(b"world".into())))
);
Ok(())
}
}
#[cfg(feature = "debug")]
#[cfg(test)]
mod test {
Expand Down

0 comments on commit 00ad3e7

Please sign in to comment.