Transition to ureq http client (#5777)
* Transition to ureq http client * Remove unwrap
This commit is contained in:
@ -15,12 +15,12 @@ jsonrpc-core = "13.1.0"
|
||||
log = "0.4.8"
|
||||
rand = "0.6.5"
|
||||
rayon = "1.2.0"
|
||||
reqwest = "0.9.20"
|
||||
serde = "1.0.99"
|
||||
serde_derive = "1.0.99"
|
||||
serde_json = "1.0.40"
|
||||
solana-netutil = { path = "../netutil", version = "0.19.0-pre0" }
|
||||
solana-sdk = { path = "../sdk", version = "0.19.0-pre0" }
|
||||
ureq = { version = "0.11.0", features = ["json"] }
|
||||
|
||||
[dev-dependencies]
|
||||
jsonrpc-core = "13.1.0"
|
||||
|
@ -5,10 +5,10 @@ use std::{fmt, io};
|
||||
#[derive(Debug)]
|
||||
pub enum ClientError {
|
||||
Io(io::Error),
|
||||
Reqwest(reqwest::Error),
|
||||
RpcError(rpc_request::RpcError),
|
||||
SerdeJson(serde_json::error::Error),
|
||||
TransactionError(TransactionError),
|
||||
Ureq(String),
|
||||
}
|
||||
|
||||
impl fmt::Display for ClientError {
|
||||
@ -25,9 +25,9 @@ impl From<io::Error> for ClientError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<reqwest::Error> for ClientError {
|
||||
fn from(err: reqwest::Error) -> ClientError {
|
||||
ClientError::Reqwest(err)
|
||||
impl From<&ureq::Error> for ClientError {
|
||||
fn from(err: &ureq::Error) -> ClientError {
|
||||
ClientError::Ureq(err.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,32 +2,34 @@ use crate::client_error::ClientError;
|
||||
use crate::generic_rpc_client_request::GenericRpcClientRequest;
|
||||
use crate::rpc_request::{RpcError, RpcRequest};
|
||||
use log::*;
|
||||
use reqwest;
|
||||
use reqwest::header::CONTENT_TYPE;
|
||||
use solana_sdk::timing::{DEFAULT_TICKS_PER_SECOND, DEFAULT_TICKS_PER_SLOT};
|
||||
use std::io::{Error as IoError, ErrorKind};
|
||||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
use ureq::Error;
|
||||
|
||||
pub struct RpcClientRequest {
|
||||
client: reqwest::Client,
|
||||
client: ureq::Agent,
|
||||
url: String,
|
||||
timeout: Option<Duration>,
|
||||
}
|
||||
|
||||
impl RpcClientRequest {
|
||||
pub fn new(url: String) -> Self {
|
||||
Self {
|
||||
client: reqwest::Client::new(),
|
||||
client: ureq::agent(),
|
||||
url,
|
||||
timeout: None,
|
||||
}
|
||||
}
|
||||
|
||||
// Timeout applies separately to each socket action: connect, read, write
|
||||
pub fn new_with_timeout(url: String, timeout: Duration) -> Self {
|
||||
let client = reqwest::Client::builder()
|
||||
.timeout(timeout)
|
||||
.build()
|
||||
.expect("build rpc client");
|
||||
|
||||
Self { client, url }
|
||||
Self {
|
||||
client: ureq::agent(),
|
||||
url,
|
||||
timeout: Some(timeout),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,38 +46,48 @@ impl GenericRpcClientRequest for RpcClientRequest {
|
||||
let request_json = request.build_request_json(request_id, params);
|
||||
|
||||
loop {
|
||||
match self
|
||||
let mut request_builder = self
|
||||
.client
|
||||
.post(&self.url)
|
||||
.header(CONTENT_TYPE, "application/json")
|
||||
.body(request_json.to_string())
|
||||
.send()
|
||||
{
|
||||
Ok(mut response) => {
|
||||
let json: serde_json::Value = serde_json::from_str(&response.text()?)?;
|
||||
if json["error"].is_object() {
|
||||
Err(RpcError::RpcRequestError(format!(
|
||||
"RPC Error response: {}",
|
||||
serde_json::to_string(&json["error"]).unwrap()
|
||||
)))?
|
||||
}
|
||||
return Ok(json["result"].clone());
|
||||
.set("Content-Type", "application/json")
|
||||
.build();
|
||||
if self.timeout.is_some() {
|
||||
request_builder = request_builder
|
||||
.timeout_connect(self.timeout.unwrap().as_millis() as u64)
|
||||
.timeout_read(self.timeout.unwrap().as_millis() as u64)
|
||||
.timeout_write(self.timeout.unwrap().as_millis() as u64)
|
||||
.build();
|
||||
}
|
||||
let response = request_builder.send_json(request_json.clone());
|
||||
if response.ok() {
|
||||
let json: serde_json::Value = response.into_json()?;
|
||||
if json["error"].is_object() {
|
||||
Err(RpcError::RpcRequestError(format!(
|
||||
"RPC Error response: {}",
|
||||
serde_json::to_string(&json["error"]).unwrap()
|
||||
)))?
|
||||
}
|
||||
Err(e) => {
|
||||
info!(
|
||||
"make_rpc_request({:?}) failed, {} retries left: {:?}",
|
||||
request, retries, e
|
||||
);
|
||||
if retries == 0 {
|
||||
Err(e)?;
|
||||
}
|
||||
retries -= 1;
|
||||
return Ok(json["result"].clone());
|
||||
} else {
|
||||
let io_error = Error::Io(IoError::new(ErrorKind::Other, "Unspecified error"));
|
||||
let error = if let Some(err) = response.synthetic_error().as_ref() {
|
||||
err
|
||||
} else {
|
||||
&io_error
|
||||
};
|
||||
info!(
|
||||
"make_rpc_request({:?}) failed, {} retries left: {:?}",
|
||||
request, retries, error
|
||||
);
|
||||
if retries == 0 {
|
||||
Err(error)?;
|
||||
}
|
||||
retries -= 1;
|
||||
|
||||
// Sleep for approximately half a slot
|
||||
sleep(Duration::from_millis(
|
||||
500 * DEFAULT_TICKS_PER_SLOT / DEFAULT_TICKS_PER_SECOND,
|
||||
));
|
||||
}
|
||||
// Sleep for approximately half a slot
|
||||
sleep(Duration::from_millis(
|
||||
500 * DEFAULT_TICKS_PER_SLOT / DEFAULT_TICKS_PER_SECOND,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user