diff --git a/Cargo.lock b/Cargo.lock index 5768c237..115ea447 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7219,7 +7219,7 @@ dependencies = [ [[package]] name = "web3_proxy" -version = "1.42.0" +version = "1.42.1" dependencies = [ "anyhow", "arc-swap", diff --git a/web3_proxy/Cargo.toml b/web3_proxy/Cargo.toml index 720f82df..06c91f55 100644 --- a/web3_proxy/Cargo.toml +++ b/web3_proxy/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "web3_proxy" -version = "1.42.0" +version = "1.42.1" edition = "2021" default-run = "web3_proxy_cli" diff --git a/web3_proxy/src/app/mod.rs b/web3_proxy/src/app/mod.rs index f826dbb1..ffc38a0b 100644 --- a/web3_proxy/src/app/mod.rs +++ b/web3_proxy/src/app/mod.rs @@ -1731,10 +1731,16 @@ impl Web3ProxyApp { // return all the errors now. moka will not cache Err results Err(err) } else { + // convert jsonrpc errors into JsonRpcResponseEnum, but leave the rest as errors let response_data: JsonRpcResponseEnum> = response_data.try_into()?; - // TODO: response data should maybe be Arc>>, but that's more work - Ok(response_data) + if response_data.is_null() { + // don't ever cache "null" as a success. its too likely to be a problem + Err(Web3ProxyError::NullJsonRpcResult) + } else { + // TODO: response data should maybe be Arc>>, but that's more work + Ok(response_data) + } } }).await? } else { diff --git a/web3_proxy/src/errors.rs b/web3_proxy/src/errors.rs index 31533297..fa899fe0 100644 --- a/web3_proxy/src/errors.rs +++ b/web3_proxy/src/errors.rs @@ -124,6 +124,8 @@ pub enum Web3ProxyError { #[from(ignore)] NotImplemented(Cow<'static, str>), NoVolatileRedisDatabase, + /// make it easy to skip caching null results + NullJsonRpcResult, OriginRequired, #[error(ignore)] #[from(ignore)] @@ -759,6 +761,9 @@ impl Web3ProxyError { }, ) } + Self::NullJsonRpcResult => { + return (StatusCode::OK, JsonRpcResponseEnum::NullResult); + } Self::OriginRequired => { trace!("OriginRequired"); ( diff --git a/web3_proxy/src/jsonrpc.rs b/web3_proxy/src/jsonrpc.rs index aabe8c71..f7591f32 100644 --- a/web3_proxy/src/jsonrpc.rs +++ b/web3_proxy/src/jsonrpc.rs @@ -366,6 +366,10 @@ impl JsonRpcForwardedResponse { pub fn from_response_data(data: JsonRpcResponseEnum>, id: Box) -> Self { match data { + JsonRpcResponseEnum::NullResult => { + let x: Box = Default::default(); + Self::from_raw_response(x.into(), id) + } JsonRpcResponseEnum::Result { value, .. } => Self::from_raw_response(value, id), JsonRpcResponseEnum::RpcError { error_data: value, .. diff --git a/web3_proxy/src/response_cache.rs b/web3_proxy/src/response_cache.rs index 01459188..03409230 100644 --- a/web3_proxy/src/response_cache.rs +++ b/web3_proxy/src/response_cache.rs @@ -89,6 +89,7 @@ pub type JsonRpcResponseCache = Cache>>; /// TODO: we might need one that holds RawValue and one that holds serde_json::Value #[derive(Clone, Debug)] pub enum JsonRpcResponseEnum { + NullResult, Result { value: R, num_bytes: u32, @@ -103,12 +104,29 @@ pub enum JsonRpcResponseEnum { impl JsonRpcResponseEnum { pub fn num_bytes(&self) -> u32 { match self { + Self::NullResult => 1, Self::Result { num_bytes, .. } => *num_bytes, Self::RpcError { num_bytes, .. } => *num_bytes, } } } +impl JsonRpcResponseEnum> { + pub fn is_null(&self) -> bool { + matches!(self, Self::NullResult | Self::Result { value: None, .. }) + } +} + +impl JsonRpcResponseEnum> { + pub fn is_null(&self) -> bool { + match self { + Self::NullResult => true, + Self::Result { value, .. } => value.get() == "null", + _ => false, + } + } +} + impl From for JsonRpcResponseEnum> { fn from(value: serde_json::Value) -> Self { let value = RawValue::from_string(value.to_string()).unwrap();