Add cache for parallel HTTP requests (#4879)

This commit is contained in:
Michael Sproul
2024-01-11 17:13:43 +11:00
committed by GitHub
parent 8db17dac1d
commit 664a7784f8
21 changed files with 466 additions and 260 deletions

View File

@@ -926,7 +926,7 @@ pub fn serve<T: BeaconChainTypes>(
.shuffling_cache
.try_write_for(std::time::Duration::from_secs(1))
{
cache_write.insert_committee_cache(
cache_write.insert_value(
shuffling_id,
&possibly_built_cache,
);

View File

@@ -1,6 +1,7 @@
use crate::ExecutionOptimistic;
use beacon_chain::{BeaconChain, BeaconChainError, BeaconChainTypes};
use eth2::types::StateId as CoreStateId;
use slog::{debug, warn};
use std::fmt;
use std::str::FromStr;
use types::{BeaconState, Checkpoint, EthSpec, Fork, Hash256, Slot};
@@ -187,6 +188,49 @@ impl StateId {
_ => (self.root(chain)?, None),
};
let mut opt_state_cache = Some(chain.parallel_state_cache.write());
// Try the cache.
if let Some(cache_item) = opt_state_cache
.as_mut()
.and_then(|cache| cache.get(&state_root))
{
drop(opt_state_cache.take());
match cache_item.wait() {
Ok(state) => {
debug!(
chain.logger(),
"HTTP state cache hit";
"state_root" => ?state_root,
"slot" => state.slot(),
);
return Ok(((*state).clone(), execution_optimistic, finalized));
}
Err(e) => {
warn!(
chain.logger(),
"State promise failed";
"state_root" => ?state_root,
"outcome" => "re-computing",
"error" => ?e,
);
}
}
}
// Re-lock only in case of failed promise.
debug!(
chain.logger(),
"HTTP state cache miss";
"state_root" => ?state_root
);
let mut state_cache = opt_state_cache.unwrap_or_else(|| chain.parallel_state_cache.write());
let sender = state_cache.create_promise(state_root).map_err(|e| {
warp_utils::reject::custom_server_error(format!("too many concurrent requests: {e:?}"))
})?;
drop(state_cache);
let state = chain
.get_state(&state_root, slot_opt)
.map_err(warp_utils::reject::beacon_chain_error)
@@ -199,6 +243,11 @@ impl StateId {
})
})?;
// Fulfil promise (and re-lock again).
let mut state_cache = chain.parallel_state_cache.write();
state_cache.resolve_promise(sender, state_root, &state);
drop(state_cache);
Ok((state, execution_optimistic, finalized))
}