feat(exex): finalize WAL with the lowest finished height (#11323)

This commit is contained in:
Alexey Shekhirin
2024-09-30 11:06:40 +03:00
committed by GitHub
parent e21d75f9aa
commit e02a2de2d0
2 changed files with 22 additions and 17 deletions

View File

@ -333,35 +333,40 @@ where
let exex_finished_heights = self let exex_finished_heights = self
.exex_handles .exex_handles
.iter() .iter()
// Get ExEx ID and hash of the finished height for each ExEx // Get ID and finished height for each ExEx
.map(|exex_handle| { .map(|exex_handle| (&exex_handle.id, exex_handle.finished_height))
(&exex_handle.id, exex_handle.finished_height.map(|block| block.hash))
})
// Deduplicate all hashes // Deduplicate all hashes
.unique_by(|(_, hash)| *hash) .unique_by(|(_, num_hash)| num_hash.map(|num_hash| num_hash.hash))
// Check if hashes are canonical // Check if hashes are canonical
.map(|(exex_id, hash)| { .map(|(exex_id, num_hash)| {
hash.map_or(Ok((exex_id, hash, false)), |hash| { num_hash.map_or(Ok((exex_id, num_hash, false)), |num_hash| {
self.provider self.provider
.is_known(&hash) .is_known(&num_hash.hash)
// Save the ExEx ID, hash of the finished height, and whether the hash // Save the ExEx ID, finished height, and whether the hash is canonical
// is canonical .map(|is_canonical| (exex_id, Some(num_hash), is_canonical))
.map(|is_canonical| (exex_id, Some(hash), is_canonical))
}) })
}) })
// We collect here to be able to log the unfinalized ExExes below // We collect here to be able to log the unfinalized ExExes below
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;
if exex_finished_heights.iter().all(|(_, _, is_canonical)| *is_canonical) { if exex_finished_heights.iter().all(|(_, _, is_canonical)| *is_canonical) {
// If there is a finalized header and all ExExs are on the canonical chain, finalize // If there is a finalized header and all ExExs are on the canonical chain, finalize
// the WAL with the new finalized header // the WAL with the lowest finished height among all ExExes
self.wal.finalize(finalized_header.num_hash())?; let lowest_finished_height = exex_finished_heights
.iter()
.copied()
.filter_map(|(_, num_hash, _)| num_hash)
.min_by_key(|num_hash| num_hash.number);
self.wal
.finalize(lowest_finished_height.expect("ExExManager has at least one ExEx"))?;
} else { } else {
let unfinalized_exexes = exex_finished_heights let unfinalized_exexes = exex_finished_heights
.into_iter() .into_iter()
.filter_map(|(exex_id, hash, is_canonical)| { .filter_map(|(exex_id, num_hash, is_canonical)| {
is_canonical.not().then_some((exex_id, hash)) is_canonical.not().then_some((exex_id, num_hash))
}) })
.format_with(", ", |(exex_id, hash), f| f(&format_args!("{exex_id:?} = {hash:?}"))); .format_with(", ", |(exex_id, num_hash), f| {
f(&format_args!("{exex_id:?} = {num_hash:?}"))
});
debug!( debug!(
%unfinalized_exexes, %unfinalized_exexes,
"Not all ExExes are on the canonical chain, can't finalize the WAL" "Not all ExExes are on the canonical chain, can't finalize the WAL"

View File

@ -18,7 +18,7 @@ pub struct BlockCache {
/// the cache with the same file ID. I.e. for each notification, there may be multiple blocks /// the cache with the same file ID. I.e. for each notification, there may be multiple blocks
/// in the cache. /// in the cache.
files: RwLock<BTreeMap<u64, VecDeque<CachedBlock>>>, files: RwLock<BTreeMap<u64, VecDeque<CachedBlock>>>,
/// A mapping of committed blocks `Block Hash -> Block`. /// A mapping of committed blocks `Block Hash -> (File ID, Block)`.
/// ///
/// For each [`ExExNotification::ChainCommitted`] notification, there will be an entry per /// For each [`ExExNotification::ChainCommitted`] notification, there will be an entry per
/// block. /// block.