This repository has been archived by the owner on Sep 21, 2024. It is now read-only.
feat!: Replace Bundle
with CAR streams in push
#624
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This change removes all usage of
Bundle
within our network code, replacing it with CARv1-formatted byte streams. These byte streams are produced by literalStream
s, which enable us to send large amounts of data back and forth without necessarily ballooning memory (though still subject to buffering by theStream
consumer).reqwest
streaming complicationsOne complicating factor I encountered in this change is that our HTTP client of choice (
reqwest
) brings some caveats when considering streaming requests.First, it's important to note: we prefer
reqwest
because it is adaptive to our Wasm targets, preferring ahyper
-based implementation on native targets but substituting afetch
-based API on web.Sync
streamsThe first challenge I hit is that all streams used in
reqwest
bodies must meet aSync
bound, and most of our streams do not rigorously enforce this bound at this time (it seemed plausible to me that we might be able to meet it with some refactoring). Although in theory it would be interesting to share a stream across many threads, where each thread polls the stream so that chunks could be processed in parallel, in practice we do not have this use case today. For details on why this bound is present inreqwest
, please follow the links in this issue I filed against the project: seanmonstar/reqwest#1969To resolve this issue, I have adapted a suggestion from a discussion in Rust internals. We now have a helper called
Unshared
that can wrap!Sync
things and add an unsafeSync
implementation to them. The wrapper only allows mutable borrows of the wrapped value, which presumably are exclusive, justifying theSync
bound. Additionally I added anUnsharedStream
wrapper that implementsStream
and gives us aStream + Sync
for anyStream + Send
that we wrap it with (viaUnshared
), enabling us to satisfy the bounds inreqwest
streaming bodies.Wasm streams
I encountered another complication with
reqwest
/Wasm: although streaming request bodies viafetch
are possible thanks toReadableStream
,reqwest
/Wasm does not implement support for them.So, to work around this, I added a conditional compilation branch to our client for push requests on
wasm32
targets. The upshot is that on web, we use a different request method when pushing that usesfetch
viagloo-net
with aReadableStream
body.Crate refactor
This change ended up leading to a major refactor of our crates. Implementing streaming push means adding streaming support to our API client. However, we have (on
main
) an existing dependency edge fromnoosphere-sphere
(where streaming is implemented) tonoosphere-api
(where the client is implemented). So, adding streaming support to the API client would have created a dependency cycle between our crates (which is not allowed). Originally, bothnoosphere-api
andnoosphere-sphere
were inlined to thenoosphere-core
crate, so I decided to migrate us back to that state with this change as it resolves the cyclical dependency. Thenoosphere-sphere
andnoosphere-api
crates will remain in-tree until we have the chance to publish a final,+deprecated
version for both of them.Breaking changes include:
noosphere-sphere
andnoosphere-api
crates, consolidating them withnoosphere-core
/api/v0alpha1/push
in favor of/api/v0alpha2/push
Bundle
SphereDb::put_block_stream
(replaced with more generalized helper)helpers
modules inside of their domain-relevant crates, and require thehelpers
feature to be used across cratestest_kubo
feature renamed totest-kubo