Skip to main content

gear_common/storage/complex/
waitlist.rs

1// Copyright (C) Gear Technologies Inc.
2// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
3
4//! Module for waitlist implementation.
5//!
6//! Waitlist provides functionality of delaying messages execution,
7//! addressed to programs, by their storing out of message queue.
8
9use crate::storage::{
10    Callback, CountedByKey, DoubleMapStorage, GetCallback, Interval, IterableByKeyMap, IterableMap,
11    KeyFor,
12};
13use core::marker::PhantomData;
14
15pub type ValueWithInterval<T, B> = (T, Interval<B>);
16
17/// Represents waitlist managing logic.
18pub trait Waitlist {
19    /// First key type.
20    type Key1;
21    /// Second key type.
22    type Key2;
23    /// Stored values type.
24    type Value;
25    /// Block number type.
26    ///
27    /// Stored with `Self::Value`.
28    type BlockNumber;
29    /// Inner error type of waitlist storing algorithm.
30    type Error: WaitlistError;
31    /// Output error type of the waitlist.
32    type OutputError: From<Self::Error>;
33
34    /// Returns bool, defining does first key's waitlist contain second key.
35    fn contains(key1: &Self::Key1, key2: &Self::Key2) -> bool;
36
37    /// Inserts given value in waitlist.
38    fn insert(value: Self::Value, bn: Self::BlockNumber) -> Result<(), Self::OutputError>;
39
40    /// Removes and returns value from waitlist by given keys,
41    /// if present, else returns error.
42    fn remove(
43        key1: Self::Key1,
44        key2: Self::Key2,
45    ) -> Result<ValueWithInterval<Self::Value, Self::BlockNumber>, Self::OutputError>;
46
47    /// Removes all values from all key's waitlisted.
48    fn clear();
49}
50
51/// Represents store of waitlist's action callbacks.
52pub trait WaitlistCallbacks {
53    /// Callback relative type.
54    ///
55    /// This value represents main stored component in waitlist,
56    /// which uses this callbacks store.
57    type Value;
58    /// Callback relative type.
59    ///
60    /// This type represents block number of stored component in waitlist,
61    /// which uses this callbacks store.
62    type BlockNumber;
63
64    /// Callback used for getting current block number.
65    type GetBlockNumber: GetCallback<Self::BlockNumber>;
66    /// Callback on success `insert`.
67    type OnInsert: Callback<ValueWithInterval<Self::Value, Self::BlockNumber>>;
68    /// Callback on success `remove`.
69    type OnRemove: Callback<ValueWithInterval<Self::Value, Self::BlockNumber>>;
70}
71
72/// Represents waitlist error type.
73///
74/// Contains constructors for all existing errors.
75pub trait WaitlistError {
76    /// Occurs when given value already exists in waitlist.
77    fn duplicate_key() -> Self;
78
79    /// Occurs when element wasn't found in storage.
80    fn element_not_found() -> Self;
81}
82
83/// `Waitlist` implementation based on `DoubleMapStorage`.
84///
85/// Generic parameter `Error` requires `WaitlistError` implementation.
86/// Generic parameter `KeyGen` presents key generation for given values.
87/// Generic parameter `Callbacks` presents actions for success operations
88/// over waitlist.
89pub struct WaitlistImpl<T, Value, BlockNumber, Error, OutputError, Callbacks, KeyGen>(
90    PhantomData<(T, Error, OutputError, Callbacks, KeyGen)>,
91)
92where
93    T: DoubleMapStorage<Value = (Value, Interval<BlockNumber>)>,
94    Error: WaitlistError,
95    OutputError: From<Error>,
96    Callbacks: WaitlistCallbacks<Value = Value, BlockNumber = BlockNumber>,
97    KeyGen: KeyFor<Key = (T::Key1, T::Key2), Value = Value>;
98
99// Implementation of `Waitlist` for `WaitlistImpl`.
100impl<T, Value, BlockNumber, Error, OutputError, Callbacks, KeyGen> Waitlist
101    for WaitlistImpl<T, Value, BlockNumber, Error, OutputError, Callbacks, KeyGen>
102where
103    T: DoubleMapStorage<Value = (Value, Interval<BlockNumber>)>,
104    Error: WaitlistError,
105    OutputError: From<Error>,
106    Callbacks: WaitlistCallbacks<Value = Value, BlockNumber = BlockNumber>,
107    KeyGen: KeyFor<Key = (T::Key1, T::Key2), Value = Value>,
108{
109    type Key1 = T::Key1;
110    type Key2 = T::Key2;
111    type Value = Value;
112    type BlockNumber = BlockNumber;
113    type Error = Error;
114    type OutputError = OutputError;
115
116    fn contains(program_id: &Self::Key1, message_id: &Self::Key2) -> bool {
117        T::contains_keys(program_id, message_id)
118    }
119
120    fn insert(
121        message: Self::Value,
122        scheduled_at: Self::BlockNumber,
123    ) -> Result<(), Self::OutputError> {
124        let (key1, key2) = KeyGen::key_for(&message);
125
126        if Self::contains(&key1, &key2) {
127            return Err(Self::Error::duplicate_key().into());
128        }
129
130        let block_number = Callbacks::GetBlockNumber::call();
131        let message_with_bn = (
132            message,
133            Interval {
134                start: block_number,
135                finish: scheduled_at,
136            },
137        );
138
139        Callbacks::OnInsert::call(&message_with_bn);
140        T::insert(key1, key2, message_with_bn);
141        Ok(())
142    }
143
144    fn remove(
145        program_id: Self::Key1,
146        message_id: Self::Key2,
147    ) -> Result<ValueWithInterval<Self::Value, Self::BlockNumber>, Self::OutputError> {
148        if let Some(message_with_bn) = T::take(program_id, message_id) {
149            Callbacks::OnRemove::call(&message_with_bn);
150            Ok(message_with_bn)
151        } else {
152            Err(Self::Error::element_not_found().into())
153        }
154    }
155
156    fn clear() {
157        T::clear()
158    }
159}
160
161// Implementation of `CountedByKey` trait for `WaitlistImpl` in case,
162// when inner `DoubleMapStorage` implements `CountedByKey`.
163impl<T, Value, BlockNumber, Error, OutputError, Callbacks, KeyGen> CountedByKey
164    for WaitlistImpl<T, Value, BlockNumber, Error, OutputError, Callbacks, KeyGen>
165where
166    T: DoubleMapStorage<Value = (Value, Interval<BlockNumber>)> + CountedByKey<Key = T::Key1>,
167    Error: WaitlistError,
168    OutputError: From<Error>,
169    Callbacks: WaitlistCallbacks<Value = Value, BlockNumber = BlockNumber>,
170    KeyGen: KeyFor<Key = (T::Key1, T::Key2), Value = Value>,
171{
172    type Key = T::Key1;
173    type Length = T::Length;
174
175    fn len(key: &Self::Key) -> Self::Length {
176        T::len(key)
177    }
178}
179
180// Implementation of `IterableByKeyMap` trait for `WaitlistImpl` in case,
181// when inner `DoubleMapStorage` implements `IterableByKeyMap`.
182impl<T, Value, BlockNumber, Error, OutputError, Callbacks, KeyGen> IterableByKeyMap<T::Value>
183    for WaitlistImpl<T, Value, BlockNumber, Error, OutputError, Callbacks, KeyGen>
184where
185    T: DoubleMapStorage<Value = (Value, Interval<BlockNumber>)>
186        + IterableByKeyMap<T::Value, Key = T::Key1>,
187    Error: WaitlistError,
188    OutputError: From<Error>,
189    Callbacks: WaitlistCallbacks<Value = Value, BlockNumber = BlockNumber>,
190    KeyGen: KeyFor<Key = (T::Key1, T::Key2), Value = Value>,
191{
192    type Key = T::Key1;
193    type DrainIter = T::DrainIter;
194    type Iter = T::Iter;
195
196    fn drain_key(key: Self::Key) -> Self::DrainIter {
197        T::drain_key(key)
198    }
199
200    fn iter_key(key: Self::Key) -> Self::Iter {
201        T::iter_key(key)
202    }
203}
204
205// Implementation of `IterableMap` trait for `WaitlistImpl` in case,
206// when inner `DoubleMapStorage` implements `IterableMap`.
207impl<T, Value, BlockNumber, Error, OutputError, Callbacks, KeyGen> IterableMap<T::Value>
208    for WaitlistImpl<T, Value, BlockNumber, Error, OutputError, Callbacks, KeyGen>
209where
210    T: DoubleMapStorage<Value = (Value, Interval<BlockNumber>)> + IterableMap<T::Value>,
211    Error: WaitlistError,
212    OutputError: From<Error>,
213    Callbacks: WaitlistCallbacks<Value = Value, BlockNumber = BlockNumber>,
214    KeyGen: KeyFor<Key = (T::Key1, T::Key2), Value = Value>,
215{
216    type DrainIter = T::DrainIter;
217    type Iter = T::Iter;
218
219    fn drain() -> Self::DrainIter {
220        T::drain()
221    }
222
223    fn iter() -> Self::Iter {
224        T::iter()
225    }
226}