Skip to content

feat(rust): re-export what a consumer driving the connector needs - #746

Draft
wkirschenmann wants to merge 4 commits into
wk/feat/csharp-options-generatorfrom
wk/feat/rust-transport-reexports
Draft

wkirschenmann wants to merge 4 commits into
wk/feat/csharp-options-generatorfrom
wk/feat/rust-transport-reexports

Conversation

@wkirschenmann

Copy link
Copy Markdown
Contributor

Sits on wk/feat/csharp-options-generator, to merge first.

Motivation

armonik-transport stops at the connector and leaves the HTTP/2 engine to whoever consumes it. It
therefore owes that consumer the crates the engine is spoken to, and a type it can write down to
hold the connector in.

Description

hyper-util's http2 feature is declared rather than relied on transitively, since it was on only
because hyper-rustls happens to ask for it and another crate's feature list can change. Writing it
down turns nothing on, and Cargo.lock staying byte-identical is the proof.

tokio, h2 and http-body-util are re-exported: the stream types the connector hands back, the
reason a stream was reset, the bodies hyper is given. The last two are dependencies for the
re-export alone, used nowhere in the crate, which is the point rather than the smell - taken from
crates.io separately, either can resolve to a version other than the one hyper was built against,
and the skew shows up as a type error at the seam.

Connector names HttpsConnector<ProxyConnector<HttpConnector>>, and ProxyConnector is exported
because it is a layer of it. That type was already public, being a public function's return type,
but unnameable outside the crate - the worst of both, since a consumer holding it in a struct field
had to erase it into a trait object for want of a name.

https_connector becomes synchronous: it awaits nothing, and being async charged every caller a
runtime for a future that never yields while leaving a caller already inside its only runtime with a
block_on that panics there rather than waits.

Testing

No test is added or removed - this declares a feature, adds three re-exports, exports a type and
drops an async. cargo test --workspace --all-features --no-fail-fast is unmoved, and the check
the first commit rests on is git diff --exit-code -- packages/rust/Cargo.lock after a build.

Impact

https_connector is no longer async, a breaking signature change; both callers are in armonik
and lose an .await, and the crate has no published release. A re-export guarantees versions, not
feature sets, which cargo unifies across the build; the README says so and names the case a consumer
is likeliest to meet.

Additional Information

tokio_stream is deliberately not re-exported: it used to arrive through tonic::codegen, and
nothing in the crate or its connector speaks it now.

Checklist

  • My code adheres to the coding and style guidelines of the project.
  • I have performed a self-review of my code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have made corresponding changes to the documentation.
  • I have thoroughly tested my modifications and added tests when necessary. (none needed here)
  • Tests pass locally and in the CI. (locally yes; CI has not run this branch)
  • I have assessed the performance impact of my modifications. (nothing measured)

@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown

☂️ Python Coverage

current status: ✅

Overall Coverage

Lines Covered Coverage Threshold Status
1478 1247 84% 0% 🟢

New Files

No new covered files...

Modified Files

No covered modified files...

updated for commit: 813fb17 by action🐍

@wkirschenmann
wkirschenmann force-pushed the wk/feat/rust-transport-reexports branch 2 times, most recently from 7155d44 to e10db52 Compare August 9, 2026 10:40
`hyper_util::client::legacy::Client` exists only when `http1` or `http2` is on, and the crate
re-exports `hyper_util` so a dependent can build that client over the connector. `http1` was named
here; `http2`, the protocol such a dependent actually speaks, was on only because `hyper-rustls`
happens to ask for it. Depending on another crate's feature list would break the day it changes.

Writing the feature down turns nothing on, which the lockfile is the proof of:

    cargo build --workspace --all-features                            -> Finished
    git diff --exit-code -- packages/rust/Cargo.lock                  -> no diff

    cargo test --workspace --all-features --no-fail-fast
      armonik-transport lib: 106 passed; every other target passed
      armonik lib: 5 passed, 110 failed, the pre-existing count for want of a running
      ArmoniK.Api.Mock server, unchanged by this commit
    cargo clippy --workspace --all-targets --all-features -- -D warnings              -> Finished
    cargo clippy --workspace --all-features --no-deps -- -Dwarnings
      -Dunused-crate-dependencies                                                     -> Finished
    cargo fmt --check                                                                 -> clean
The crate stops at the connector and leaves the HTTP/2 engine to whoever consumes it, so it owes
that consumer the crates the engine is spoken to: `tokio` for the stream types the connector hands
back, `h2` for the reason a stream was reset, `http_body_util` for the bodies hyper is given. Taken
from crates.io separately, any of the three can resolve to a version other than the one hyper was
built against, and the mismatch shows up as a type error at the seam.

`h2` and `http_body_util` become dependencies for the re-export alone and are used nowhere in the
crate; the module documents that, so a reader does not go looking for the call site. `tokio` was
already a dependency. `tokio_stream` is not here: it used to arrive through `tonic::codegen`, and
with tonic gone nothing in the crate or its connector speaks it.

Only the versions are guaranteed, not the feature sets, which cargo unifies across the whole build.
The module and the README both say so, because a consumer reaching for `tokio::runtime` through this
re-export is the way to be surprised by it. The README names the one feature a consumer is likely to
go looking for and not find: `http-body-util`'s `channel`, left off because the `tokio` edge it adds
belongs on the dependency of whoever feeds a request body, where the cost is attached to the need.

    cargo build --workspace --all-features                            -> Finished
    cargo test --workspace --all-features --no-fail-fast
      armonik-transport lib: 106 passed; every other target passed
      armonik lib: 5 passed, 110 failed, the pre-existing count for want of a running
      ArmoniK.Api.Mock server, unchanged by this commit
    cargo clippy --workspace --all-targets --all-features -- -D warnings              -> exit 0
    cargo clippy --workspace --all-features --no-deps -- -Dwarnings
      -Dunused-crate-dependencies                                                     -> exit 0
    cargo fmt --check                                                                 -> clean

`Cargo.lock` gains two edges from `armonik-transport` and no crate: both were already resolved for
the workspace, `h2` inside this crate's own tree through `hyper`'s `http2`.
…s built from

`https_connector` returns `HttpsConnector<ProxyConnector<HttpConnector>>`. That type was already
public, being the return type of a public function, but it could not be written down outside this
crate because `ProxyConnector` was not exported. Public and unnameable is the worst of both: a
consumer that wraps the connector in an engine of its own has to name the result to hold it, and
Rust cannot infer the type of a struct field, so it was pushed into a trait object erasing a
connector that has no reason to be erased.

`Connector` is that name, `ProxyConnector` is exported because it is a layer of it, and
`https_connector` loses the `#[doc(hidden)]` that was only hiding this. `ProxyConnector::new` stays
crate-private: the layer is assembled from an `HttpConfig`, never by hand.

    cargo build --workspace --all-features                            -> Finished
    cargo doc -p armonik-transport --all-features --no-deps           -> Finished, no warnings
    cargo test --workspace --all-features --no-fail-fast
      armonik-transport lib: 106 passed; every other target passed
      armonik lib: 5 passed, 110 failed, the pre-existing count for want of a running
      ArmoniK.Api.Mock server, unchanged by this commit
    cargo clippy --workspace --all-targets --all-features -- -D warnings              -> Finished
    cargo clippy --workspace --all-features --no-deps -- -Dwarnings
      -Dunused-crate-dependencies                                                     -> Finished
    cargo fmt --check                                                                 -> clean
It awaits nothing: the certificates were loaded when the configuration was read, and what is left is
assembling a connector, which opens no socket. Being `async` all the same charged every caller a
runtime for a future that never yields, and left a caller already inside its only runtime with a
`block_on` that panics there rather than waits - a restriction that would otherwise have to be
documented and honoured forever.

Both callers are in `armonik`, and each loses an `.await`: `client::channel::connect`, and the
`get_nb_request` test helper that reaches the mock server's diagnostic endpoint.

    cargo build --workspace --all-features                            -> Finished
    cargo test --workspace --all-features --no-fail-fast
      armonik-transport lib: 106 passed; every other target passed
      armonik lib: 5 passed, 110 failed, the pre-existing count for want of a running
      ArmoniK.Api.Mock server, unchanged by this commit
    cargo clippy --workspace --all-targets --all-features -- -D warnings              -> Finished
    cargo clippy --workspace --all-features --no-deps -- -Dwarnings
      -Dunused-crate-dependencies                                                     -> Finished
    cargo fmt --check                                                                 -> clean
@wkirschenmann
wkirschenmann force-pushed the wk/feat/rust-transport-reexports branch from e10db52 to 813fb17 Compare August 9, 2026 10:52
@sonarqubecloud

sonarqubecloud Bot commented Aug 9, 2026

Copy link
Copy Markdown

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.

1 participant