From 3635ea4dceb04088e522a1933a5bf756a49e6254 Mon Sep 17 00:00:00 2001 From: Jonas Hahn Date: Wed, 13 Nov 2024 14:33:54 +0100 Subject: [PATCH] Add retries for RPC calls --- Cargo.lock | 2 +- src/main.rs | 50 ++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3b064e1..6eaf2f3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4019,7 +4019,7 @@ dependencies = [ [[package]] name = "solana-verify" -version = "0.2.14" +version = "0.3.0" dependencies = [ "anyhow", "borsh 1.5.0", diff --git a/src/main.rs b/src/main.rs index 320e7be..b577b11 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,6 +20,8 @@ use std::{ atomic::{AtomicBool, Ordering}, Arc, }, + thread::sleep, + time::Duration, }; use uuid::Uuid; pub mod api; @@ -37,6 +39,8 @@ use crate::{ }; const MAINNET_GENESIS_HASH: &str = "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d"; +const MAX_RETRIES: u32 = 5; +const INITIAL_RETRY_DELAY_MS: u64 = 500; pub fn get_network(network_str: &str) -> &str { match network_str { @@ -351,12 +355,38 @@ pub fn get_file_hash(filepath: &str) -> Result { Ok(get_binary_hash(buffer)) } +fn retry_rpc_call(mut rpc_call: F) -> anyhow::Result +where + F: FnMut() -> anyhow::Result, +{ + let mut attempts = 0; + let mut delay = INITIAL_RETRY_DELAY_MS; + + loop { + match rpc_call() { + Ok(result) => return Ok(result), + Err(err) if attempts < MAX_RETRIES => { + attempts += 1; + println!( + "RPC call failed (attempt {}/{}) - retrying in {} ms... Error: {}", + attempts, MAX_RETRIES, delay, err + ); + sleep(Duration::from_millis(delay)); + delay *= 2; // Exponential backoff + } + Err(err) => return Err(err), + } + } +} + pub fn get_buffer_hash(url: Option, buffer_address: Pubkey) -> anyhow::Result { let client = get_client(url); let offset = UpgradeableLoaderState::size_of_buffer_metadata(); - let account_data = client.get_account_data(&buffer_address)?[offset..].to_vec(); - let program_hash = get_binary_hash(account_data); - Ok(program_hash) + retry_rpc_call(|| { + let account_data = client.get_account_data(&buffer_address)?[offset..].to_vec(); + let program_hash = get_binary_hash(account_data); + Ok(program_hash) + }) } pub fn get_program_hash(url: Option, program_id: Pubkey) -> anyhow::Result { @@ -364,15 +394,19 @@ pub fn get_program_hash(url: Option, program_id: Pubkey) -> anyhow::Resu let program_buffer = Pubkey::find_program_address(&[program_id.as_ref()], &bpf_loader_upgradeable::id()).0; let offset = UpgradeableLoaderState::size_of_programdata_metadata(); - let account_data = client.get_account_data(&program_buffer)?[offset..].to_vec(); - let program_hash = get_binary_hash(account_data); - Ok(program_hash) + retry_rpc_call(|| { + let account_data = client.get_account_data(&program_buffer)?[offset..].to_vec(); + let program_hash = get_binary_hash(account_data); + Ok(program_hash) + }) } pub fn get_genesis_hash(url: Option) -> anyhow::Result { let client = get_client(url); - let genesis_hash = client.get_genesis_hash()?; - Ok(genesis_hash.to_string()) + retry_rpc_call(|| { + let genesis_hash = client.get_genesis_hash()?; + Ok(genesis_hash.to_string()) + }) } pub fn get_docker_resource_limits() -> Option<(String, String)> {