Skip to content

Commit 703fd2a

Browse files
committed
docs(examples): add transfer-collection example
1 parent 4645452 commit 703fd2a

File tree

2 files changed

+94
-1
lines changed

2 files changed

+94
-1
lines changed

examples/transfer-collection.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
use anyhow::{Context, Result};
2+
use iroh::{protocol::Router, Endpoint, NodeAddr, Watcher};
3+
use iroh_blobs::{
4+
api::{downloader::Shuffled, Store},
5+
format::collection::Collection,
6+
store::mem::MemStore,
7+
BlobsProtocol, Hash, HashAndFormat,
8+
};
9+
10+
struct Node {
11+
store: Store,
12+
router: Router,
13+
}
14+
15+
impl Node {
16+
async fn new() -> Result<Self> {
17+
let endpoint = Endpoint::builder().discovery_n0().bind().await?;
18+
19+
// We initialize an in-memory backing store for iroh-blobs
20+
let store = MemStore::new();
21+
// Then we initialize a struct that can accept blobs requests over iroh connections
22+
let blobs = BlobsProtocol::new(&store, endpoint.clone(), None);
23+
24+
let router = Router::builder(endpoint)
25+
.accept(iroh_blobs::ALPN, blobs)
26+
.spawn();
27+
28+
Ok(Self {
29+
store: store.into(),
30+
router,
31+
})
32+
}
33+
34+
async fn node_addr(&self) -> Result<NodeAddr> {
35+
let addr = self.router.endpoint().node_addr().initialized().await;
36+
Ok(addr)
37+
}
38+
39+
async fn list_hashes(&self) -> Result<Vec<Hash>> {
40+
self.store
41+
.blobs()
42+
.list()
43+
.hashes()
44+
.await
45+
.context("Failed to list hashes")
46+
}
47+
48+
async fn create_collection(&self) -> Result<Hash> {
49+
let tx = self.store.batch().await?;
50+
let a = tx.add_slice(b"a").await?;
51+
let b = tx.add_slice(b"b").await?;
52+
let c = tx.add_slice(b"c").await?;
53+
54+
let collection = Collection::from_iter([
55+
("a", a.hash().clone()),
56+
("b", b.hash().clone()),
57+
("c", c.hash().clone()),
58+
]);
59+
60+
let collection = collection.store(&self.store).await?;
61+
let hash = collection.hash().clone();
62+
self.store.tags().create(collection).await?;
63+
Ok(hash)
64+
}
65+
66+
async fn get_collection(&self, hash: Hash, provider: NodeAddr) -> Result<()> {
67+
self.router.endpoint().add_node_addr(provider.clone())?;
68+
let req = HashAndFormat::hash_seq(hash);
69+
let addrs = Shuffled::new(vec![provider.node_id]);
70+
self.store
71+
.downloader(self.router.endpoint())
72+
.download(req, addrs)
73+
.await?;
74+
Ok(())
75+
}
76+
}
77+
78+
#[tokio::main]
79+
async fn main() -> anyhow::Result<()> {
80+
let send_node = Node::new().await?;
81+
let send_node_addr = send_node.node_addr().await?;
82+
let hash = send_node.create_collection().await?;
83+
84+
let recv_node = Node::new().await?;
85+
recv_node.node_addr().await?;
86+
recv_node.get_collection(hash, send_node_addr).await?;
87+
88+
let send_hashes = send_node.list_hashes().await?;
89+
let recv_hashes = recv_node.list_hashes().await?;
90+
assert_eq!(send_hashes.len(), recv_hashes.len());
91+
92+
Ok(())
93+
}

src/api/blobs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,7 @@ pub struct AddPathOptions {
620620
/// stream directly can be inconvenient, so this struct provides some convenience
621621
/// methods to work with the result.
622622
///
623-
/// It also implements [`IntoFuture`], so you can await it to get the [`TempTag`] that
623+
/// It also implements [`IntoFuture`], so you can await it to get the [`TagInfo`] that
624624
/// contains the hash of the added content and also protects the content.
625625
///
626626
/// If you want access to the stream, you can use the [`AddProgress::stream`] method.

0 commit comments

Comments
 (0)