split inner and outer
This commit is contained in:
parent
949c3eeb5d
commit
f7997a4878
@ -34,7 +34,7 @@ impl Serialize for Web3ProxyBlock {
|
|||||||
// TODO: i'm not sure about this name
|
// TODO: i'm not sure about this name
|
||||||
let mut state = serializer.serialize_struct("saved_block", 2)?;
|
let mut state = serializer.serialize_struct("saved_block", 2)?;
|
||||||
|
|
||||||
state.serialize_field("age", &self.age())?;
|
state.serialize_field("age", &self.age().as_secs_f32())?;
|
||||||
|
|
||||||
let block = json!({
|
let block = json!({
|
||||||
"hash": self.0.hash,
|
"hash": self.0.hash,
|
||||||
|
@ -124,6 +124,7 @@ pub struct RankedRpcs {
|
|||||||
// TODO: could these be refs? The owning RankedRpcs lifetime might work. `stream!` might make it complicated
|
// TODO: could these be refs? The owning RankedRpcs lifetime might work. `stream!` might make it complicated
|
||||||
pub struct RpcsForRequest {
|
pub struct RpcsForRequest {
|
||||||
inner: Vec<Arc<Web3Rpc>>,
|
inner: Vec<Arc<Web3Rpc>>,
|
||||||
|
outer: Vec<Arc<Web3Rpc>>,
|
||||||
request: Arc<Web3Request>,
|
request: Arc<Web3Request>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,10 +277,9 @@ impl RankedRpcs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inner.extend(outer);
|
|
||||||
|
|
||||||
Some(RpcsForRequest {
|
Some(RpcsForRequest {
|
||||||
inner,
|
inner,
|
||||||
|
outer,
|
||||||
request: web3_request.clone(),
|
request: web3_request.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -972,6 +972,18 @@ impl ConsensusFinder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn best_rpc<'a>(rpc_a: &'a Arc<Web3Rpc>, rpc_b: &'a Arc<Web3Rpc>) -> &'a Arc<Web3Rpc> {
|
||||||
|
let now = Instant::now();
|
||||||
|
|
||||||
|
let faster = min_by_key(rpc_a, rpc_b, |x| {
|
||||||
|
(x.next_available(now), x.backup, x.weighted_peak_latency())
|
||||||
|
});
|
||||||
|
|
||||||
|
trace!("{} vs {} = {}", rpc_a, rpc_b, faster);
|
||||||
|
|
||||||
|
faster
|
||||||
|
}
|
||||||
|
|
||||||
impl RpcsForRequest {
|
impl RpcsForRequest {
|
||||||
pub fn to_stream(self) -> impl Stream<Item = OpenRequestHandle> {
|
pub fn to_stream(self) -> impl Stream<Item = OpenRequestHandle> {
|
||||||
// TODO: get error_handler out of the web3_request, probably the authorization
|
// TODO: get error_handler out of the web3_request, probably the authorization
|
||||||
@ -982,30 +994,29 @@ impl RpcsForRequest {
|
|||||||
loop {
|
loop {
|
||||||
let mut earliest_retry_at = None;
|
let mut earliest_retry_at = None;
|
||||||
|
|
||||||
let now = Instant::now();
|
// first check the inners
|
||||||
|
// TODO: DRY
|
||||||
// TODO: need an iter of self.inner, then self.outer
|
|
||||||
|
|
||||||
// we have to collect cuz apparently a Chain isn't sized
|
|
||||||
for (rpc_a, rpc_b) in self.inner.iter().circular_tuple_windows() {
|
for (rpc_a, rpc_b) in self.inner.iter().circular_tuple_windows() {
|
||||||
trace!("{} vs {}", rpc_a, rpc_b);
|
|
||||||
// TODO: ties within X% to the server with the smallest block_data_limit?
|
// TODO: ties within X% to the server with the smallest block_data_limit?
|
||||||
// find rpc with the lowest weighted peak latency. backups always lose. rate limits always lose
|
// find rpc with the lowest weighted peak latency. backups always lose. rate limits always lose
|
||||||
let faster_rpc = min_by_key(rpc_a, rpc_b, |x| (Reverse(x.next_available(now)), x.backup, x.weighted_peak_latency()));
|
// TODO: should next_available be reversed?
|
||||||
trace!("winner: {}", faster_rpc);
|
// TODO: this is similar to sort_for_load_balancing_on, but at this point we don't want to prefer tiers
|
||||||
|
// TODO: move ethis to a helper function just so we can test it
|
||||||
|
// TODO: should x.next_available should be Reverse<_>?
|
||||||
|
let best_rpc = best_rpc(rpc_a, rpc_b);
|
||||||
|
|
||||||
match faster_rpc
|
match best_rpc
|
||||||
.try_request_handle(&self.request, error_handler)
|
.try_request_handle(&self.request, error_handler)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(OpenRequestResult::Handle(handle)) => {
|
Ok(OpenRequestResult::Handle(handle)) => {
|
||||||
trace!("opened handle: {}", faster_rpc);
|
trace!("opened handle: {}", best_rpc);
|
||||||
yield handle;
|
yield handle;
|
||||||
}
|
}
|
||||||
Ok(OpenRequestResult::RetryAt(retry_at)) => {
|
Ok(OpenRequestResult::RetryAt(retry_at)) => {
|
||||||
trace!(
|
trace!(
|
||||||
"retry on {} @ {}",
|
"retry on {} @ {}",
|
||||||
faster_rpc,
|
best_rpc,
|
||||||
retry_at.duration_since(Instant::now()).as_secs_f32()
|
retry_at.duration_since(Instant::now()).as_secs_f32()
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1014,17 +1025,40 @@ impl RpcsForRequest {
|
|||||||
}
|
}
|
||||||
Ok(OpenRequestResult::NotReady) => {
|
Ok(OpenRequestResult::NotReady) => {
|
||||||
// TODO: log a warning? emit a stat?
|
// TODO: log a warning? emit a stat?
|
||||||
trace!("best_rpc not ready: {}", faster_rpc);
|
trace!("best_rpc not ready: {}", best_rpc);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
trace!("No request handle for {}. err={:?}", faster_rpc, err);
|
trace!("No request handle for {}. err={:?}", best_rpc, err);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check self.outer
|
// check self.outer only after self.inner. thats because the outer rpcs weren't ready to serve the request
|
||||||
|
for (rpc_a, rpc_b) in self.outer.iter().circular_tuple_windows() {
|
||||||
|
// TODO: ties within X% to the server with the smallest block_data_limit?
|
||||||
|
// find rpc with the lowest weighted peak latency. backups always lose. rate limits always lose
|
||||||
|
// TODO: should next_available be reversed?
|
||||||
|
// TODO: this is similar to sort_for_load_balancing_on, but at this point we don't want to prefer tiers
|
||||||
|
// TODO: move ethis to a helper function just so we can test it
|
||||||
|
// TODO: should x.next_available should be Reverse<_>?
|
||||||
|
let best_rpc = best_rpc(rpc_a, rpc_b);
|
||||||
|
|
||||||
|
match best_rpc
|
||||||
|
.wait_for_request_handle(&self.request, error_handler)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(handle) => {
|
||||||
|
trace!("opened handle: {}", best_rpc);
|
||||||
|
yield handle;
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
trace!("No request handle for {}. err={:?}", best_rpc, err);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(retry_at) = earliest_retry_at {
|
if let Some(retry_at) = earliest_retry_at {
|
||||||
if self.request.expire_instant <= retry_at {
|
if self.request.expire_instant <= retry_at {
|
||||||
|
Loading…
Reference in New Issue
Block a user