diff --git a/web3-proxy/src/connections.rs b/web3-proxy/src/connections.rs index 35b320c6..d13a2a1f 100644 --- a/web3-proxy/src/connections.rs +++ b/web3-proxy/src/connections.rs @@ -469,17 +469,32 @@ impl Web3Connections { .request(&request.method, &request.params) .await; - let response = - JsonRpcForwardedResponse::from_response_result(response_result, request.id); + match JsonRpcForwardedResponse::from_response_result( + response_result, + request.id.clone(), + ) { + Ok(response) => { + if response.error.is_some() { + trace!(?response, "Sending error reply",); + // errors already sent false to the in_flight_tx + } else { + trace!(?response, "Sending reply"); + } - if response.error.is_some() { - trace!(?response, "Sending error reply",); - // errors already sent false to the in_flight_tx - } else { - trace!(?response, "Sending reply"); + return Ok(response); + } + Err(e) => { + warn!(?self, ?e, "Backend server error!"); + + // TODO: sleep how long? until synced_connections changes or rate limits are available + sleep(Duration::from_millis(100)).await; + + // TODO: when we retry, depending on the error, skip using this same server + // for example, if rpc isn't available on this server, retrying is bad + // but if an http error, retrying on same is probably fine + continue; + } } - - return Ok(response); } Err(None) => { warn!(?self, "No servers in sync!"); diff --git a/web3-proxy/src/jsonrpc.rs b/web3-proxy/src/jsonrpc.rs index b3881106..f3809c1b 100644 --- a/web3-proxy/src/jsonrpc.rs +++ b/web3-proxy/src/jsonrpc.rs @@ -184,9 +184,9 @@ impl JsonRpcForwardedResponse { pub fn from_response_result( result: Result, ProviderError>, id: Box, - ) -> Self { + ) -> anyhow::Result { match result { - Ok(response) => Self::from_response(response, id), + Ok(response) => Ok(Self::from_response(response, id)), Err(e) => Self::from_ethers_error(e, id), } } @@ -208,7 +208,7 @@ impl JsonRpcForwardedResponse { } } - pub fn from_ethers_error(e: ProviderError, id: Box) -> Self { + pub fn from_ethers_error(e: ProviderError, id: Box) -> anyhow::Result { // TODO: move turning ClientError into json to a helper function? let code; let message: String; @@ -216,47 +216,46 @@ impl JsonRpcForwardedResponse { match e { ProviderError::JsonRpcClientError(e) => { - // TODO: we should check what type the provider is rather than trying to downcast both types of errors - if let Some(e) = e.downcast_ref::() { - match &*e { + // TODO: check what type the provider is rather than trying to downcast both types of errors + let e = e.downcast::(); + + if let Ok(e) = e { + match *e { HttpClientError::JsonRpcError(e) => { code = e.code; message = e.message.clone(); - data = e.data.clone(); + data = e.data; } e => { - // TODO: improve this - code = -32603; - message = format!("{}", e); - data = None; - } - } - } else if let Some(e) = e.downcast_ref::() { - match &*e { - WsClientError::JsonRpcError(e) => { - code = e.code; - message = e.message.clone(); - data = e.data.clone(); - } - e => { - // TODO: improve this - code = -32603; - message = format!("{}", e); - data = None; + // this is not an rpc error. keep it as an error + return Err(e.into()); } } } else { - unimplemented!(); + // it wasn't an HttpClientError. try WsClientError + let e = e.unwrap_err().downcast::(); + + if let Ok(e) = e { + match *e { + WsClientError::JsonRpcError(e) => { + code = e.code; + message = e.message.clone(); + data = e.data; + } + e => { + // this is not an rpc error. keep it as an error + return Err(e.into()); + } + } + } else { + unimplemented!(); + } } } - _ => { - code = -32603; - message = format!("{}", e); - data = None; - } + e => return Err(e.into()), } - Self { + Ok(Self { jsonrpc: "2.0".to_string(), id, result: None, @@ -265,7 +264,7 @@ impl JsonRpcForwardedResponse { message, data, }), - } + }) } }