more refs will cut down on cloning an Arc multiple times that isn't really necessary
This commit is contained in:
parent
376048a76b
commit
f704d1c4aa
@ -1097,7 +1097,7 @@ impl Web3ProxyApp {
|
|||||||
self: &Arc<Self>,
|
self: &Arc<Self>,
|
||||||
web3_request: &Arc<Web3Request>,
|
web3_request: &Arc<Web3Request>,
|
||||||
) -> Web3ProxyResult<Arc<RawValue>> {
|
) -> Web3ProxyResult<Arc<RawValue>> {
|
||||||
if self.protected_rpcs.is_empty() {
|
let rpcs = if self.protected_rpcs.is_empty() {
|
||||||
let num_public_rpcs = match web3_request.proxy_mode() {
|
let num_public_rpcs = match web3_request.proxy_mode() {
|
||||||
// TODO: how many balanced rpcs should we send to? configurable? percentage of total?
|
// TODO: how many balanced rpcs should we send to? configurable? percentage of total?
|
||||||
ProxyMode::Best | ProxyMode::Debug => Some(4),
|
ProxyMode::Best | ProxyMode::Debug => Some(4),
|
||||||
@ -1110,6 +1110,8 @@ impl Web3ProxyApp {
|
|||||||
ProxyMode::Versus => None,
|
ProxyMode::Versus => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.balanced_rpcs.try_rpcs_for_request(web3_request).await
|
||||||
|
|
||||||
// // no private rpcs to send to. send to a few public rpcs
|
// // no private rpcs to send to. send to a few public rpcs
|
||||||
// // try_send_all_upstream_servers puts the request id into the response. no need to do that ourselves here.
|
// // try_send_all_upstream_servers puts the request id into the response. no need to do that ourselves here.
|
||||||
// self.balanced_rpcs
|
// self.balanced_rpcs
|
||||||
@ -1120,19 +1122,12 @@ impl Web3ProxyApp {
|
|||||||
// num_public_rpcs,
|
// num_public_rpcs,
|
||||||
// )
|
// )
|
||||||
// .await
|
// .await
|
||||||
todo!();
|
|
||||||
} else {
|
} else {
|
||||||
// self.protected_rpcs
|
self.protected_rpcs.try_rpcs_for_request(web3_request).await
|
||||||
// .try_send_all_synced_connections(
|
};
|
||||||
// web3_request,
|
|
||||||
// Some(Duration::from_secs(10)),
|
|
||||||
// Some(Level::TRACE.into()),
|
|
||||||
// Some(3),
|
|
||||||
// )
|
|
||||||
// .await
|
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// proxy request with up to 3 tries.
|
/// proxy request with up to 3 tries.
|
||||||
async fn proxy_request(
|
async fn proxy_request(
|
||||||
@ -1157,8 +1152,7 @@ impl Web3ProxyApp {
|
|||||||
|
|
||||||
tries += 1;
|
tries += 1;
|
||||||
|
|
||||||
let (code, response) =
|
let (code, response) = match self._proxy_request_with_caching(&web3_request).await {
|
||||||
match self._proxy_request_with_caching(web3_request.clone()).await {
|
|
||||||
Ok(response_data) => {
|
Ok(response_data) => {
|
||||||
web3_request.error_response.store(false, Ordering::Relaxed);
|
web3_request.error_response.store(false, Ordering::Relaxed);
|
||||||
web3_request
|
web3_request
|
||||||
@ -1219,7 +1213,7 @@ impl Web3ProxyApp {
|
|||||||
/// TODO: how can we make this generic?
|
/// TODO: how can we make this generic?
|
||||||
async fn _proxy_request_with_caching(
|
async fn _proxy_request_with_caching(
|
||||||
self: &Arc<Self>,
|
self: &Arc<Self>,
|
||||||
web3_request: Arc<Web3Request>,
|
web3_request: &Arc<Web3Request>,
|
||||||
) -> Web3ProxyResult<jsonrpc::SingleResponse> {
|
) -> Web3ProxyResult<jsonrpc::SingleResponse> {
|
||||||
// TODO: serve net_version without querying the backend
|
// TODO: serve net_version without querying the backend
|
||||||
// TODO: don't force RawValue
|
// TODO: don't force RawValue
|
||||||
@ -1338,7 +1332,7 @@ impl Web3ProxyApp {
|
|||||||
let mut gas_estimate = self
|
let mut gas_estimate = self
|
||||||
.balanced_rpcs
|
.balanced_rpcs
|
||||||
.try_proxy_connection::<U256>(
|
.try_proxy_connection::<U256>(
|
||||||
web3_request.clone(),
|
web3_request,
|
||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
.parsed()
|
.parsed()
|
||||||
@ -1374,7 +1368,7 @@ impl Web3ProxyApp {
|
|||||||
let mut result = self
|
let mut result = self
|
||||||
.balanced_rpcs
|
.balanced_rpcs
|
||||||
.try_proxy_connection::<Arc<RawValue>>(
|
.try_proxy_connection::<Arc<RawValue>>(
|
||||||
web3_request.clone(),
|
web3_request,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
@ -1433,7 +1427,7 @@ impl Web3ProxyApp {
|
|||||||
|
|
||||||
let response = self
|
let response = self
|
||||||
.try_send_protected(
|
.try_send_protected(
|
||||||
&web3_request,
|
web3_request,
|
||||||
).await;
|
).await;
|
||||||
|
|
||||||
let mut response = response.try_into()?;
|
let mut response = response.try_into()?;
|
||||||
@ -1637,7 +1631,7 @@ impl Web3ProxyApp {
|
|||||||
web3_request.ttl(),
|
web3_request.ttl(),
|
||||||
self.balanced_rpcs
|
self.balanced_rpcs
|
||||||
.try_proxy_connection::<Arc<RawValue>>(
|
.try_proxy_connection::<Arc<RawValue>>(
|
||||||
web3_request,
|
&web3_request,
|
||||||
)
|
)
|
||||||
).await??
|
).await??
|
||||||
} else {
|
} else {
|
||||||
@ -1658,7 +1652,7 @@ impl Web3ProxyApp {
|
|||||||
web3_request.ttl(),
|
web3_request.ttl(),
|
||||||
self.balanced_rpcs
|
self.balanced_rpcs
|
||||||
.try_proxy_connection::<Arc<RawValue>>(
|
.try_proxy_connection::<Arc<RawValue>>(
|
||||||
web3_request.clone(),
|
&web3_request,
|
||||||
)
|
)
|
||||||
).await??
|
).await??
|
||||||
}
|
}
|
||||||
@ -1678,7 +1672,7 @@ impl Web3ProxyApp {
|
|||||||
// TODO: dynamic timeout based on whats left on web3_request
|
// TODO: dynamic timeout based on whats left on web3_request
|
||||||
let response_data = timeout(duration, app.balanced_rpcs
|
let response_data = timeout(duration, app.balanced_rpcs
|
||||||
.try_proxy_connection::<Arc<RawValue>>(
|
.try_proxy_connection::<Arc<RawValue>>(
|
||||||
web3_request.clone(),
|
&web3_request,
|
||||||
)).await;
|
)).await;
|
||||||
|
|
||||||
match response_data {
|
match response_data {
|
||||||
@ -1754,7 +1748,7 @@ impl Web3ProxyApp {
|
|||||||
web3_request.ttl(),
|
web3_request.ttl(),
|
||||||
self.balanced_rpcs
|
self.balanced_rpcs
|
||||||
.try_proxy_connection::<Arc<RawValue>>(
|
.try_proxy_connection::<Arc<RawValue>>(
|
||||||
web3_request.clone(),
|
&web3_request,
|
||||||
)
|
)
|
||||||
).await??;
|
).await??;
|
||||||
|
|
||||||
|
@ -49,6 +49,7 @@ impl ParsedResponse<Arc<RawValue>> {
|
|||||||
match data {
|
match data {
|
||||||
JsonRpcResponseEnum::NullResult => {
|
JsonRpcResponseEnum::NullResult => {
|
||||||
let x: Box<RawValue> = Default::default();
|
let x: Box<RawValue> = Default::default();
|
||||||
|
// TODO: how can we make this generic if this always wants to be a Box<RawValue>?. Do we even want to keep NullResult?
|
||||||
Self::from_result(Arc::from(x), id)
|
Self::from_result(Arc::from(x), id)
|
||||||
}
|
}
|
||||||
JsonRpcResponseEnum::RpcError { error_data, .. } => Self::from_error(error_data, id),
|
JsonRpcResponseEnum::RpcError { error_data, .. } => Self::from_error(error_data, id),
|
||||||
|
@ -95,6 +95,12 @@ pub enum ShouldWaitForBlock {
|
|||||||
NeverReady,
|
NeverReady,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize)]
|
||||||
|
enum SortMethod {
|
||||||
|
Shuffle,
|
||||||
|
Sort,
|
||||||
|
}
|
||||||
|
|
||||||
/// A collection of Web3Rpcs that are on the same block.
|
/// A collection of Web3Rpcs that are on the same block.
|
||||||
/// Serialize is so we can print it on our /status endpoint
|
/// Serialize is so we can print it on our /status endpoint
|
||||||
/// TODO: remove head_block/head_rpcs/tier and replace with one RankedRpcMap
|
/// TODO: remove head_block/head_rpcs/tier and replace with one RankedRpcMap
|
||||||
@ -111,6 +117,8 @@ pub struct RankedRpcs {
|
|||||||
// TODO: make serializing work. the key needs to be a string. I think we need `serialize_with`
|
// TODO: make serializing work. the key needs to be a string. I think we need `serialize_with`
|
||||||
#[serde(skip_serializing)]
|
#[serde(skip_serializing)]
|
||||||
rpc_data: HashMap<Arc<Web3Rpc>, ConsensusRpcData>,
|
rpc_data: HashMap<Arc<Web3Rpc>, ConsensusRpcData>,
|
||||||
|
|
||||||
|
sort_mode: SortMethod,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RpcsForRequest {
|
pub struct RpcsForRequest {
|
||||||
@ -128,14 +136,18 @@ impl RankedRpcs {
|
|||||||
|
|
||||||
let num_synced = rpcs.len();
|
let num_synced = rpcs.len();
|
||||||
|
|
||||||
|
// TODO: do we need real data in here? if we are calling from_rpcs, we probably don't even track their block
|
||||||
let rpc_data = Default::default();
|
let rpc_data = Default::default();
|
||||||
|
|
||||||
|
let sort_mode = SortMethod::Shuffle;
|
||||||
|
|
||||||
let ranked_rpcs = RankedRpcs {
|
let ranked_rpcs = RankedRpcs {
|
||||||
backups_needed,
|
backups_needed,
|
||||||
head_block,
|
head_block,
|
||||||
inner: rpcs,
|
inner: rpcs,
|
||||||
num_synced,
|
num_synced,
|
||||||
rpc_data,
|
rpc_data,
|
||||||
|
sort_mode,
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(ranked_rpcs)
|
Some(ranked_rpcs)
|
||||||
@ -205,10 +217,13 @@ impl RankedRpcs {
|
|||||||
// consensus found!
|
// consensus found!
|
||||||
trace!(?ranked_rpcs);
|
trace!(?ranked_rpcs);
|
||||||
|
|
||||||
|
let sort_mode = SortMethod::Sort;
|
||||||
|
|
||||||
let consensus = RankedRpcs {
|
let consensus = RankedRpcs {
|
||||||
backups_needed,
|
backups_needed,
|
||||||
head_block: best_block,
|
head_block: best_block,
|
||||||
rpc_data,
|
rpc_data,
|
||||||
|
sort_mode,
|
||||||
inner: ranked_rpcs,
|
inner: ranked_rpcs,
|
||||||
num_synced,
|
num_synced,
|
||||||
};
|
};
|
||||||
@ -219,7 +234,7 @@ impl RankedRpcs {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn for_request(&self, web3_request: Arc<Web3Request>) -> Option<RpcsForRequest> {
|
pub fn for_request(&self, web3_request: &Arc<Web3Request>) -> Option<RpcsForRequest> {
|
||||||
if self.num_active_rpcs() == 0 {
|
if self.num_active_rpcs() == 0 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@ -251,7 +266,7 @@ impl RankedRpcs {
|
|||||||
Some(RpcsForRequest {
|
Some(RpcsForRequest {
|
||||||
inner,
|
inner,
|
||||||
outer,
|
outer,
|
||||||
request: web3_request,
|
request: web3_request.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//! Load balanced communication with a group of web3 rpc providers
|
//! Load balanced communication with a group of web3 rpc providers
|
||||||
use super::blockchain::{BlocksByHashCache, BlocksByNumberCache, Web3ProxyBlock};
|
use super::blockchain::{BlocksByHashCache, BlocksByNumberCache, Web3ProxyBlock};
|
||||||
use super::consensus::{RankedRpcs, RpcsForRequest, ShouldWaitForBlock};
|
use super::consensus::{RankedRpcs, RpcsForRequest};
|
||||||
use super::one::Web3Rpc;
|
use super::one::Web3Rpc;
|
||||||
use super::request::{OpenRequestHandle, OpenRequestResult, RequestErrorHandler};
|
use super::request::{OpenRequestHandle, OpenRequestResult, RequestErrorHandler};
|
||||||
use crate::app::{flatten_handle, Web3ProxyApp, Web3ProxyJoinHandle};
|
use crate::app::{flatten_handle, Web3ProxyApp, Web3ProxyJoinHandle};
|
||||||
@ -10,7 +10,6 @@ use crate::frontend::authorization::Web3Request;
|
|||||||
use crate::frontend::rpc_proxy_ws::ProxyMode;
|
use crate::frontend::rpc_proxy_ws::ProxyMode;
|
||||||
use crate::frontend::status::MokaCacheSerializer;
|
use crate::frontend::status::MokaCacheSerializer;
|
||||||
use crate::jsonrpc::{self, JsonRpcErrorData, JsonRpcParams, JsonRpcResultData, ParsedResponse};
|
use crate::jsonrpc::{self, JsonRpcErrorData, JsonRpcParams, JsonRpcResultData, ParsedResponse};
|
||||||
use counter::Counter;
|
|
||||||
use derive_more::From;
|
use derive_more::From;
|
||||||
use ethers::prelude::{TxHash, U64};
|
use ethers::prelude::{TxHash, U64};
|
||||||
use futures::future::try_join_all;
|
use futures::future::try_join_all;
|
||||||
@ -23,13 +22,11 @@ use parking_lot::RwLock;
|
|||||||
use serde::ser::{SerializeStruct, Serializer};
|
use serde::ser::{SerializeStruct, Serializer};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cmp::min_by_key;
|
|
||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::sync::{mpsc, watch};
|
use tokio::sync::{mpsc, watch};
|
||||||
use tokio::task::yield_now;
|
use tokio::time::{Duration, Instant};
|
||||||
use tokio::time::{sleep, sleep_until, timeout, Duration, Instant};
|
|
||||||
use tokio::{pin, select};
|
use tokio::{pin, select};
|
||||||
use tracing::{debug, error, info, instrument, trace, warn};
|
use tracing::{debug, error, info, instrument, trace, warn};
|
||||||
|
|
||||||
@ -400,7 +397,7 @@ impl Web3Rpcs {
|
|||||||
/// this prefers synced servers, but it will return servers even if they aren't fully in sync.
|
/// this prefers synced servers, but it will return servers even if they aren't fully in sync.
|
||||||
/// this does not gaurentee you won't be rate limited. we don't increment our counters until you try to send. so you might have to wait to be able to send
|
/// this does not gaurentee you won't be rate limited. we don't increment our counters until you try to send. so you might have to wait to be able to send
|
||||||
/// TODO: should this wait for ranked rpcs? maybe only a fraction of web3_request's time?
|
/// TODO: should this wait for ranked rpcs? maybe only a fraction of web3_request's time?
|
||||||
pub async fn try_rpcs_for_request(&self, web3_request: Arc<Web3Request>) -> TryRpcsForRequest {
|
pub async fn try_rpcs_for_request(&self, web3_request: &Arc<Web3Request>) -> TryRpcsForRequest {
|
||||||
// TODO: by_name might include things that are on a forked
|
// TODO: by_name might include things that are on a forked
|
||||||
let ranked_rpcs: Arc<RankedRpcs> =
|
let ranked_rpcs: Arc<RankedRpcs> =
|
||||||
if let Some(ranked_rpcs) = self.watch_ranked_rpcs.borrow().clone() {
|
if let Some(ranked_rpcs) = self.watch_ranked_rpcs.borrow().clone() {
|
||||||
@ -435,7 +432,7 @@ impl Web3Rpcs {
|
|||||||
let web3_request =
|
let web3_request =
|
||||||
Web3Request::new_internal(method.into(), params, head_block, max_wait).await;
|
Web3Request::new_internal(method.into(), params, head_block, max_wait).await;
|
||||||
|
|
||||||
let response = self.request_with_metadata(web3_request).await?;
|
let response = self.request_with_metadata(&web3_request).await?;
|
||||||
|
|
||||||
let parsed = response.parsed().await?;
|
let parsed = response.parsed().await?;
|
||||||
|
|
||||||
@ -452,7 +449,7 @@ impl Web3Rpcs {
|
|||||||
/// TODO: take an arg for max_tries. take an arg for quorum(size) or serial
|
/// TODO: take an arg for max_tries. take an arg for quorum(size) or serial
|
||||||
pub async fn request_with_metadata<R: JsonRpcResultData>(
|
pub async fn request_with_metadata<R: JsonRpcResultData>(
|
||||||
&self,
|
&self,
|
||||||
web3_request: Arc<Web3Request>,
|
web3_request: &Arc<Web3Request>,
|
||||||
) -> Web3ProxyResult<jsonrpc::SingleResponse<R>> {
|
) -> Web3ProxyResult<jsonrpc::SingleResponse<R>> {
|
||||||
let mut method_not_available_response = None;
|
let mut method_not_available_response = None;
|
||||||
|
|
||||||
@ -467,7 +464,7 @@ impl Web3Rpcs {
|
|||||||
let mut last_provider_error = None;
|
let mut last_provider_error = None;
|
||||||
|
|
||||||
// TODO: limit number of tries
|
// TODO: limit number of tries
|
||||||
match self.try_rpcs_for_request(web3_request.clone()).await {
|
match self.try_rpcs_for_request(web3_request).await {
|
||||||
TryRpcsForRequest::None => return Err(Web3ProxyError::NoServersSynced),
|
TryRpcsForRequest::None => return Err(Web3ProxyError::NoServersSynced),
|
||||||
TryRpcsForRequest::RetryAt(retry_at) => {
|
TryRpcsForRequest::RetryAt(retry_at) => {
|
||||||
if retry_at > web3_request.expire_instant {
|
if retry_at > web3_request.expire_instant {
|
||||||
@ -839,7 +836,7 @@ impl Web3Rpcs {
|
|||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub async fn try_proxy_connection<R: JsonRpcResultData>(
|
pub async fn try_proxy_connection<R: JsonRpcResultData>(
|
||||||
&self,
|
&self,
|
||||||
web3_request: Arc<Web3Request>,
|
web3_request: &Arc<Web3Request>,
|
||||||
) -> Web3ProxyResult<jsonrpc::SingleResponse<R>> {
|
) -> Web3ProxyResult<jsonrpc::SingleResponse<R>> {
|
||||||
let proxy_mode = web3_request.proxy_mode();
|
let proxy_mode = web3_request.proxy_mode();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user