use super::*;
use frame_support::{pallet_prelude::*, traits::OnRuntimeUpgrade};
use sp_std::{marker::PhantomData, vec::Vec};
pub struct LastAuthoredBlockCleanup<T: Config>(PhantomData<T>);
impl<T: Config> OnRuntimeUpgrade for LastAuthoredBlockCleanup<T> {
fn on_runtime_upgrade() -> Weight {
log::info!("Running CollatorSelection::LastAuthoredBlockCleanup...");
let invulnerables = Invulnerables::<T>::get();
let candidates: sp_std::collections::btree_set::BTreeSet<T::AccountId> =
Candidates::<T>::get().into_iter().map(|c| c.who).collect();
let mut read = 0u64;
let mut write = 0u64;
let mut stale = Vec::new();
const MAX_SCAN: u64 = 200;
for (account, _) in LastAuthoredBlock::<T>::iter() {
if read >= MAX_SCAN {
log::warn!("LastAuthoredBlockCleanup: scan limit {} reached.", MAX_SCAN);
break;
}
read += 1;
let keep = invulnerables.contains(&account) || candidates.contains(&account);
if !keep {
stale.push(account);
}
}
for account in stale {
LastAuthoredBlock::<T>::remove(account);
write += 1;
}
log::info!(
"LastAuthoredBlockCleanup completed: removed {} entries (reads {}, writes {}).",
write,
read,
write
);
<T as frame_system::Config>::DbWeight::get().reads_writes(read, write)
}
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
let old_count = LastAuthoredBlock::<T>::iter().count() as u64;
Ok(old_count.encode())
}
#[cfg(feature = "try-runtime")]
fn post_upgrade(data: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
let old_count: u64 = Decode::decode(&mut &data[..]).map_err(|_| {
sp_runtime::TryRuntimeError::Other("Failed to decode pre-upgrade count")
})?;
let new_count = LastAuthoredBlock::<T>::iter().count() as u64;
assert!(
new_count < old_count,
"LastAuthoredBlockCleanup: new count > old count (should only decrease)"
);
Ok(())
}
}