Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: update and turn WsTransportClientBuilder generic #1168

Conversation

oleonardolima
Copy link
Contributor

@oleonardolima oleonardolima commented Aug 7, 2023

e7ecb9d refactor(jsonrpsee-client-transport): update and turn WsTransportClientBuilder generic

  • fix(docs): typo on WsTransportClientBuilder doc on Receiver
    reference.
  • refactor: add initial fn signatures for build_with_stream,
    try_connect_over_tcp, and try_connect.
  • refactor: expose EitherStream visibility to public.
  • refactor: make Sender and Receiver generic over T, a data stream.
  • refactor: make TransportSenderT and TransportReceiverT
    implementations over generic Sender and Receiver, bound to
    AsyncRead, AsyncRead, MaybeSend and 'static.
  • refactor: turn old try_connect TCP steps into
    try_connect_over_tcp.
  • feat: implement build_with_stream and try_connect to handle and
    handle the handshake for a generic data stream T.
  • feat: add new Redirected error variant to WsHandshakeError, as it
    should be handled by the client when using a generic data stream T.

c7ae7dd refactor(jsonrpsee-ws-client): add new fns to WsClientBuilder

  • feat: add new WsClientBuilder::build_with_transport that builds and
    returns a WsClient with the given Sender and Receiver.
  • feat: add new WsClientBuilder::build_with_stream that uses the new
    WsTransportClientBuilder::build_with_stream, building and returning
    the WsClient with the given data_stream as transport layer.
  • refactor: update the WsClientBuilder::build to use the new
    build_with_transport, it helps not having duplicated code.

10e78a0 refactor: re-export EitherStream & sort current list

53641d1 test: add integration tests and helper fns

  • add new helper fns to spawn a socks5 server, using fast-socks5
  • add new helper enum for DataStream that acts as a wrapper to
    Socks5Stream<T>, similar to what a client would need to do.
  • impl AsyncRead + AsyncWrite for the helper DataStream enum, to make
    it compatible between futures::io and tokio::io.
  • add new tests that connects over a socks5 proxy, and use the new
    `WsClientBuilder::default()::build_with_stream(...) fn.

fixes #1162 #870

@oleonardolima oleonardolima force-pushed the refactor/update-ws-client-transport-to-generic-over-stream branch from cdc6ce4 to 7985210 Compare August 23, 2023 00:39
@niklasad1
Copy link
Member

@oleonardolima any update on this one?

Let us know whether you need help to push this further.

@oleonardolima
Copy link
Contributor Author

@niklasad1 I plan to get back to it by the end of the week. Sorry for the delayed PR, conferences and changing jobs got me delayed on it.

@oleonardolima oleonardolima force-pushed the refactor/update-ws-client-transport-to-generic-over-stream branch 4 times, most recently from 9a08f03 to c7ae7dd Compare October 20, 2023 01:08
@oleonardolima
Copy link
Contributor Author

oleonardolima commented Oct 20, 2023

@oleonardolima any update on this one?

Let us know whether you need help to push this further.

@niklasad1 Do you see any problem with adding the arti-client dependency on jsonrpsee-integration-tests in order to have integration tests for different streams other than tokio::net::TcpStream ?

@oleonardolima oleonardolima changed the title wip(refactor): update and turn WsTransportClientBuilder generic refactor: update and turn WsTransportClientBuilder generic Oct 20, 2023
@oleonardolima oleonardolima force-pushed the refactor/update-ws-client-transport-to-generic-over-stream branch from c7ae7dd to 988bd1e Compare October 20, 2023 02:52
@niklasad1
Copy link
Member

niklasad1 commented Oct 20, 2023

@niklasad1 Do you see any problem with adding the arti-client dependency on jsonrpsee-integration-tests in order to have integration tests for different streams other than tokio::net::TcpStream ?

It's not possible to use a more light-weight dependency than arti-client for that?

I'm happy if we just have a test to wrap another stream using the WsTransportBuilder::build_with_stream and assert connecting and make a simple RPC call works.

Copy link
Member

@niklasad1 niklasad1 left a comment

Choose a reason for hiding this comment

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

Yupp, nice looks you are on the right path.

This PR just needs to fix a few minor things + add few tests then it should be good to go.

@oleonardolima oleonardolima force-pushed the refactor/update-ws-client-transport-to-generic-over-stream branch from 988bd1e to f1f93fe Compare October 21, 2023 16:35
@oleonardolima
Copy link
Contributor Author

It's not possible to use a more light-weight dependency than arti-client for that?

I'm happy if we just have a test to wrap another stream using the WsTransportBuilder::build_with_stream and assert connecting and make a simple RPC call works.

Sure, I'll check if there is a more light-weight one.

PS.: We can use the TcpStream, but wouldn't be testing anything new in my opinion (because is the default already used one)

@niklasad1
Copy link
Member

PS.: We can use the TcpStream, but wouldn't be testing anything new in my opinion (because is the default already used one)

Yeah, I agree that we should test with another one

@oleonardolima oleonardolima force-pushed the refactor/update-ws-client-transport-to-generic-over-stream branch from f1f93fe to 4c702df Compare November 8, 2023 01:18

#[pin_project(project = DataStreamProj)]
#[allow(dead_code)]
pub enum DataStream<T: tokio::io::AsyncRead + tokio::io::AsyncWrite + std::marker::Unpin> {
Copy link
Member

@niklasad1 niklasad1 Nov 15, 2023

Choose a reason for hiding this comment

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

I don't understand why this type is needed, can't you just use fast_socks5::client::Socks5Stream directly instead because it already implements AsyncRead and AsyncWrite?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@niklasad1 It does implement the tokio::io::AsyncRead and tokio::io::AsyncWrite, but currently the TransportSenderT and TransportReceiverT requires the futures::io::AsyncRead and futures::io::AsyncRead implementation.

I made this way not to change the current implementation of EitherStream, which implements the futures::io traits.

I can change the EitherStream to use the tokio::io traits instead, do you see any problem ?

I'm actually biased because requiring the tokio traits as default would make it easier for me on other projects 😅

Copy link
Member

Choose a reason for hiding this comment

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

This is just for tests so I don't mind having this extra code.

I can change the EitherStream to use the tokio::io traits instead, do you see any problem ?

Let's keep it out this PR but tokio::io makes sense to me since this crate it's tightly-coupled to tokio nowdays.
This is probably old code when this was supposed to support both tokio and async-std.

//cc @lexnv @jsdw

Copy link
Contributor Author

@oleonardolima oleonardolima Nov 20, 2023

Choose a reason for hiding this comment

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

Ok, I can give it a try on another PR as well, as tokio "native" support will help me with changes on the fedimint side

Copy link
Collaborator

Choose a reason for hiding this comment

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

Agreed that moving to tokio::io traits probably makes sense and might simplify some stuff given that we are "all in" on tokio in this lib nowadays

Copy link
Collaborator

Choose a reason for hiding this comment

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

Also I wonder why this is an enum and not struct?

Copy link
Member

Choose a reason for hiding this comment

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

yeah, would be cleaner with a struct to avoid matching on it :P

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great, thanks for the suggestion and @niklasad1 for addressing the changes

Copy link
Member

@niklasad1 niklasad1 left a comment

Choose a reason for hiding this comment

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

Nice, looks good

Run cargo fmt --all to make the CI happy.

@oleonardolima oleonardolima force-pushed the refactor/update-ws-client-transport-to-generic-over-stream branch 2 times, most recently from 9bfd89f to e44f993 Compare November 20, 2023 18:18
@niklasad1 niklasad1 marked this pull request as ready for review November 20, 2023 18:33
@niklasad1 niklasad1 requested a review from a team as a code owner November 20, 2023 18:33
Copy link
Member

@niklasad1 niklasad1 left a comment

Choose a reason for hiding this comment

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

Looks good to me, nice work

Can you please run cargo clippy and fix the warnings?

…entBuilder` generic

- fix(docs): typo on `WsTransportClientBuilder` doc on `Receiver`
  reference.
- refactor: add initial fn signatures for `build_with_stream`,
  `try_connect_over_tcp`, and `try_connect`.
- refactor: expose `EitherStream` visibility to public.
- refactor: make `Sender` and `Receiver` generic over T, a data stream.
- refactor: make `TransportSenderT` and `TransportReceiverT`
  implementations over generic `Sender` and `Receiver`, bound to
`AsyncRead`, `AsyncRead`, `MaybeSend` and `'static`.
- refactor: turn old `try_connect` TCP steps into
  `try_connect_over_tcp`.
- feat: implement `build_with_stream` and `try_connect` to handle and
  handle the handshake for a generic data stream `T`.
- feat: add new `Redirected` error variant to `WsHandshakeError`, as it
  should be handled by the client when using a generic data stream `T`.
- TODO(@oleonardolima): Add new tests that uses a different data stream.
- feat: add new `WsClientBuilder::build_with_transport` that builds and
  returns a `WsClient` with the given `Sender` and `Receiver`.
- feat: add new `WsClientBuilder::build_with_stream` that uses the new
  `WsTransportClientBuilder::build_with_stream`, building and returning
  the `WsClient` with the given `data_stream` as transport layer.
- refactor: update the `WsClientBuilder::build` to use the new
  `build_with_transport`, it helps not having duplicated code.
- add new helper fns to spawn a socks5 server, using `fast-socks5`
- add new helper enum for `DataStream` that acts as a wrapper to
  `Socks5Stream<T>`, similar to what a client would need to do.
- impl AsyncRead + AsyncWrite for the helper `DataStream` enum, to make
  it compatible between futures::io and tokio::io.
- add new tests that connects over a socks5 proxy, and use the new
  `WsClientBuilder::default()::build_with_stream(...) fn.
@oleonardolima oleonardolima force-pushed the refactor/update-ws-client-transport-to-generic-over-stream branch from e44f993 to 53641d1 Compare November 20, 2023 18:49
@oleonardolima
Copy link
Contributor Author

Looks good to me, nice work

Can you please run cargo clippy and fix the warnings?

Sure, CI is all good now 🚀

@niklasad1 niklasad1 requested a review from a team November 21, 2023 09:57
}
};
}
}
err.unwrap_or(Err(WsHandshakeError::NoAddressFound(target.host)))
}

/// Try to establish the connection over the given data stream.
pub async fn build_with_stream<T>(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: I'd move this fn to be right underneath build

@@ -249,3 +254,112 @@ pub async fn pipe_from_stream_and_drop<T: Serialize>(
}
}
}

#[allow(dead_code)]
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd have to compile this to check but I wonder why all the #[allow(dead_code)]s are needed!

Copy link
Member

Choose a reason for hiding this comment

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

I don't remember but probably that is just used for tests are not exported outside the crate.

Maybe pub(crate) would do it...

Copy link
Collaborator

Choose a reason for hiding this comment

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

If they are only used for tests then having the helpers be behind #[cfg(test)] would also remove such a warning :)

Copy link
Member

Choose a reason for hiding this comment

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

we don't have a lib.rs in the crate it's like https://github.com/paritytech/jsonrpsee/tree/master/tests/tests but every file should #![cfg(test)] so I don't know ^^

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry about that, totally missed it

tests/tests/helpers.rs Outdated Show resolved Hide resolved
Comment on lines +161 to +172
let mut success = false;

// Wait until a slot is available, as only one concurrent call is allowed.
// Then when this finishes we know that unsubscribe call has been finished.
for _ in 0..30 {
let res: Result<String, _> = client.request("say_hello", rpc_params![]).await;
if res.is_ok() {
success = true;
break;
}
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

So this is all just here to check that unsubscribe has finished; I wonder whether there is a simpler/cleaner way to do this (@niklasad1)

Copy link
Member

@niklasad1 niklasad1 Nov 21, 2023

Choose a reason for hiding this comment

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

yeah but I realized that the subscription doesn't keep the request id guard so this doesn't work as intended.

let's remove the extra ugliness for this test when this PR is merged...

Copy link
Collaborator

@jsdw jsdw left a comment

Choose a reason for hiding this comment

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

Looks like a nice addition to me; thank you! Just some nits but nothing super important

@niklasad1 niklasad1 merged commit 08292b0 into paritytech:master Nov 21, 2023
10 checks passed
@oleonardolima oleonardolima deleted the refactor/update-ws-client-transport-to-generic-over-stream branch January 20, 2024 17:27
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.

refactor(ws-client+ws-transport): make WsTransportClientBuilder generic over a data stream
3 participants