From b1e57e2a305f0f4f8650c73e01b8851e75384c9c Mon Sep 17 00:00:00 2001 From: Michael Vines Date: Tue, 15 Jan 2019 12:54:48 -0800 Subject: [PATCH] Retry rpc requests on connection failures Applied a blanket default retry count of 5, which seems like enough but not excessive retries. --- src/rpc_mock.rs | 18 ++++++++++++++---- wallet/src/wallet.rs | 25 +++++++++++++------------ 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/rpc_mock.rs b/src/rpc_mock.rs index 5d6404f885..c92723ab0f 100644 --- a/src/rpc_mock.rs +++ b/src/rpc_mock.rs @@ -24,14 +24,13 @@ impl MockRpcClient { pub fn new(addr: String) -> Self { MockRpcClient { addr } } -} -impl RpcRequestHandler for MockRpcClient { - fn make_rpc_request( + pub fn retry_make_rpc_request( &self, _id: u64, - request: RpcRequest, + request: &RpcRequest, params: Option, + mut _retries: usize, ) -> Result> { if self.addr == "fails" { 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, + ) -> Result> { + self.retry_make_rpc_request(id, &request, params, 0) + } +} + pub fn request_airdrop_transaction( _drone_addr: &SocketAddr, _id: &Pubkey, diff --git a/wallet/src/wallet.rs b/wallet/src/wallet.rs index 7801a41719..2e91afcba9 100644 --- a/wallet/src/wallet.rs +++ b/wallet/src/wallet.rs @@ -9,7 +9,7 @@ use solana::rpc::{RpcSignatureStatus, RPC_PORT}; use solana::rpc_mock::{request_airdrop_transaction, MockRpcClient as RpcClient}; #[cfg(not(test))] 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; #[cfg(not(test))] use solana_drone::drone::request_airdrop_transaction; @@ -342,7 +342,7 @@ pub fn process_command(config: &WalletConfig) -> Result tokens, @@ -356,7 +356,7 @@ pub fn process_command(config: &WalletConfig) -> Result Result { let params = json!([format!("{}", config.id.pubkey())]); let balance = rpc_client - .make_rpc_request(1, RpcRequest::GetBalance, Some(params))? + .retry_make_rpc_request(1, &RpcRequest::GetBalance, Some(params), 5)? .as_u64(); match balance { 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 { let params = json!([format!("{}", signature)]); let confirmation = rpc_client - .make_rpc_request(1, RpcRequest::ConfirmTransaction, Some(params))? + .retry_make_rpc_request(1, &RpcRequest::ConfirmTransaction, Some(params), 5)? .as_bool(); match confirmation { Some(b) => { @@ -410,7 +410,7 @@ pub fn process_command(config: &WalletConfig) -> Result { let params = json!([format!("{}", config.id.pubkey())]); let balance = rpc_client - .make_rpc_request(1, RpcRequest::GetBalance, Some(params))? + .retry_make_rpc_request(1, &RpcRequest::GetBalance, Some(params), 5)? .as_u64(); if let Some(tokens) = balance { if tokens < 1 { @@ -484,7 +484,7 @@ pub fn process_command(config: &WalletConfig) -> Result { let transaction_count = rpc_client - .make_rpc_request(1, RpcRequest::GetTransactionCount, None)? + .retry_make_rpc_request(1, &RpcRequest::GetTransactionCount, None, 5)? .as_u64(); match transaction_count { Some(count) => Ok(count.to_string()), @@ -618,7 +618,7 @@ pub fn process_command(config: &WalletConfig) -> Result { let params = json!([format!("{}", config.id.pubkey())]); let balance = rpc_client - .make_rpc_request(1, RpcRequest::GetBalance, Some(params))? + .retry_make_rpc_request(1, &RpcRequest::GetBalance, Some(params), 5)? .as_u64(); if let Some(0) = balance { @@ -637,7 +637,7 @@ pub fn process_command(config: &WalletConfig) -> Result { let params = json!([format!("{}", config.id.pubkey())]); let balance = rpc_client - .make_rpc_request(1, RpcRequest::GetBalance, Some(params))? + .retry_make_rpc_request(1, &RpcRequest::GetBalance, Some(params), 5)? .as_u64(); if let Some(0) = balance { @@ -655,7 +655,7 @@ pub fn process_command(config: &WalletConfig) -> Result Result> { - 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() { Err(WalletError::RpcRequestError( "Received bad last_id".to_string(), @@ -671,7 +671,8 @@ fn get_last_id(rpc_client: &RpcClient) -> Result> { fn send_tx(rpc_client: &RpcClient, tx: &Transaction) -> Result> { let serialized = serialize(tx).unwrap(); 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() { Err(WalletError::RpcRequestError( "Received result of an unexpected type".to_string(), @@ -686,7 +687,7 @@ fn confirm_tx( ) -> Result> { let params = json!([signature.to_string()]); 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() { let rpc_status = RpcSignatureStatus::from_str(status).map_err(|_| { WalletError::RpcRequestError("Unable to parse signature status".to_string())