From 14acda1da4c5da51465058171c65b12238b563cf Mon Sep 17 00:00:00 2001 From: Deiadara Date: Fri, 12 Dec 2025 22:10:01 +0100 Subject: [PATCH 1/3] fix(redis): exponential backoff in get_cost_by_message_id --- src/redis.rs | 97 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 73 insertions(+), 24 deletions(-) diff --git a/src/redis.rs b/src/redis.rs index 24cb169..786c7e4 100644 --- a/src/redis.rs +++ b/src/redis.rs @@ -3,7 +3,9 @@ use relayer_core::utils::ThreadSafe; use serde::{Deserialize, Serialize}; use std::fmt::{Display, Formatter}; use std::sync::Arc; -use tracing::{debug, error}; +use std::time::Duration; +use tokio::time::sleep; +use tracing::{debug, error, warn}; #[derive(Clone)] pub struct CostCache { @@ -38,32 +40,79 @@ impl CostCacheTrait for CostCache { ) -> Result { let key = format!("cost:{}:{}", transaction_type, message_id); let mut conn = self.conn.clone(); - match conn.get::<_, Option>(&key).await { - Ok(Some(serialized)) => { - if let Ok(cost) = serialized.parse::() { - debug!("Cost for key {} is {}", key, cost); - return Ok(cost); - } else { - error!("Failed to parse cost for key {}: {}", key, serialized); - return Err(anyhow::anyhow!( - "Failed to parse cost for key {}: {}", - key, - serialized - )); + let max_retries = 5; + let mut backoff_duration = Duration::from_secs(1); + + for attempt in 0..max_retries { + match conn.get::<_, Option>(&key).await { + Ok(Some(serialized)) => { + if let Ok(cost) = serialized.parse::() { + debug!("Cost for key {} is {}", key, cost); + return Ok(cost); + } else { + error!("Failed to parse cost for key {}: {}", key, serialized); + return Err(anyhow::anyhow!( + "Failed to parse cost for key {}: {}", + key, + serialized + )); + } + } + Ok(None) => { + if attempt < max_retries - 1 { + debug!( + "Failed to get cost from Redis for key {} (attempt {}/{}): Key not found. Retrying in {:?}...", + key, + attempt + 1, + max_retries, + backoff_duration + ); + sleep(backoff_duration).await; + backoff_duration *= 2; + } else { + error!( + "Failed to get cost from Redis for key {} after {} attempts: Key not found in Redis", + key, max_retries + ); + return Err(anyhow::anyhow!( + "Failed to get cost for key {} after {} attempts: Key not found in Redis", + key, + max_retries + )); + } + } + Err(e) => { + if attempt < max_retries - 1 { + debug!( + "Failed to get cost from Redis for key {} (attempt {}/{}): {}. Retrying in {:?}...", + key, + attempt + 1, + max_retries, + e, + backoff_duration + ); + sleep(backoff_duration).await; + backoff_duration *= 2; + } else { + error!( + "Failed to get cost from Redis for key {} after {} attempts: {}", + key, max_retries, e + ); + return Err(anyhow::anyhow!( + "Failed to get cost for key {} after {} attempts: {}", + key, + max_retries, + e + )); + } } - } - Ok(None) => { - error!("Failed to get cost for key {}: Key not found in Redis", key); - return Err(anyhow::anyhow!( - "Failed to get cost for key {}: Key not found in Redis", - key - )); - } - Err(e) => { - error!("Failed to get context from Redis for key {}: {}", key, e); - return Err(anyhow::anyhow!("Failed to get cost for key {}: {}", key, e)); } } + + Err(anyhow::anyhow!( + "Failed to get cost for key {}: Max retries exceeded", + key + )) } } From 4e30c398d0bfc9630a64723e2ebf20fc22810a3e Mon Sep 17 00:00:00 2001 From: Deiadara Date: Fri, 12 Dec 2025 22:34:37 +0100 Subject: [PATCH 2/3] chore: fix clippy --- Cargo.lock | 36 ++++++++++++++++++------------------ src/redis.rs | 2 +- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6ce2f9f..db9fe1c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1536,7 +1536,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115e54d64eb62cdebad391c19efc9dce4981c690c85a33a12199d99bb9546fee" dependencies = [ "borsh-derive 0.10.4", - "hashbrown 0.13.2", + "hashbrown 0.12.3", ] [[package]] @@ -2697,7 +2697,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -3848,8 +3848,8 @@ dependencies = [ [[package]] name = "interchain-token-transfer-gmp" -version = "0.1.1" -source = "git+https://github.com/axelarnetwork/axelar-amplifier-solana?branch=main#b2900004c829118344156441d4f13322bb8d6d50" +version = "0.1.2" +source = "git+https://github.com/axelarnetwork/axelar-amplifier-solana?branch=main#8d4c3b82f9f1fc5ad7cb642fed0666058ce2e1fb" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -5255,8 +5255,8 @@ dependencies = [ [[package]] name = "program-utils" -version = "0.1.2" -source = "git+https://github.com/axelarnetwork/axelar-amplifier-solana?branch=main#b2900004c829118344156441d4f13322bb8d6d50" +version = "0.1.3" +source = "git+https://github.com/axelarnetwork/axelar-amplifier-solana?branch=main#8d4c3b82f9f1fc5ad7cb642fed0666058ce2e1fb" dependencies = [ "mpl-token-metadata", "solana-program", @@ -6093,7 +6093,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.11.0", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -6953,8 +6953,8 @@ dependencies = [ [[package]] name = "solana-axelar-gas-service" -version = "0.1.4" -source = "git+https://github.com/axelarnetwork/axelar-amplifier-solana?branch=main#b2900004c829118344156441d4f13322bb8d6d50" +version = "0.1.5" +source = "git+https://github.com/axelarnetwork/axelar-amplifier-solana?branch=main#8d4c3b82f9f1fc5ad7cb642fed0666058ce2e1fb" dependencies = [ "anchor-lang", "bytemuck", @@ -6964,8 +6964,8 @@ dependencies = [ [[package]] name = "solana-axelar-gateway" -version = "0.1.4" -source = "git+https://github.com/axelarnetwork/axelar-amplifier-solana?branch=main#b2900004c829118344156441d4f13322bb8d6d50" +version = "0.1.5" +source = "git+https://github.com/axelarnetwork/axelar-amplifier-solana?branch=main#8d4c3b82f9f1fc5ad7cb642fed0666058ce2e1fb" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -6981,8 +6981,8 @@ dependencies = [ [[package]] name = "solana-axelar-its" -version = "0.1.4" -source = "git+https://github.com/axelarnetwork/axelar-amplifier-solana?branch=main#b2900004c829118344156441d4f13322bb8d6d50" +version = "0.1.5" +source = "git+https://github.com/axelarnetwork/axelar-amplifier-solana?branch=main#8d4c3b82f9f1fc5ad7cb642fed0666058ce2e1fb" dependencies = [ "alloy-primitives", "anchor-lang", @@ -7000,8 +7000,8 @@ dependencies = [ [[package]] name = "solana-axelar-operators" -version = "0.1.4" -source = "git+https://github.com/axelarnetwork/axelar-amplifier-solana?branch=main#b2900004c829118344156441d4f13322bb8d6d50" +version = "0.1.5" +source = "git+https://github.com/axelarnetwork/axelar-amplifier-solana?branch=main#8d4c3b82f9f1fc5ad7cb642fed0666058ce2e1fb" dependencies = [ "anchor-lang", "program-utils", @@ -7009,8 +7009,8 @@ dependencies = [ [[package]] name = "solana-axelar-std" -version = "0.1.2" -source = "git+https://github.com/axelarnetwork/axelar-amplifier-solana?branch=main#b2900004c829118344156441d4f13322bb8d6d50" +version = "0.1.3" +source = "git+https://github.com/axelarnetwork/axelar-amplifier-solana?branch=main#8d4c3b82f9f1fc5ad7cb642fed0666058ce2e1fb" dependencies = [ "alloy-primitives", "anchor-lang", @@ -9670,7 +9670,7 @@ dependencies = [ "getrandom 0.3.3", "once_cell", "rustix 1.1.2", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] diff --git a/src/redis.rs b/src/redis.rs index 786c7e4..b3b653c 100644 --- a/src/redis.rs +++ b/src/redis.rs @@ -5,7 +5,7 @@ use std::fmt::{Display, Formatter}; use std::sync::Arc; use std::time::Duration; use tokio::time::sleep; -use tracing::{debug, error, warn}; +use tracing::{debug, error}; #[derive(Clone)] pub struct CostCache { From 2cc490924a493997fa251853c171d736bef9162c Mon Sep 17 00:00:00 2001 From: Deiadara Date: Sat, 13 Dec 2025 00:02:51 +0100 Subject: [PATCH 3/3] chore: dry --- src/redis.rs | 29 ++--------------------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/src/redis.rs b/src/redis.rs index b3b653c..98d0494 100644 --- a/src/redis.rs +++ b/src/redis.rs @@ -41,7 +41,7 @@ impl CostCacheTrait for CostCache { let key = format!("cost:{}:{}", transaction_type, message_id); let mut conn = self.conn.clone(); let max_retries = 5; - let mut backoff_duration = Duration::from_secs(1); + let mut backoff_duration = Duration::from_millis(500); for attempt in 0..max_retries { match conn.get::<_, Option>(&key).await { @@ -58,7 +58,7 @@ impl CostCacheTrait for CostCache { )); } } - Ok(None) => { + _ => { if attempt < max_retries - 1 { debug!( "Failed to get cost from Redis for key {} (attempt {}/{}): Key not found. Retrying in {:?}...", @@ -81,31 +81,6 @@ impl CostCacheTrait for CostCache { )); } } - Err(e) => { - if attempt < max_retries - 1 { - debug!( - "Failed to get cost from Redis for key {} (attempt {}/{}): {}. Retrying in {:?}...", - key, - attempt + 1, - max_retries, - e, - backoff_duration - ); - sleep(backoff_duration).await; - backoff_duration *= 2; - } else { - error!( - "Failed to get cost from Redis for key {} after {} attempts: {}", - key, max_retries, e - ); - return Err(anyhow::anyhow!( - "Failed to get cost for key {} after {} attempts: {}", - key, - max_retries, - e - )); - } - } } }