Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

example: Multiprovider downloader #62

Open
wants to merge 47 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
fa8fab4
start downloader engine
rklaehn Jan 29, 2025
23817cc
WIP
rklaehn Jan 29, 2025
090e54b
WIP
rklaehn Jan 29, 2025
8caf034
WIP
rklaehn Jan 30, 2025
e945d1c
WIP
rklaehn Jan 30, 2025
7f3f22f
WIP
rklaehn Jan 30, 2025
9af5698
wip
rklaehn Jan 30, 2025
ebc8454
Add large test
rklaehn Jan 30, 2025
002503f
add planner
rklaehn Jan 31, 2025
f20bc2e
Add fast download start
rklaehn Jan 31, 2025
3885954
DRY
rklaehn Jan 31, 2025
ae5f05c
incremental scenario
rklaehn Jan 31, 2025
e46182e
delayed rebalance
rklaehn Jan 31, 2025
a14ab1f
plug in planner
rklaehn Jan 31, 2025
3bc8b35
newtypes
rklaehn Feb 3, 2025
a94d800
Add and handle PeerDownloadComplete
rklaehn Feb 3, 2025
871b343
WIP
rklaehn Feb 3, 2025
414715f
remame bitmap to bitfield part 1
rklaehn Feb 4, 2025
b39d1f9
rename bitmap to bitfield
rklaehn Feb 4, 2025
94eaf5f
Properly handle dropping downloads
rklaehn Feb 4, 2025
6073d6c
more tests
rklaehn Feb 7, 2025
04712e3
Fix warnings
rklaehn Feb 7, 2025
ff029a6
Add multiprovider example
rklaehn Feb 7, 2025
64d7ea8
Add debug output
rklaehn Feb 7, 2025
730bcf6
Working multiprovider example
rklaehn Feb 7, 2025
5c91fd4
Add way to keep node id stable in multiprovider example provide
rklaehn Feb 10, 2025
5a658f6
Show some progress bars
rklaehn Feb 10, 2025
9ba84c3
Don't use DownloadRequest for internal state
rklaehn Feb 10, 2025
87938af
start moving stuff into separate mods
rklaehn Feb 10, 2025
e3ff68f
Move things into modules
rklaehn Feb 10, 2025
0706098
more moving stuff around
rklaehn Feb 10, 2025
84fbe80
clippy
rklaehn Feb 11, 2025
dbf20de
more clippy
rklaehn Feb 11, 2025
a8015d5
Extend multiprovider example with persistent local storage
rklaehn Feb 11, 2025
d511286
fix off by one bug in the quick hacky valid_ranges
rklaehn Feb 11, 2025
b55267b
Make the test a real test
rklaehn Feb 12, 2025
ea3595a
Unify BitfieldEvent and BitfieldSubscriptionEvent
rklaehn Feb 12, 2025
704c7eb
Unify BitfieldEvents and start adding size (not used yet)
rklaehn Feb 12, 2025
ced9b95
Make use of the size
rklaehn Feb 12, 2025
43b9842
introduce BitfieldUpdate and BitfieldState structs
rklaehn Feb 12, 2025
18d7688
First somewhat working size handling approach
rklaehn Feb 12, 2025
54ec3e3
Even more size refactoring
rklaehn Feb 13, 2025
419f8d8
Move entire multiprovider downloader into an example.
rklaehn Feb 21, 2025
1905089
fmt & clippy
rklaehn Feb 21, 2025
c9146e9
codespell
rklaehn Feb 21, 2025
177dfce
Increase stripe size and add readme
rklaehn Feb 21, 2025
e5d231a
more limitations
rklaehn Feb 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,10 @@ required-features = ["example-iroh"]
name = "custom-protocol"
required-features = ["example-iroh"]

[[example]]
name = "multiprovider"
required-features = ["example-iroh"]

[lints.rust]
missing_debug_implementations = "warn"

Expand Down
96 changes: 96 additions & 0 deletions examples/multiprovider/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Multiprovider

This example shows how to use iroh-blobs to download concurrently from multiple
providers. As of now, the infrastructure to do this is included in the example.
It will move into the main crate soon.

## Usage

This example requires the `rpc` feature, so is is easiest to run it with
`--all-features`. Also, if you want try it out with large blobs such as ML
models, it is best to run in release mode.

There are two subcommands, `provide` and `download`.

### Provide

Provide provides a *single* blob, printing the blob hash and the node id.

### Download

Download downloads a *single* hash from any number of node ids.

In the long
term we are going to have content discovery based on trackers or other mechanisms,
but for this example you just have to provide the node ids in the command line.

To have a stable node id, it is
possible to provide the iroh node secret in an environment variable.

**This is fine for an example, but don't do it in production**

## Trying it out

Multiprovider downloads are mostly relevant for very large downloads, so let's
use a large file, a ~4GB ML model.

Terminal 1:

```
> IROH_SECRET=<secret1> \
cargo run --release --all-features --example multiprovider \
provide ~/.ollama/models/blobs/sha256-96c415656d377afbff962f6cdb2394ab092ccbcbaab4b82525bc4ca800fe8a49
added /Users/rklaehn/.ollama/models/blobs/sha256-96c415656d377afbff962f6cdb2394ab092ccbcbaab4b82525bc4ca800fe8a49 as e5njueepdum3ks2usqdxw3ofztj63jgedtnfak34smgvw5b6cr3a, 4683073184 bytes, 4573314 chunks
listening on 28300fcb69830c3e094c68f383ffd568dd9aa9126a6aa537c3dcfec077b60af9
```

Terminal 2:

```
❯ IROH_SECRET=<secret2> \
cargo run --release --all-features --example multiprovider \
provide ~/.ollama/models/blobs/sha256-96c415656d377afbff962f6cdb2394ab092ccbcbaab4b82525bc4ca800fe8a49
added /Users/rklaehn/.ollama/models/blobs/sha256-96c415656d377afbff962f6cdb2394ab092ccbcbaab4b82525bc4ca800fe8a49 as e5njueepdum3ks2usqdxw3ofztj63jgedtnfak34smgvw5b6cr3a, 4683073184 bytes, 4573314 chunks
listening on 77d81595422c0a757b9e3f739f9a67eab9646f13d941654e9074982c5c800a5a
```

So now we got 2 node ids,
`77d81595422c0a757b9e3f739f9a67eab9646f13d941654e9074982c5c800a5a` and
`28300fcb69830c3e094c68f383ffd568dd9aa9126a6aa537c3dcfec077b60af9`, providing
the data.

Note that the provide side is not in any way special. It is just using the
existing iroh-blobs protocol, so any other iroh node could be used as well.

For downloading, we don't need a stable node id, so we don't need to bother with
setting IROH_SECRET.

```
> cargo run --release --all-features --example multiprovider \
download e5njueepdum3ks2usqdxw3ofztj63jgedtnfak34smgvw5b6cr3a \
28300fcb69830c3e094c68f383ffd568dd9aa9126a6aa537c3dcfec077b60af9 \
77d81595422c0a757b9e3f739f9a67eab9646f13d941654e9074982c5c800a5a

peer discovered for hash e5njueepdum3ks2usqdxw3ofztj63jgedtnfak34smgvw5b6cr3a: 28300fcb69830c3e094c68f383ffd568dd9aa9126a6aa537c3dcfec077b60af9
peer discovered for hash e5njueepdum3ks2usqdxw3ofztj63jgedtnfak34smgvw5b6cr3a: 77d81595422c0a757b9e3f739f9a67eab9646f13d941654e9074982c5c800a5a
█████████▓ ░█████████░
```

The download side will initially download from the first peer, then quickly
rebalance the download as a new peer becomes available. It will currently
download from each peer in "stripes".

When running without `--path` argument it will download into a memory store.
When providing a `--path` argument it will download into a persistent store at the
given path, and the download will resume if you interrupt the download process.

## Notes on the current state

The current state of the downloader is highly experimental. While peers that don't
respond at all are handled properly, peers that are slow or become slow over time
are not properly punished. Also, there is not yet a mechanism to limit the number
of peers to download from.

In addition, the current blob store does not have the ability to watch a bitfield
of available chunks for a blob. The current multiprovider downloader just fakes
this by assuming that all remote stores have the full file.
Loading
Loading