Retry rpc requests on connection failures

Applied a blanket default retry count of 5, which seems like enough but
not excessive retries.
This commit is contained in:
Michael Vines
2019-01-15 12:54:48 -08:00
parent 4d9489aeb1
commit b1e57e2a30
2 changed files with 27 additions and 16 deletions

View File

@@ -24,14 +24,13 @@ impl MockRpcClient {
pub fn new(addr: String) -> Self { pub fn new(addr: String) -> Self {
MockRpcClient { addr } MockRpcClient { addr }
} }
}
impl RpcRequestHandler for MockRpcClient { pub fn retry_make_rpc_request(
fn make_rpc_request(
&self, &self,
_id: u64, _id: u64,
request: RpcRequest, request: &RpcRequest,
params: Option<Value>, params: Option<Value>,
mut _retries: usize,
) -> Result<Value, Box<dyn error::Error>> { ) -> Result<Value, Box<dyn error::Error>> {
if self.addr == "fails" { if self.addr == "fails" {
return Ok(Value::Null); return Ok(Value::Null);
@@ -71,6 +70,17 @@ impl RpcRequestHandler for MockRpcClient {
} }
} }
impl RpcRequestHandler for MockRpcClient {
fn make_rpc_request(
&self,
id: u64,
request: RpcRequest,
params: Option<Value>,
) -> Result<Value, Box<dyn error::Error>> {
self.retry_make_rpc_request(id, &request, params, 0)
}
}
pub fn request_airdrop_transaction( pub fn request_airdrop_transaction(
_drone_addr: &SocketAddr, _drone_addr: &SocketAddr,
_id: &Pubkey, _id: &Pubkey,

View File

@@ -9,7 +9,7 @@ use solana::rpc::{RpcSignatureStatus, RPC_PORT};
use solana::rpc_mock::{request_airdrop_transaction, MockRpcClient as RpcClient}; use solana::rpc_mock::{request_airdrop_transaction, MockRpcClient as RpcClient};
#[cfg(not(test))] #[cfg(not(test))]
use solana::rpc_request::RpcClient; use solana::rpc_request::RpcClient;
use solana::rpc_request::{get_rpc_request_str, RpcRequest, RpcRequestHandler}; use solana::rpc_request::{get_rpc_request_str, RpcRequest};
use solana::socketaddr; use solana::socketaddr;
#[cfg(not(test))] #[cfg(not(test))]
use solana_drone::drone::request_airdrop_transaction; use solana_drone::drone::request_airdrop_transaction;
@@ -342,7 +342,7 @@ pub fn process_command(config: &WalletConfig) -> Result<String, Box<dyn error::E
); );
let params = json!([format!("{}", config.id.pubkey())]); let params = json!([format!("{}", config.id.pubkey())]);
let previous_balance = match rpc_client let previous_balance = match rpc_client
.make_rpc_request(1, RpcRequest::GetBalance, Some(params))? .retry_make_rpc_request(1, &RpcRequest::GetBalance, Some(params), 5)?
.as_u64() .as_u64()
{ {
Some(tokens) => tokens, Some(tokens) => tokens,
@@ -356,7 +356,7 @@ pub fn process_command(config: &WalletConfig) -> Result<String, Box<dyn error::E
let params = json!([format!("{}", config.id.pubkey())]); let params = json!([format!("{}", config.id.pubkey())]);
let current_balance = rpc_client let current_balance = rpc_client
.make_rpc_request(1, RpcRequest::GetBalance, Some(params))? .retry_make_rpc_request(1, &RpcRequest::GetBalance, Some(params), 5)?
.as_u64() .as_u64()
.unwrap_or(previous_balance); .unwrap_or(previous_balance);
@@ -369,7 +369,7 @@ pub fn process_command(config: &WalletConfig) -> Result<String, Box<dyn error::E
WalletCommand::Balance => { WalletCommand::Balance => {
let params = json!([format!("{}", config.id.pubkey())]); let params = json!([format!("{}", config.id.pubkey())]);
let balance = rpc_client let balance = rpc_client
.make_rpc_request(1, RpcRequest::GetBalance, Some(params))? .retry_make_rpc_request(1, &RpcRequest::GetBalance, Some(params), 5)?
.as_u64(); .as_u64();
match balance { match balance {
Some(0) => Ok("No account found! Request an airdrop to get started.".to_string()), Some(0) => Ok("No account found! Request an airdrop to get started.".to_string()),
@@ -391,7 +391,7 @@ pub fn process_command(config: &WalletConfig) -> Result<String, Box<dyn error::E
WalletCommand::Confirm(signature) => { WalletCommand::Confirm(signature) => {
let params = json!([format!("{}", signature)]); let params = json!([format!("{}", signature)]);
let confirmation = rpc_client let confirmation = rpc_client
.make_rpc_request(1, RpcRequest::ConfirmTransaction, Some(params))? .retry_make_rpc_request(1, &RpcRequest::ConfirmTransaction, Some(params), 5)?
.as_bool(); .as_bool();
match confirmation { match confirmation {
Some(b) => { Some(b) => {
@@ -410,7 +410,7 @@ pub fn process_command(config: &WalletConfig) -> Result<String, Box<dyn error::E
WalletCommand::Deploy(ref program_location) => { WalletCommand::Deploy(ref program_location) => {
let params = json!([format!("{}", config.id.pubkey())]); let params = json!([format!("{}", config.id.pubkey())]);
let balance = rpc_client let balance = rpc_client
.make_rpc_request(1, RpcRequest::GetBalance, Some(params))? .retry_make_rpc_request(1, &RpcRequest::GetBalance, Some(params), 5)?
.as_u64(); .as_u64();
if let Some(tokens) = balance { if let Some(tokens) = balance {
if tokens < 1 { if tokens < 1 {
@@ -484,7 +484,7 @@ pub fn process_command(config: &WalletConfig) -> Result<String, Box<dyn error::E
} }
WalletCommand::GetTransactionCount => { WalletCommand::GetTransactionCount => {
let transaction_count = rpc_client let transaction_count = rpc_client
.make_rpc_request(1, RpcRequest::GetTransactionCount, None)? .retry_make_rpc_request(1, &RpcRequest::GetTransactionCount, None, 5)?
.as_u64(); .as_u64();
match transaction_count { match transaction_count {
Some(count) => Ok(count.to_string()), Some(count) => Ok(count.to_string()),
@@ -618,7 +618,7 @@ pub fn process_command(config: &WalletConfig) -> Result<String, Box<dyn error::E
WalletCommand::TimeElapsed(to, pubkey, dt) => { WalletCommand::TimeElapsed(to, pubkey, dt) => {
let params = json!([format!("{}", config.id.pubkey())]); let params = json!([format!("{}", config.id.pubkey())]);
let balance = rpc_client let balance = rpc_client
.make_rpc_request(1, RpcRequest::GetBalance, Some(params))? .retry_make_rpc_request(1, &RpcRequest::GetBalance, Some(params), 5)?
.as_u64(); .as_u64();
if let Some(0) = balance { if let Some(0) = balance {
@@ -637,7 +637,7 @@ pub fn process_command(config: &WalletConfig) -> Result<String, Box<dyn error::E
WalletCommand::Witness(to, pubkey) => { WalletCommand::Witness(to, pubkey) => {
let params = json!([format!("{}", config.id.pubkey())]); let params = json!([format!("{}", config.id.pubkey())]);
let balance = rpc_client let balance = rpc_client
.make_rpc_request(1, RpcRequest::GetBalance, Some(params))? .retry_make_rpc_request(1, &RpcRequest::GetBalance, Some(params), 5)?
.as_u64(); .as_u64();
if let Some(0) = balance { if let Some(0) = balance {
@@ -655,7 +655,7 @@ pub fn process_command(config: &WalletConfig) -> Result<String, Box<dyn error::E
} }
fn get_last_id(rpc_client: &RpcClient) -> Result<Hash, Box<dyn error::Error>> { fn get_last_id(rpc_client: &RpcClient) -> Result<Hash, Box<dyn error::Error>> {
let result = rpc_client.make_rpc_request(1, RpcRequest::GetLastId, None)?; let result = rpc_client.retry_make_rpc_request(1, &RpcRequest::GetLastId, None, 5)?;
if result.as_str().is_none() { if result.as_str().is_none() {
Err(WalletError::RpcRequestError( Err(WalletError::RpcRequestError(
"Received bad last_id".to_string(), "Received bad last_id".to_string(),
@@ -671,7 +671,8 @@ fn get_last_id(rpc_client: &RpcClient) -> Result<Hash, Box<dyn error::Error>> {
fn send_tx(rpc_client: &RpcClient, tx: &Transaction) -> Result<String, Box<dyn error::Error>> { fn send_tx(rpc_client: &RpcClient, tx: &Transaction) -> Result<String, Box<dyn error::Error>> {
let serialized = serialize(tx).unwrap(); let serialized = serialize(tx).unwrap();
let params = json!([serialized]); let params = json!([serialized]);
let signature = rpc_client.make_rpc_request(2, RpcRequest::SendTransaction, Some(params))?; let signature =
rpc_client.retry_make_rpc_request(2, &RpcRequest::SendTransaction, Some(params), 5)?;
if signature.as_str().is_none() { if signature.as_str().is_none() {
Err(WalletError::RpcRequestError( Err(WalletError::RpcRequestError(
"Received result of an unexpected type".to_string(), "Received result of an unexpected type".to_string(),
@@ -686,7 +687,7 @@ fn confirm_tx(
) -> Result<RpcSignatureStatus, Box<dyn error::Error>> { ) -> Result<RpcSignatureStatus, Box<dyn error::Error>> {
let params = json!([signature.to_string()]); let params = json!([signature.to_string()]);
let signature_status = let signature_status =
rpc_client.make_rpc_request(1, RpcRequest::GetSignatureStatus, Some(params))?; rpc_client.retry_make_rpc_request(1, &RpcRequest::GetSignatureStatus, Some(params), 5)?;
if let Some(status) = signature_status.as_str() { if let Some(status) = signature_status.as_str() {
let rpc_status = RpcSignatureStatus::from_str(status).map_err(|_| { let rpc_status = RpcSignatureStatus::from_str(status).map_err(|_| {
WalletError::RpcRequestError("Unable to parse signature status".to_string()) WalletError::RpcRequestError("Unable to parse signature status".to_string())