Fix nothing scheduled on session boundary (#1403)

* Fix scheduled state at session boundaries.

* Cleanup + better docs.

* More cleanup and fixes.

* Remove 12s hack.

* Add dep.

* Make clippy happy

---------

Co-authored-by: eskimor <eskimor@no-such-url.com>
This commit is contained in:
eskimor
2023-09-06 18:19:21 +02:00
committed by GitHub
parent eeb368ed9c
commit 1e2a2f0c69
19 changed files with 489 additions and 643 deletions
@@ -29,10 +29,7 @@ use crate::{
initializer,
metrics::METRICS,
paras,
scheduler::{
self,
common::{CoreAssignment, FreedReason},
},
scheduler::{self, FreedReason},
shared, ParaId,
};
use bitvec::prelude::BitVec;
@@ -245,8 +242,8 @@ pub mod pallet {
T: Config,
{
// Handle timeouts for any availability core work.
let availability_pred = <scheduler::Pallet<T>>::availability_timeout_predicate();
let freed_timeout = if let Some(pred) = availability_pred {
let freed_timeout = if <scheduler::Pallet<T>>::availability_timeout_check_required() {
let pred = <scheduler::Pallet<T>>::availability_timeout_predicate();
<inclusion::Pallet<T>>::collect_pending(pred)
} else {
Vec::new()
@@ -320,7 +317,7 @@ impl<T: Config> Pallet<T> {
///
/// When called from `create_inherent` the `context` must be set to
/// `ProcessInherentDataContext::ProvideInherent` so it guarantees the invariant that inherent
/// is not overweight.
/// is not overweight.
/// It is **mandatory** that calls from `enter` set `context` to
/// `ProcessInherentDataContext::Enter` to ensure the weight invariant is checked.
///
@@ -583,7 +580,10 @@ impl<T: Config> Pallet<T> {
let freed = collect_all_freed_cores::<T, _>(freed_concluded.iter().cloned());
let scheduled = <scheduler::Pallet<T>>::update_claimqueue(freed, now);
<scheduler::Pallet<T>>::update_claimqueue(freed, now);
let scheduled = <scheduler::Pallet<T>>::scheduled_paras()
.map(|(core_idx, para_id)| (para_id, core_idx))
.collect();
METRICS.on_candidates_processed_total(backed_candidates.len() as u64);
@@ -608,7 +608,7 @@ impl<T: Config> Pallet<T> {
.verify_backed_candidate(&allowed_relay_parents, candidate_idx, backed_candidate)
.is_err()
},
&scheduled[..],
&scheduled,
);
METRICS.on_candidates_sanitized(backed_candidates.len() as u64);
@@ -620,7 +620,7 @@ impl<T: Config> Pallet<T> {
} = <inclusion::Pallet<T>>::process_candidates(
&allowed_relay_parents,
backed_candidates.clone(),
scheduled,
&scheduled,
<scheduler::Pallet<T>>::group_validators,
)?;
// Note which of the scheduled cores were actually occupied by a backed candidate.
@@ -917,7 +917,7 @@ fn sanitize_backed_candidates<
>(
mut backed_candidates: Vec<BackedCandidate<T::Hash>>,
mut candidate_has_concluded_invalid_dispute_or_is_invalid: F,
scheduled: &[CoreAssignment<BlockNumberFor<T>>],
scheduled: &BTreeMap<ParaId, CoreIndex>,
) -> Vec<BackedCandidate<T::Hash>> {
// Remove any candidates that were concluded invalid.
// This does not assume sorting.
@@ -925,11 +925,6 @@ fn sanitize_backed_candidates<
!candidate_has_concluded_invalid_dispute_or_is_invalid(candidate_idx, backed_candidate)
});
let scheduled_paras_to_core_idx = scheduled
.into_iter()
.map(|core_assignment| (core_assignment.paras_entry.para_id(), core_assignment.core))
.collect::<BTreeMap<ParaId, CoreIndex>>();
// Assure the backed candidate's `ParaId`'s core is free.
// This holds under the assumption that `Scheduler::schedule` is called _before_.
// We don't check the relay-parent because this is done in the closure when
@@ -938,7 +933,7 @@ fn sanitize_backed_candidates<
backed_candidates.retain(|backed_candidate| {
let desc = backed_candidate.descriptor();
scheduled_paras_to_core_idx.get(&desc.para_id).is_some()
scheduled.get(&desc.para_id).is_some()
});
// Sort the `Vec` last, once there is a guarantee that these
@@ -948,8 +943,7 @@ fn sanitize_backed_candidates<
// but also allows this to be done in place.
backed_candidates.sort_by(|x, y| {
// Never panics, since we filtered all panic arguments out in the previous `fn retain`.
scheduled_paras_to_core_idx[&x.descriptor().para_id]
.cmp(&scheduled_paras_to_core_idx[&y.descriptor().para_id])
scheduled[&x.descriptor().para_id].cmp(&scheduled[&y.descriptor().para_id])
});
backed_candidates
@@ -963,10 +963,7 @@ mod sanitizers {
use crate::mock::Test;
use keyring::Sr25519Keyring;
use primitives::{
v5::{Assignment, ParasEntry},
PARACHAIN_KEY_TYPE_ID,
};
use primitives::PARACHAIN_KEY_TYPE_ID;
use sc_keystore::LocalKeystore;
use sp_keystore::{Keystore, KeystorePtr};
use std::sync::Arc;
@@ -1239,21 +1236,10 @@ mod sanitizers {
let has_concluded_invalid =
|_idx: usize, _backed_candidate: &BackedCandidate| -> bool { false };
let entry_ttl = 10_000;
let scheduled = (0_usize..2)
.into_iter()
.map(|idx| {
let core_idx = CoreIndex::from(idx as u32);
let ca = CoreAssignment {
paras_entry: ParasEntry::new(
Assignment::new(ParaId::from(1_u32 + idx as u32)),
entry_ttl,
),
core: core_idx,
};
ca
})
.collect::<Vec<_>>();
.map(|idx| (ParaId::from(1_u32 + idx as u32), CoreIndex::from(idx as u32)))
.collect::<BTreeMap<_, _>>();
let group_validators = |group_index: GroupIndex| {
match group_index {
@@ -1304,7 +1290,7 @@ mod sanitizers {
// nothing is scheduled, so no paraids match, thus all backed candidates are skipped
{
let scheduled = &Vec::new();
let scheduled = &BTreeMap::new();
assert!(sanitize_backed_candidates::<Test, _>(
backed_candidates.clone(),
has_concluded_invalid,