-
Notifications
You must be signed in to change notification settings - Fork 127
Closed
Labels
F2-bugSomething isn't workingSomething isn't workingF9-dependenciesPull requests that update a dependency filePull requests that update a dependency fileQ3-substantial
Description
While trying to update the jsonrpsee client to a newer version (#671), the client (most likely) deadlocked itself after 59 requests (see https://github.com/scs/substrate-api-client/actions/runs/7126321622/job/19404332411). This is because we are using future::executor::block_on within tokio runtime to make async code synchronous. More info: paritytech/jsonrpsee#1259
To ensure this deadlock does not happen, I currently see two options:
- Replace futures with a tokio block.
Example replacement:
Old code:
impl Request for JsonrpseeClient {
fn request<R: DeserializeOwned>(&self, method: &str, params: RpcParams) -> Result<R> {
block_on(self.inner.request(method, RpcParamsWrapper(params)))
.map_err(|e| Error::Client(Box::new(e)))
}
}New code (didn't find a better way yet, should be improved):
impl Request for JsonrpseeClient {
fn request<R: DeserializeOwned>(&self, method: &str, params: RpcParams) -> Result<R> {
// Catch the current runtime.
let handle = match Handle::try_current() {
Ok(handle) => handle,
Err(_) => {
// We are not inside a tokio runtime, so lets start one.
let rt =
tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap();
rt.handle().clone()
},
};
let client = self.inner.clone();
let method_string = method.to_string();
// The inner jsonrpsee client must not deserialize to the `R` value, because the return value must
// implement `Send`. But we do not want to enforce the `R` value to implement this solely because we need
// to de-async something. Therefore, the deserialization must happen outside of the newly spawned thread.
// We need to spawn a new thread because tokio does not allow the blocking of the main thread:
// ERROR: Cannot block the current thread from within a runtime.
// This happens because a function attempted to block the current thread while the thread is being used to drive asynchronous tasks.
let string_answer: Value = std::thread::spawn(move || {
handle.block_on(client.request(&method_string, RpcParamsWrapper(params)))
})
.join()
.unwrap()
.map_err(|e| Error::Client(Box::new(e)))?;
let deserialized_value: R = serde_json::from_value(string_answer)?;
Ok(deserialized_value)
}
}- Open PR on jsonrpsee providing sync api
Metadata
Metadata
Assignees
Labels
F2-bugSomething isn't workingSomething isn't workingF9-dependenciesPull requests that update a dependency filePull requests that update a dependency fileQ3-substantial