paritytech / jsonrpsee

Rust JSON-RPC library on top of async/await
MIT License
645 stars 172 forks source link

Multiple client traits indiscriminately mix into ClientBuilder #1460

Closed AArnott closed 1 month ago

AArnott commented 2 months ago

In a module that defines two client RPC contracts, the ClientBuilder constructs a Client value that has methods from both traits.

#[rpc(client)]
trait Calculator {
    #[method(name = "add")]
    fn add(&self, a: u64, b: u64) -> Result<u64, ErrorObject>;
}

#[rpc(client)]
trait ScientificCalculator {
    #[method(name = "multiply")]
    fn multiply(&self, a: u64, b: u64) -> Result<u64, ErrorObject>;
}

Given the code above, the code below compiles:

let client = ClientBuilder::default().build_with_tokio(w, r);
let sum = client.add(3, 5).await.unwrap();
println!("{}", sum);
let product = client.multiply(3, 5).await.unwrap();
println!("{}", product);

But it fails at runtime because the connection is with a server that only implements one of the traits.

In my scenarios, the code bases very often communicate with a variety of services, all offering different contracts. It's important to get a client whose offered functions match the right trait(s) rather than be a mix of all of them.

Is this supported somehow?

AArnott commented 2 months ago

It looks like I can control this by managing the use directive in this file or scoped to where I make the client calls to only include those traits that I expect to work for a given service. This is workable, though it would make it rather inconvenient if, say, I had a function in which I called into multiple services. I guess I would have to use the more verbose trait-function syntax.

Probably something to at least document as a technique folks can use.

niklasad1 commented 1 month ago

These are just regular rust traits and it's nothing that jsonrpsee can do about if several traits are brought into scope via either use or defining the traits and used within the same module.

It's just regular rust knowledge that you can use explicitly specifying the trait you want use such CalculatorClient::add(&client, 100, 100) and additionally if you have conflicting names between different traits it will end in a compile error in Rust.

We could perhaps write some book/tutorial or other docs but nothing else to address... so closing this