Skip to content

refactor(network): use async for registry network operations#16745

Open
arlosi wants to merge 13 commits intorust-lang:masterfrom
arlosi:async-pr
Open

refactor(network): use async for registry network operations#16745
arlosi wants to merge 13 commits intorust-lang:masterfrom
arlosi:async-pr

Conversation

@arlosi
Copy link
Contributor

@arlosi arlosi commented Mar 13, 2026

What does this PR try to resolve?

The existing model for registry index operations uses Poll + block_until_ready to enable parallelism. This model is somewhat awkward to work with, especially when parallelism is desired. Using async simplifies creating and working with registries.

Convert registry methods taking &mut self to &self

In order to execute multiple futures in parallel (using FuturesUnordered or similar), there must be multiple active borrows. Many of the registry querying methods used &mut self, which prevents this.

Any mutations are now handled by using Cell / RefCell. Since the executor is single-threaded, the operations aren't actually happening in parallel, but when passing an .await point, a different future could begin executing. We must be careful now not to hold mut borrows on RefCells across await points, as it will cause a panic.

Convert methods returning Poll<_> to return Future<_> (async).

When we want to block (and we're not in an async context), the async call is wrapped with futures::executor::block_on. If this is attempted within an existing async executor, cargo will panic.

Remove all block_until_ready methods from all Source, RegistryData traits

For most of the sources, the contents of the block_until_ready function was moved into a a private update function that's called once before making any queries.

Add new HTTP async http_async module

Wraps cURL's Multi interface to provide an async interface for making HTTP requests through cURL.

Add async-trait crate

This is used to enable dynamic dispatch on traits that use async fn.

Error message output changes

Due to refactoring around removing block_until_ready, some error messages are changed, usually by having additional context information. This change makes the error messages more consistent between various code paths. I attempted to minimize the changes in this PR for ease of review. We may want to simplify the error messages (by removing one level of context) in a follow up.

Resolver

The resolver is the only portion still using the Poll approach. An adapter layer in RegistryQueryer is added that immediately translates it into async.

Converting the resolver be async native is left as future work. In theory this conversion could provide performance improvements, since the resolution would not need to be restarted. It would also let the resolver start working immediately as new dependencies became available.

.crate downloading

The downloading of crate files using PackageSet is not yet converted to async. This is expected to be straightforward to do in a separate PR.

Progress reporting

The http_remote no longer has the ability to track how many block_until_ready calls have been made, so we can't do the trick where we assume we need 10 of them. The approach here is changed so the progress bar is completed/ (completed + pending). This means the progress bar can jump backwards.

How to review

Commit by commit. The final commit contains the majority of the change that was not straightforward to separate out.

@rustbot rustbot added A-configuration Area: cargo config files and env vars A-dependency-resolution Area: dependency resolution and the resolver A-directory-source Area: directory sources (vendoring) A-future-incompat Area: future incompatible reporting A-git Area: anything dealing with git A-infrastructure Area: infrastructure around the cargo repo, ci, releases, etc. A-interacts-with-crates.io Area: interaction with registries A-local-registry-source Area: local registry sources (vendoring) A-networking Area: networking issues, curl, etc. A-overrides Area: general issues with overriding dependencies (patch, replace, paths) A-rebuild-detection Area: rebuild detection and fingerprinting A-registries Area: registries A-source-replacement Area: [source] replacement A-sparse-registry Area: http sparse registries A-testing-cargo-itself Area: cargo's tests A-workspaces Area: workspaces Command-add Command-info Command-package Command-publish Command-update Command-vendor labels Mar 13, 2026
@arlosi arlosi force-pushed the async-pr branch 2 times, most recently from 5072ba5 to e09814c Compare March 13, 2026 15:03
@weihanglo
Copy link
Member

image

Impressive. Net -20 LoC changes!

@rustbot

This comment has been minimized.

@rustbot rustbot added the S-waiting-on-author Status: The marked PR is awaiting some action (such as code changes) from the PR author. label Mar 13, 2026
@arlosi arlosi force-pushed the async-pr branch 3 times, most recently from 4e38864 to a462b06 Compare March 13, 2026 17:44
@rustbot

This comment has been minimized.

@rustbot

This comment has been minimized.

@arlosi arlosi force-pushed the async-pr branch 3 times, most recently from 26e5fb2 to 5442223 Compare March 16, 2026 21:39
@rustbot

This comment has been minimized.

@arlosi
Copy link
Contributor Author

arlosi commented Mar 16, 2026

@rustbot ready

I've split the PR into several commits. The last one is still large, but it's about 1/2 the size.

@rustbot
Copy link
Collaborator

rustbot commented Mar 18, 2026

This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@arlosi
Copy link
Contributor Author

arlosi commented Mar 18, 2026

I've split the commits up further, though the last commit is still pretty large.

A few of the very small ones could probably go in their own PR independent of this one.

The commits that add functionality could go in their own PRs, but nothing would use them until later - such as the async http client.

github-merge-queue bot pushed a commit that referenced this pull request Mar 19, 2026
…#16763)

### What does this PR try to resolve?

Split out several smaller changes from #16745.

### How to test and review this PR?

Commit by commit. Each commit should pass tests.

r? @epage
@rustbot
Copy link
Collaborator

rustbot commented Mar 19, 2026

☔ The latest upstream changes (possibly #16763) made this pull request unmergeable. Please resolve the merge conflicts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-configuration Area: cargo config files and env vars A-dependency-resolution Area: dependency resolution and the resolver A-directory-source Area: directory sources (vendoring) A-future-incompat Area: future incompatible reporting A-git Area: anything dealing with git A-infrastructure Area: infrastructure around the cargo repo, ci, releases, etc. A-interacts-with-crates.io Area: interaction with registries A-local-registry-source Area: local registry sources (vendoring) A-networking Area: networking issues, curl, etc. A-overrides Area: general issues with overriding dependencies (patch, replace, paths) A-rebuild-detection Area: rebuild detection and fingerprinting A-registries Area: registries A-source-replacement Area: [source] replacement A-sparse-registry Area: http sparse registries A-testing-cargo-itself Area: cargo's tests A-workspaces Area: workspaces Command-add Command-info Command-install Command-package Command-publish Command-update Command-vendor S-waiting-on-author Status: The marked PR is awaiting some action (such as code changes) from the PR author. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants