feat: Add Client::call_async#59
Draft
ValuedMammal wants to merge 4 commits into
Draft
Conversation
Previously, enabling `--all-features` would cause the lowest version feature to take precedence, which is counter-intuitive and incorrect for CI. Make the features additive so that `--all-features` implies the latest version feature. Each version feature explicitly enables the previous one. This means `--all-features` now correctly activates the highest version. Feature cfgs are updated throughout the library and integration tests to match the new behavior. `default` is now the minimum supported version (`28_0`), so that additional features can be given without conflict.
The previous Client owned a `jsonrpc::Client<BitreqHttpTransport>` directly, coupling all users to the bitreq HTTP transport. Introduce a layered architecture: `crate::Client`: transport-agnostic type that manages request building and ID tracking. Callers supply a `send_fn` closure per call. `bitreq::Client`: batteries-included HTTP client behind the `bitreq` feature flag (included in default). Owns a `Box<dyn Transport>` and exposes all RPC methods. Auth and cookie-file parsing live here. `with_auth` now accepts an explicit `timeout: Duration` and is renamed to `with_auth_timeout`. `corepc-types` is now an optional dependency pulled in by `bitreq`. Error variants only reachable through bitreq code are gated behind `bitreq` feature.
docs: Add `examples/call_async.rs` deps: Add dev-deps bitreq, tokio
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Description
Based on #27
Adds
Client::call_async— an async counterpart toClient::callfor use with async transports.The method accepts a
send_fn: AsyncFn(Value) -> Result<Response, E>closure rather than passing theRequestdirectly to the transport. Internally,call_asyncbuilds the request, serializes the request to an ownedserde_json::Value, calls thesend_fn, and deserializes the response like the sync path.A working example is included in call_async.rs using
bitreq::send_async()frombitreq's async feature.Notes to the reviewers
Why
AsyncFn(Value) -> Result<Response, E>instead of passingRequest<'_>to the transport?The natural design would mirror the sync API:
F: for<'r> AsyncFn(Request<'r>) -> Result<Response, E>. This was explored but seems to hit a Rust language limitation. An async closureasync |req| transport.send_request(req).awaitthat captures a reference cannot satisfyfor<'r> AsyncFn(Request<'r>), as the closure ties the future's lifetime to both the transport reference and the request lifetime, so the bound is never satisfied. Passing an ownedValuebreaks the lifetime chain entirely.The tradeoff is that callers cannot use
BitreqHttpTransport::send_requestdirectly (its return type is tied to the borrow ofselfvia aBoxFuture). Thebitreq::post()free function shown in the example is a workaround that avoids that issue. Another alternative is to support the async flavor ofTransportalongside the currentbitreqclient module, but this would lead to duplicating the API which is precisely what the sans-io design is meant to avoid.Changelog notice
Added
Client::call_async: async RPC method acceptingAsyncFn(Value) -> Result<Response, E>for use with async transports