Skip to content

Commit

Permalink
refactor(iroh): remove rpc artifacts from blobs
Browse files Browse the repository at this point in the history
  • Loading branch information
dignifiedquire committed May 2, 2024
1 parent 61df482 commit c208155
Show file tree
Hide file tree
Showing 17 changed files with 245 additions and 218 deletions.
33 changes: 19 additions & 14 deletions iroh-cli/src/commands/blob.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use indicatif::{
HumanBytes, HumanDuration, MultiProgress, ProgressBar, ProgressDrawTarget, ProgressState,
ProgressStyle,
};
use iroh::net::{key::PublicKey, relay::RelayUrl, NodeAddr};
use iroh::{
base::node_addr::AddrInfoOptions,
bytes::{
Expand All @@ -27,11 +26,15 @@ use iroh::{
};
use iroh::{
base::ticket::BlobTicket,
client::{BlobStatus, Iroh},
rpc_protocol::{
BlobDownloadRequest, BlobListCollectionsResponse, BlobListIncompleteResponse,
BlobListResponse, DownloadMode, ProviderService, SetTagOption, WrapOption,
client::Iroh,
rpc_protocol::{ProviderService, WrapOption},
};
use iroh::{
client::blobs::{
BlobInfo, BlobStatus, CollectionInfo, DownloadMode, DownloadOptions, IncompleteBlobInfo,
},
net::{key::PublicKey, relay::RelayUrl, NodeAddr},
rpc_protocol::SetTagOption,
};
use quic_rpc::ServiceConnection;
use tokio::io::AsyncWriteExt;
Expand Down Expand Up @@ -262,13 +265,15 @@ impl BlobCommands {

let mut stream = iroh
.blobs
.download(BlobDownloadRequest {
.download_with_opts(
hash,
format,
nodes: vec![node_addr],
tag,
mode,
})
DownloadOptions {
format,
nodes: vec![node_addr],
tag,
mode,
},
)
.await?;

show_download_progress(hash, &mut stream).await?;
Expand Down Expand Up @@ -452,21 +457,21 @@ impl ListCommands {
Self::Blobs => {
let mut response = iroh.blobs.list().await?;
while let Some(item) = response.next().await {
let BlobListResponse { path, hash, size } = item?;
let BlobInfo { path, hash, size } = item?;
println!("{} {} ({})", path, hash, HumanBytes(size));
}
}
Self::IncompleteBlobs => {
let mut response = iroh.blobs.list_incomplete().await?;
while let Some(item) = response.next().await {
let BlobListIncompleteResponse { hash, size, .. } = item?;
let IncompleteBlobInfo { hash, size, .. } = item?;
println!("{} ({})", hash, HumanBytes(size));
}
}
Self::Collections => {
let mut response = iroh.blobs.list_collections().await?;
while let Some(item) = response.next().await {
let BlobListCollectionsResponse {
let CollectionInfo {
tag,
hash,
total_blobs_count,
Expand Down
5 changes: 4 additions & 1 deletion iroh-cli/src/commands/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ use tokio::io::AsyncReadExt;
use iroh::{
base::{base32::fmt_short, node_addr::AddrInfoOptions},
bytes::{provider::AddProgress, Hash, Tag},
client::{Doc, Entry, Iroh, LiveEvent},
client::{
docs::{Doc, Entry, LiveEvent},
Iroh,
},
rpc_protocol::{ProviderService, SetTagOption, WrapOption},
sync::{
store::{DownloadPolicy, FilterKind, Query, SortDirection},
Expand Down
47 changes: 12 additions & 35 deletions iroh/examples/collection-fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@
use std::{env, str::FromStr};

use anyhow::{bail, ensure, Context, Result};
use iroh::{
base::ticket::BlobTicket,
bytes::BlobFormat,
rpc_protocol::{BlobDownloadRequest, DownloadMode},
};
use iroh::{base::ticket::BlobTicket, bytes::BlobFormat};
use tracing_subscriber::{prelude::*, EnvFilter};

// set the RUST_LOG env var to one of {debug,info,warn} to see logging info
Expand Down Expand Up @@ -53,32 +49,19 @@ async fn main() -> Result<()> {
.expect("a default relay url should be provided")
.to_string()
);
let req = BlobDownloadRequest {
// The hash of the content we are trying to download. Provided in the ticket.
hash: ticket.hash(),

// The format here is referring to the `BlobFormat`. We can request to download a single blob (which you can think of as a single file) or a `HashSeq` ("hash sequence"), which is a list of blobs you want to download.
// Iroh has a special kind of `HashSeq` called a "collection". A collection is just a `HashSeq` that reserves the first blob in the sequence for metadata about the `HashSeq`
// The metadata primarily contains the names of the blobs, which allows us, for example, to preserve filenames.
// When interacting with the iroh API, you will most likely be using blobs and collections.
format: ticket.format(),

// The `nodes` field is a list of `NodeAddr`, where each combines all of the known address information we have for the remote node.
// This includes the `node_id` (or `PublicKey` of the node), any direct UDP addresses we know about for that node, as well as the relay url of that node. The relay url is the url of the relay server that that node is connected to.
// If the direct UDP addresses to that node do not work, than we can use the relay node to attempt to holepunch between your current node and the remote node.
// If holepunching fails, iroh will use the relay node to proxy a connection to the remote node over HTTPS.
// Thankfully, the ticket contains all of this information
nodes: vec![ticket.node_addr().clone()],

// You can create a special tag name (`SetTagOption::Named`), or create an automatic tag that is derived from the timestamp.
tag: iroh::rpc_protocol::SetTagOption::Auto,

// Whether to use the download queue, or do a direct download.
mode: DownloadMode::Direct,
};
// Get the content we have just fetched from the iroh database.
ensure!(
ticket.format() == BlobFormat::HashSeq,
"'collection' example expects to fetch a collection, but the ticket indicates a single blob."
);

// `download` returns a stream of `DownloadProgress` events. You can iterate through these updates to get progress on the state of your download.
let download_stream = node.blobs.download(req).await?;
// `download` returns a stream of `DownloadProgress` events. You can iterate through these updates to get progress
// on the state of your download.
let download_stream = node
.blobs
.download_hash_seq(ticket.hash(), ticket.node_addr().clone())
.await?;

// You can also just `await` the stream, which poll the `DownloadProgress` stream for you.
let outcome = download_stream.await.context("unable to download hash")?;
Expand All @@ -89,12 +72,6 @@ async fn main() -> Result<()> {
ticket.node_addr().node_id
);

// Get the content we have just fetched from the iroh database.
ensure!(
ticket.format() == BlobFormat::HashSeq,
"'collection' example expects to fetch a collection, but the ticket indicates a single blob."
);

// If the `BlobFormat` is `HashSeq`, then we can assume for the example (and for any `HashSeq` that is derived from any iroh API), that it can be parsed as a `Collection`
// A `Collection` is a special `HashSeq`, where we preserve the names of any blobs added to the collection. (We do this by designating the first entry in the `Collection` as meta data.)
// To get the content of the collection, we first get the collection from the database using the `blobs` API
Expand Down
46 changes: 12 additions & 34 deletions iroh/examples/hello-world-fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@
use std::{env, str::FromStr};

use anyhow::{bail, ensure, Context, Result};
use iroh::{
base::ticket::BlobTicket,
bytes::BlobFormat,
rpc_protocol::{BlobDownloadRequest, DownloadMode},
};
use iroh::{base::ticket::BlobTicket, bytes::BlobFormat};
use tracing_subscriber::{prelude::*, EnvFilter};

// set the RUST_LOG env var to one of {debug,info,warn} to see logging info
Expand Down Expand Up @@ -53,32 +49,19 @@ async fn main() -> Result<()> {
.expect("a default relay url should be provided")
.to_string()
);
let req = BlobDownloadRequest {
// The hash of the content we are trying to download. Provided in the ticket.
hash: ticket.hash(),

// The format here is referring to the `BlobFormat`. We can request to download a single blob (which you can think of as a single file) or a `HashSeq` ("hash sequence"), which is a list of blobs you want to download.
// Iroh has a special kind of `HashSeq` called a "collection". A collection is just a `HashSeq` that reserves the first blob in the sequence for metadata about the `HashSeq`
// The metadata primarily contains the names of the blobs, which allows us, for example, to preserve filenames.
// When interacting with the iroh API, you will most likely be using blobs and collections.
format: ticket.format(),

// The `nodes` field is a list of `NodeAddr`, where each combines all of the known address information we have for the remote node.
// This includes the `node_id` (or `PublicKey` of the node), any direct UDP addresses we know about for that node, as well as the relay url of that node. The relay url is the url of the relay server that that node is connected to.
// If the direct UDP addresses to that node do not work, than we can use the relay node to attempt to holepunch between your current node and the remote node.
// If holepunching fails, iroh will use the relay node to proxy a connection to the remote node over HTTPS.
// Thankfully, the ticket contains all of this information
nodes: vec![ticket.node_addr().clone()],

// You can create a special tag name (`SetTagOption::Named`), or create an automatic tag that is derived from the timestamp.
tag: iroh::rpc_protocol::SetTagOption::Auto,

// Whether to use the download queue, or do a direct download.
mode: DownloadMode::Direct,
};
// If the `BlobFormat` is `Raw`, we have the hash for a single blob, and simply need to read the blob using the `blobs` API on the client to get the content.
ensure!(
ticket.format() == BlobFormat::Raw,
"'Hello World' example expects to fetch a single blob, but the ticket indicates a collection.",
);

// `download` returns a stream of `DownloadProgress` events. You can iterate through these updates to get progress on the state of your download.
let download_stream = node.blobs.download(req).await?;
// `download` returns a stream of `DownloadProgress` events. You can iterate through these updates to get progress
// on the state of your download.
let download_stream = node
.blobs
.download(ticket.hash(), ticket.node_addr().clone())
.await?;

// You can also just `await` the stream, which will poll the `DownloadProgress` stream for you.
let outcome = download_stream.await.context("unable to download hash")?;
Expand All @@ -90,11 +73,6 @@ async fn main() -> Result<()> {
);

// Get the content we have just fetched from the iroh database.
// If the `BlobFormat` is `Raw`, we have the hash for a single blob, and simply need to read the blob using the `blobs` API on the client to get the content.
ensure!(
ticket.format() == BlobFormat::Raw,
"'Hello World' example expects to fetch a single blob, but the ticket indicates a collection.",
);

let bytes = node.blobs.read_to_bytes(ticket.hash()).await?;
let s = std::str::from_utf8(&bytes).context("unable to parse blob as as utf-8 string")?;
Expand Down
41 changes: 16 additions & 25 deletions iroh/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,34 +10,25 @@ use crate::rpc_protocol::ProviderService;
pub mod mem;
pub mod quic;

mod authors;
mod blobs;
mod docs;
mod node;
mod tags;
pub mod authors;
pub mod blobs;
pub mod docs;
pub mod node;
pub mod tags;

pub use self::authors::Client as AuthorsClient;
pub use self::blobs::{
BlobAddOutcome, BlobAddProgress, BlobDownloadOutcome, BlobDownloadProgress, BlobReader,
BlobStatus, Client as BlobsClient,
};
pub use self::docs::{Client as DocsClient, Doc, Entry, LiveEvent};
pub use self::node::Client as NodeClient;
pub use self::tags::Client as TagsClient;

/// Iroh client
/// Iroh client.
#[derive(Debug, Clone)]
pub struct Iroh<C> {
/// Client for node operations.
pub node: NodeClient<C>,
pub node: node::Client<C>,
/// Client for blobs operations.
pub blobs: BlobsClient<C>,
pub blobs: blobs::Client<C>,
/// Client for docs operations.
pub docs: DocsClient<C>,
pub docs: docs::Client<C>,
/// Client for author operations.
pub authors: AuthorsClient<C>,
pub authors: authors::Client<C>,
/// Client for tags operations.
pub tags: TagsClient<C>,
pub tags: tags::Client<C>,
}

impl<C> Iroh<C>
Expand All @@ -47,11 +38,11 @@ where
/// Create a new high-level client to a Iroh node from the low-level RPC client.
pub fn new(rpc: RpcClient<ProviderService, C>) -> Self {
Self {
node: NodeClient { rpc: rpc.clone() },
blobs: BlobsClient { rpc: rpc.clone() },
docs: DocsClient { rpc: rpc.clone() },
authors: AuthorsClient { rpc: rpc.clone() },
tags: TagsClient { rpc },
node: node::Client { rpc: rpc.clone() },
blobs: blobs::Client { rpc: rpc.clone() },
docs: docs::Client { rpc: rpc.clone() },
authors: authors::Client { rpc: rpc.clone() },
tags: tags::Client { rpc },
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions iroh/src/client/authors.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! API for author management.
use anyhow::Result;
use futures_lite::{stream::StreamExt, Stream};
use iroh_sync::{Author, AuthorId};
Expand Down
Loading

0 comments on commit c208155

Please sign in to comment.