Round robin on_idle execution (#9432)

* update on_idle tuple implemenration

* add test

* fix

* fix fmt

* update

* update

* fix fmt

* Update frame/support/src/traits/hooks.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* update

* update

* fix pallet_ui tests

* Update frame/support/src/traits/hooks.rs

* fix

* Update frame/support/src/traits/hooks.rs

* update

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
Alex Pozhylenkov
2021-07-28 14:22:45 +03:00
committed by GitHub
parent 79052e281a
commit a8e5744985
2 changed files with 72 additions and 7 deletions
+70 -5
View File
@@ -19,7 +19,7 @@
use impl_trait_for_tuples::impl_for_tuples;
use sp_arithmetic::traits::Saturating;
use sp_runtime::traits::MaybeSerializeDeserialize;
use sp_runtime::traits::{AtLeast32BitUnsigned, MaybeSerializeDeserialize};
/// The block initialization trait.
///
@@ -80,13 +80,22 @@ pub trait OnIdle<BlockNumber> {
}
#[impl_for_tuples(30)]
impl<BlockNumber: Clone> OnIdle<BlockNumber> for Tuple {
impl<BlockNumber: Copy + AtLeast32BitUnsigned> OnIdle<BlockNumber> for Tuple {
fn on_idle(n: BlockNumber, remaining_weight: crate::weights::Weight) -> crate::weights::Weight {
let on_idle_functions: &[fn(
BlockNumber,
crate::weights::Weight,
) -> crate::weights::Weight] = &[for_tuples!( #( Tuple::on_idle ),* )];
let mut weight = 0;
for_tuples!( #(
let len = on_idle_functions.len();
let start_index = n % (len as u32).into();
let start_index = start_index.try_into().ok().expect(
"`start_index % len` always fits into `usize`, because `len` can be in maximum `usize::MAX`; qed"
);
for on_idle in on_idle_functions.iter().cycle().skip(start_index).take(len) {
let adjusted_remaining_weight = remaining_weight.saturating_sub(weight);
weight = weight.saturating_add(Tuple::on_idle(n.clone(), adjusted_remaining_weight));
)* );
weight = weight.saturating_add(on_idle(n, adjusted_remaining_weight));
}
weight
}
}
@@ -341,4 +350,60 @@ mod tests {
assert_eq!(<(Test, Test)>::on_initialize(0), 20);
assert_eq!(<(Test, Test)>::on_runtime_upgrade(), 40);
}
#[test]
fn on_idle_round_robin_works() {
static mut ON_IDLE_INVOCATION_ORDER: sp_std::vec::Vec<&str> = sp_std::vec::Vec::new();
struct Test1;
struct Test2;
struct Test3;
type TestTuple = (Test1, Test2, Test3);
impl OnIdle<u32> for Test1 {
fn on_idle(_n: u32, _weight: crate::weights::Weight) -> crate::weights::Weight {
unsafe {
ON_IDLE_INVOCATION_ORDER.push("Test1");
}
0
}
}
impl OnIdle<u32> for Test2 {
fn on_idle(_n: u32, _weight: crate::weights::Weight) -> crate::weights::Weight {
unsafe {
ON_IDLE_INVOCATION_ORDER.push("Test2");
}
0
}
}
impl OnIdle<u32> for Test3 {
fn on_idle(_n: u32, _weight: crate::weights::Weight) -> crate::weights::Weight {
unsafe {
ON_IDLE_INVOCATION_ORDER.push("Test3");
}
0
}
}
unsafe {
TestTuple::on_idle(0, 0);
assert_eq!(ON_IDLE_INVOCATION_ORDER, ["Test1", "Test2", "Test3"].to_vec());
ON_IDLE_INVOCATION_ORDER.clear();
TestTuple::on_idle(1, 0);
assert_eq!(ON_IDLE_INVOCATION_ORDER, ["Test2", "Test3", "Test1"].to_vec());
ON_IDLE_INVOCATION_ORDER.clear();
TestTuple::on_idle(2, 0);
assert_eq!(ON_IDLE_INVOCATION_ORDER, ["Test3", "Test1", "Test2"].to_vec());
ON_IDLE_INVOCATION_ORDER.clear();
TestTuple::on_idle(3, 0);
assert_eq!(ON_IDLE_INVOCATION_ORDER, ["Test1", "Test2", "Test3"].to_vec());
ON_IDLE_INVOCATION_ORDER.clear();
TestTuple::on_idle(4, 0);
assert_eq!(ON_IDLE_INVOCATION_ORDER, ["Test2", "Test3", "Test1"].to_vec());
ON_IDLE_INVOCATION_ORDER.clear();
}
}
}