dont cache responses larger than 2MB
This commit is contained in:
parent
79542c94ae
commit
d25884dfbb
@ -1161,6 +1161,8 @@ impl Web3ProxyApp {
|
|||||||
|
|
||||||
// TODO: trace/kafka log request.params before we send them to _proxy_request_with_caching which might modify them
|
// TODO: trace/kafka log request.params before we send them to _proxy_request_with_caching which might modify them
|
||||||
|
|
||||||
|
// turn some of the Web3ProxyErrors into Ok results
|
||||||
|
// TODO: move this into a helper function
|
||||||
let (code, response_data) = match self
|
let (code, response_data) = match self
|
||||||
._proxy_request_with_caching(
|
._proxy_request_with_caching(
|
||||||
&request.method,
|
&request.method,
|
||||||
@ -1178,6 +1180,20 @@ impl Web3ProxyApp {
|
|||||||
|
|
||||||
(StatusCode::OK, response_data)
|
(StatusCode::OK, response_data)
|
||||||
}
|
}
|
||||||
|
Err(err @ Web3ProxyError::NullJsonRpcResult) => {
|
||||||
|
request_metadata
|
||||||
|
.error_response
|
||||||
|
.store(false, Ordering::Release);
|
||||||
|
|
||||||
|
err.as_response_parts()
|
||||||
|
}
|
||||||
|
Err(Web3ProxyError::JsonRpcResponse(response_data)) => {
|
||||||
|
request_metadata
|
||||||
|
.error_response
|
||||||
|
.store(response_data.is_error(), Ordering::Release);
|
||||||
|
|
||||||
|
(StatusCode::OK, response_data)
|
||||||
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
request_metadata
|
request_metadata
|
||||||
.error_response
|
.error_response
|
||||||
@ -1706,11 +1722,15 @@ impl Web3ProxyApp {
|
|||||||
let to_block_num = cache_key.to_block_num().copied();
|
let to_block_num = cache_key.to_block_num().copied();
|
||||||
let cache_jsonrpc_errors = cache_key.cache_errors();
|
let cache_jsonrpc_errors = cache_key.cache_errors();
|
||||||
|
|
||||||
|
// don't cache anything larger than 2 MiB
|
||||||
|
let max_response_cache_bytes = 2 * (1024 ^ 2); // self.config.max_response_cache_bytes;
|
||||||
|
|
||||||
// TODO: try to fetch out of s3
|
// TODO: try to fetch out of s3
|
||||||
|
|
||||||
self
|
self
|
||||||
.jsonrpc_response_cache
|
.jsonrpc_response_cache
|
||||||
.try_get_with::<_, Web3ProxyError>(cache_key.hash(), async {
|
.try_get_with::<_, Web3ProxyError>(cache_key.hash(), async {
|
||||||
|
// TODO: think more about this timeout and test that it works well!
|
||||||
let response_data = timeout(
|
let response_data = timeout(
|
||||||
backend_request_timetout + Duration::from_millis(100),
|
backend_request_timetout + Duration::from_millis(100),
|
||||||
self.balanced_rpcs
|
self.balanced_rpcs
|
||||||
@ -1737,6 +1757,9 @@ impl Web3ProxyApp {
|
|||||||
if response_data.is_null() {
|
if response_data.is_null() {
|
||||||
// don't ever cache "null" as a success. its too likely to be a problem
|
// don't ever cache "null" as a success. its too likely to be a problem
|
||||||
Err(Web3ProxyError::NullJsonRpcResult)
|
Err(Web3ProxyError::NullJsonRpcResult)
|
||||||
|
} else if response_data.num_bytes() > max_response_cache_bytes {
|
||||||
|
// don't cache really large requests
|
||||||
|
Err(Web3ProxyError::JsonRpcResponse(response_data))
|
||||||
} else {
|
} else {
|
||||||
// TODO: response data should maybe be Arc<JsonRpcResponseEnum<Box<RawValue>>>, but that's more work
|
// TODO: response data should maybe be Arc<JsonRpcResponseEnum<Box<RawValue>>>, but that's more work
|
||||||
Ok(response_data)
|
Ok(response_data)
|
||||||
|
@ -23,7 +23,6 @@ use redis_rate_limiter::redis::RedisError;
|
|||||||
use redis_rate_limiter::RedisPoolError;
|
use redis_rate_limiter::RedisPoolError;
|
||||||
use reqwest::header::ToStrError;
|
use reqwest::header::ToStrError;
|
||||||
use rust_decimal::Error as DecimalError;
|
use rust_decimal::Error as DecimalError;
|
||||||
use serde::Serialize;
|
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use serde_json::value::RawValue;
|
use serde_json::value::RawValue;
|
||||||
use siwe::VerificationError;
|
use siwe::VerificationError;
|
||||||
@ -124,6 +123,10 @@ pub enum Web3ProxyError {
|
|||||||
#[from(ignore)]
|
#[from(ignore)]
|
||||||
NotImplemented(Cow<'static, str>),
|
NotImplemented(Cow<'static, str>),
|
||||||
NoVolatileRedisDatabase,
|
NoVolatileRedisDatabase,
|
||||||
|
/// make it easy to skip caching large results
|
||||||
|
#[error(ignore)]
|
||||||
|
#[display(fmt = "{:?}", _0)]
|
||||||
|
JsonRpcResponse(JsonRpcResponseEnum<Arc<RawValue>>),
|
||||||
/// make it easy to skip caching null results
|
/// make it easy to skip caching null results
|
||||||
NullJsonRpcResult,
|
NullJsonRpcResult,
|
||||||
OriginRequired,
|
OriginRequired,
|
||||||
@ -181,7 +184,7 @@ pub enum Web3ProxyError {
|
|||||||
impl Web3ProxyError {
|
impl Web3ProxyError {
|
||||||
/// turn the error into an axum response.
|
/// turn the error into an axum response.
|
||||||
/// <https://www.jsonrpc.org/specification#error_object>
|
/// <https://www.jsonrpc.org/specification#error_object>
|
||||||
pub fn as_response_parts<R: Serialize>(&self) -> (StatusCode, JsonRpcResponseEnum<R>) {
|
pub fn as_response_parts(&self) -> (StatusCode, JsonRpcResponseEnum<Arc<RawValue>>) {
|
||||||
// TODO: include a unique request id in the data
|
// TODO: include a unique request id in the data
|
||||||
let (code, err): (StatusCode, JsonRpcErrorData) = match self {
|
let (code, err): (StatusCode, JsonRpcErrorData) = match self {
|
||||||
Self::Abi(err) => {
|
Self::Abi(err) => {
|
||||||
@ -761,6 +764,10 @@ impl Web3ProxyError {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Self::JsonRpcResponse(response_enum) => {
|
||||||
|
// TODO: shame we have to clone, but its an Arc so its not terrible
|
||||||
|
return (StatusCode::OK, response_enum.clone());
|
||||||
|
}
|
||||||
Self::NullJsonRpcResult => {
|
Self::NullJsonRpcResult => {
|
||||||
return (StatusCode::OK, JsonRpcResponseEnum::NullResult);
|
return (StatusCode::OK, JsonRpcResponseEnum::NullResult);
|
||||||
}
|
}
|
||||||
|
@ -464,7 +464,7 @@ impl ResponseOrBytes<'_> {
|
|||||||
.len(),
|
.len(),
|
||||||
Self::Bytes(num_bytes) => *num_bytes,
|
Self::Bytes(num_bytes) => *num_bytes,
|
||||||
Self::Error(x) => {
|
Self::Error(x) => {
|
||||||
let (_, x) = x.as_response_parts::<()>();
|
let (_, x) = x.as_response_parts();
|
||||||
|
|
||||||
x.num_bytes() as usize
|
x.num_bytes() as usize
|
||||||
}
|
}
|
||||||
@ -579,6 +579,8 @@ impl RequestMetadata {
|
|||||||
self.response_timestamp
|
self.response_timestamp
|
||||||
.store(Utc::now().timestamp(), atomic::Ordering::Release);
|
.store(Utc::now().timestamp(), atomic::Ordering::Release);
|
||||||
|
|
||||||
|
// TODO: set user_error_response and error_response here instead of outside this function
|
||||||
|
|
||||||
if let Some(kafka_debug_logger) = self.kafka_debug_logger.as_ref() {
|
if let Some(kafka_debug_logger) = self.kafka_debug_logger.as_ref() {
|
||||||
if let ResponseOrBytes::Response(response) = response {
|
if let ResponseOrBytes::Response(response) = response {
|
||||||
kafka_debug_logger.log_debug_response(response);
|
kafka_debug_logger.log_debug_response(response);
|
||||||
|
@ -109,6 +109,14 @@ impl<R> JsonRpcResponseEnum<R> {
|
|||||||
Self::RpcError { num_bytes, .. } => *num_bytes,
|
Self::RpcError { num_bytes, .. } => *num_bytes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_error(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::NullResult => false,
|
||||||
|
Self::Result { .. } => false,
|
||||||
|
Self::RpcError { .. } => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R> JsonRpcResponseEnum<Option<R>> {
|
impl<R> JsonRpcResponseEnum<Option<R>> {
|
||||||
@ -157,19 +165,25 @@ impl From<Box<RawValue>> for JsonRpcResponseEnum<Arc<RawValue>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R> TryFrom<Web3ProxyError> for JsonRpcResponseEnum<R> {
|
impl TryFrom<Web3ProxyError> for JsonRpcResponseEnum<Arc<RawValue>> {
|
||||||
type Error = Web3ProxyError;
|
type Error = Web3ProxyError;
|
||||||
|
|
||||||
fn try_from(value: Web3ProxyError) -> Result<Self, Self::Error> {
|
fn try_from(value: Web3ProxyError) -> Result<Self, Self::Error> {
|
||||||
if let Web3ProxyError::EthersProvider(ref err) = value {
|
match value {
|
||||||
if let Ok(x) = JsonRpcErrorData::try_from(err) {
|
Web3ProxyError::EthersProvider(err) => {
|
||||||
|
if let Ok(x) = JsonRpcErrorData::try_from(&err) {
|
||||||
let x = x.into();
|
let x = x.into();
|
||||||
|
|
||||||
return Ok(x);
|
Ok(x)
|
||||||
|
} else {
|
||||||
|
Err(err.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Web3ProxyError::NullJsonRpcResult => Ok(JsonRpcResponseEnum::NullResult),
|
||||||
Err(value)
|
Web3ProxyError::JsonRpcResponse(x) => Ok(x),
|
||||||
|
Web3ProxyError::JsonRpcErrorData(err) => Ok(err.into()),
|
||||||
|
err => Err(err),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user