Skip to content

Conversation

@TheBlueMatt
Copy link
Member

@TheBlueMatt TheBlueMatt commented Jan 7, 2026

Prevously, "async" HTTP calls were actually just spawning blocking
calls which were run in a background task and waited on. This is
obviously rather un-scalable (not to mention breaks with
single-threaded `tokio` executors) and can hang attempts to shut
down the `tokio` reactor.

Instead, here, we switch to doing actual async reads.

In order to avoid changing the API (so that we can ship a point
release), we still have to support returning a `ResponseLazy` from
`send_lazy_async`, which we obviously can't make async since
`ResponseLazy`'s read methods are sync. Instead, in that case we
pre-load the full response and store the bytes in `ResponseLazy`,
allowing it to read them as needed.

Asking claude to copy `ResponseLazy` to an `AsyncResponseLazy`
which reads from an actual async stream is left as an exercise for
the reader.

Fixes #441

TheBlueMatt and others added 3 commits January 7, 2026 00:49
This takes almost all our existing tests and converts them to
dual-sync-async, testing that both ways of running requests returns
the same results.
In the coming commits we'll move to actually async-ifying our
"async" HTTP fetching logic. Here we start by making the
response-reading utilities (which compromise the bulk of the logic)
dual-sync-async by shoving them in a macro that gets run twice.

Best reviewed with `--color-moved -b`
In the next commit we'll move to actually doing async reads when
making an async request. However, in the current work we want to
avoid changing the public API so that we can switch to real async
without a new minor version. Thus, because we cannot convert
`LazyResponse` to async, we have to ensure we complete all the
async bits before returning a "`LazyResponse`", and thus have to
pre-read the entire contents immediately.

Here we implement this with a new `Response` builder, reading as
required from an async stream.
Prevously, "async" HTTP calls were actually just spawning blocking
calls which were run in a background task and waited on. This is
obviously rather un-scalable (not to mention breaks with
single-threaded `tokio` executors) and can hang attempts to shut
down the `tokio` reactor.

Instead, here, we switch to doing actual async reads.

In order to avoid changing the API (so that we can ship a point
release), we still have to support returning a `ResponseLazy` from
`send_lazy_async`, which we obviously can't make async since
`ResponseLazy`'s read methods are sync. Instead, in that case we
pre-load the full response and store the bytes in `ResponseLazy`,
allowing it to read them as needed.

Asking claude to copy `ResponseLazy` to an `AsyncResponseLazy`
which reads from an actual async stream is left as an exercise for
the reader.

Fixes rust-bitcoin#441
Comment on lines -51 to +57
pub fn create_secured_stream(conn: &Connection) -> Result<HttpStream, Error> {
pub(super) fn create_secured_stream(conn: &Connection) -> Result<HttpStream, Error> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flagging that this module is private so this is not a breaking change.

Copy link
Member

@tcharding tcharding left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK aab48de

My review is quite shallow because I don't know much at all about async Rust.

@tcharding
Copy link
Member

Would be nice to get a review from someone who knows async but since this crate is so new and I blindly vibe coded all the async stuff anyways I'm happy to just run ACK, merge, YOLO policy on this crate for now. @TheBlueMatt?

@tcharding
Copy link
Member

I'm going to merge this. The CI fails are unrelated (#447).

@tcharding tcharding merged commit a9ff6a3 into rust-bitcoin:master Jan 8, 2026
27 of 30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bitreq: Use tokio::net types instead of spawn_blocking in AsyncConnection

2 participants