use crate::storage::{
CountedByKey, DoubleMapStorage, EmptyCallback, KeyIterableByKeyMap, ValueStorage,
};
use core::{fmt::Debug, marker::PhantomData};
pub trait Scheduler {
type BlockNumber;
type Task;
type Cost;
type Error: TaskPoolError;
type OutputError: From<Self::Error> + Debug;
type CostsPerBlock: SchedulingCostsPerBlock<BlockNumber = Self::BlockNumber, Cost = Self::Cost>;
type FirstIncompleteTasksBlock: ValueStorage<Value = Self::BlockNumber>;
type TaskPool: TaskPool<
BlockNumber = Self::BlockNumber,
Task = Self::Task,
Error = Self::Error,
OutputError = Self::OutputError,
> + CountedByKey<Key = Self::BlockNumber, Length = usize>
+ KeyIterableByKeyMap<Key1 = Self::BlockNumber, Key2 = Self::Task>;
fn reset() {
Self::FirstIncompleteTasksBlock::kill();
Self::TaskPool::clear();
}
}
pub trait SchedulingCostsPerBlock {
type BlockNumber;
type Cost;
fn reserve_for() -> Self::BlockNumber;
fn code() -> Self::Cost;
fn mailbox() -> Self::Cost;
fn program() -> Self::Cost;
fn waitlist() -> Self::Cost;
fn reservation() -> Self::Cost;
fn dispatch_stash() -> Self::Cost;
fn by_storage_type(storage: StorageType) -> Self::Cost;
}
#[derive(Debug, Clone, Copy)]
pub enum StorageType {
Code,
Mailbox,
Program,
Waitlist,
Reservation,
DispatchStash,
}
pub trait TaskPool {
type BlockNumber;
type Task;
type Error: TaskPoolError;
type OutputError: From<Self::Error>;
fn add(bn: Self::BlockNumber, task: Self::Task) -> Result<(), Self::OutputError>;
fn clear();
fn contains(bn: &Self::BlockNumber, task: &Self::Task) -> bool;
fn delete(bn: Self::BlockNumber, task: Self::Task) -> Result<(), Self::OutputError>;
}
pub trait TaskPoolCallbacks {
type OnAdd: EmptyCallback;
type OnDelete: EmptyCallback;
}
pub trait TaskPoolError {
fn duplicate_task() -> Self;
fn task_not_found() -> Self;
}
pub struct TaskPoolImpl<T, Task, Error, OutputError, Callbacks>(
PhantomData<(T, Task, Error, OutputError, Callbacks)>,
)
where
T: DoubleMapStorage<Key2 = Task, Value = ()>,
Error: TaskPoolError,
OutputError: From<Error>,
Callbacks: TaskPoolCallbacks;
impl<T, Task, Error, OutputError, Callbacks> TaskPool
for TaskPoolImpl<T, Task, Error, OutputError, Callbacks>
where
T: DoubleMapStorage<Key2 = Task, Value = ()>,
Error: TaskPoolError,
OutputError: From<Error>,
Callbacks: TaskPoolCallbacks,
{
type BlockNumber = T::Key1;
type Task = T::Key2;
type Error = Error;
type OutputError = OutputError;
fn add(bn: Self::BlockNumber, task: Self::Task) -> Result<(), Self::OutputError> {
if !Self::contains(&bn, &task) {
T::insert(bn, task, ());
Callbacks::OnAdd::call();
Ok(())
} else {
Err(Self::Error::duplicate_task().into())
}
}
fn clear() {
T::clear()
}
fn contains(bn: &Self::BlockNumber, task: &Self::Task) -> bool {
T::contains_keys(bn, task)
}
fn delete(bn: Self::BlockNumber, task: Self::Task) -> Result<(), Self::OutputError> {
if T::contains_keys(&bn, &task) {
T::remove(bn, task);
Callbacks::OnDelete::call();
Ok(())
} else {
Err(Self::Error::task_not_found().into())
}
}
}
impl<T, Task, Error, OutputError, Callbacks> CountedByKey
for TaskPoolImpl<T, Task, Error, OutputError, Callbacks>
where
T: DoubleMapStorage<Key2 = Task, Value = ()> + CountedByKey<Key = T::Key1>,
Error: TaskPoolError,
OutputError: From<Error>,
Callbacks: TaskPoolCallbacks,
{
type Key = T::Key1;
type Length = T::Length;
fn len(key: &Self::Key) -> Self::Length {
T::len(key)
}
}
impl<T, Task, Error, OutputError, Callbacks> KeyIterableByKeyMap
for TaskPoolImpl<T, Task, Error, OutputError, Callbacks>
where
T: DoubleMapStorage<Key2 = Task, Value = ()> + KeyIterableByKeyMap,
Error: TaskPoolError,
OutputError: From<Error>,
Callbacks: TaskPoolCallbacks,
{
type Key1 = <T as KeyIterableByKeyMap>::Key1;
type Key2 = <T as KeyIterableByKeyMap>::Key2;
type DrainIter = T::DrainIter;
type Iter = T::Iter;
fn drain_prefix_keys(bn: Self::Key1) -> Self::DrainIter {
T::drain_prefix_keys(bn)
}
fn iter_prefix_keys(bn: Self::Key1) -> Self::Iter {
T::iter_prefix_keys(bn)
}
}