use crate::{
constants::BlockNumber,
state::{WithOverlay, blocks::GetBlockNumberImpl},
};
use gear_common::storage::{
AuxiliaryDoubleStorageWrap, DoubleBTreeMap, Interval, IterableByKeyMap, Waitlist,
WaitlistCallbacks, WaitlistError, WaitlistImpl, WaitlistKeyGen,
};
use gear_core::{
ids::{ActorId, MessageId},
message::StoredDispatch,
};
use std::thread::LocalKey;
pub type AuxiliaryWaitlist = WaitlistImpl<
WaitlistStorageWrap,
WaitlistedMessage,
BlockNumber,
WaitlistErrorImpl,
WaitlistErrorImpl,
WaitlistCallbacksImpl,
WaitlistKeyGen,
>;
pub type WaitlistedMessage = StoredDispatch;
pub(crate) type WaitlistStorage =
WithOverlay<DoubleBTreeMap<ActorId, MessageId, (WaitlistedMessage, Interval<BlockNumber>)>>;
std::thread_local! {
pub(crate) static WAITLIST_STORAGE: WaitlistStorage = Default::default();
}
fn storage() -> &'static LocalKey<WaitlistStorage> {
&WAITLIST_STORAGE
}
#[derive(Debug, Default)]
pub(crate) struct WaitlistManager;
impl WaitlistManager {
pub(crate) fn contains(&self, program_id: ActorId, message_id: MessageId) -> bool {
<AuxiliaryWaitlist as Waitlist>::contains(&program_id, &message_id)
}
pub(crate) fn insert(
&self,
message: WaitlistedMessage,
expected: BlockNumber,
) -> Result<(), WaitlistErrorImpl> {
<AuxiliaryWaitlist as Waitlist>::insert(message, expected)
}
pub(crate) fn remove(
&self,
program_id: ActorId,
message_id: MessageId,
) -> Result<(WaitlistedMessage, Interval<BlockNumber>), WaitlistErrorImpl> {
<AuxiliaryWaitlist as Waitlist>::remove(program_id, message_id)
}
pub(crate) fn clear(&self) {
<AuxiliaryWaitlist as Waitlist>::clear();
}
pub(crate) fn drain_key(
&self,
program_id: ActorId,
) -> impl Iterator<Item = (StoredDispatch, Interval<BlockNumber>)> + Send + 'static {
<AuxiliaryWaitlist as IterableByKeyMap<(StoredDispatch, Interval<BlockNumber>)>>::drain_key(
program_id,
)
}
}
pub(crate) struct WaitlistCallbacksImpl;
impl WaitlistCallbacks for WaitlistCallbacksImpl {
type Value = WaitlistedMessage;
type BlockNumber = BlockNumber;
type GetBlockNumber = GetBlockNumberImpl;
type OnInsert = ();
type OnRemove = ();
}
pub struct WaitlistStorageWrap;
impl AuxiliaryDoubleStorageWrap for WaitlistStorageWrap {
type Key1 = ActorId;
type Key2 = MessageId;
type Value = (WaitlistedMessage, Interval<BlockNumber>);
fn with_storage<F, R>(f: F) -> R
where
F: FnOnce(&DoubleBTreeMap<Self::Key1, Self::Key2, Self::Value>) -> R,
{
storage().with(|wls| f(&wls.data()))
}
fn with_storage_mut<F, R>(f: F) -> R
where
F: FnOnce(&mut DoubleBTreeMap<Self::Key1, Self::Key2, Self::Value>) -> R,
{
storage().with(|wls| f(&mut wls.data_mut()))
}
}
#[derive(Debug)]
pub enum WaitlistErrorImpl {
DuplicateKey,
ElementNotFound,
}
impl WaitlistError for WaitlistErrorImpl {
fn duplicate_key() -> Self {
Self::DuplicateKey
}
fn element_not_found() -> Self {
Self::ElementNotFound
}
}