mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 07:01:03 +00:00
Result<Option<>> rather than Option<Option<>> (#9119)
* Clearer API to code against.
This commit is contained in:
@@ -29,7 +29,10 @@ use sp_npos_elections::{
|
||||
CompactSolution, ElectionResult, assignment_ratio_to_staked_normalized,
|
||||
assignment_staked_to_ratio_normalized, is_score_better, seq_phragmen,
|
||||
};
|
||||
use sp_runtime::{offchain::storage::StorageValueRef, traits::TrailingZeroInput, SaturatedConversion};
|
||||
use sp_runtime::{
|
||||
offchain::storage::{MutateStorageError, StorageValueRef},
|
||||
traits::TrailingZeroInput, SaturatedConversion
|
||||
};
|
||||
use sp_std::{cmp::Ordering, convert::TryFrom, vec::Vec};
|
||||
|
||||
/// Storage key used to store the last block number at which offchain worker ran.
|
||||
@@ -98,9 +101,9 @@ fn save_solution<T: Config>(call: &Call<T>) -> Result<(), MinerError> {
|
||||
log!(debug, "saving a call to the offchain storage.");
|
||||
let storage = StorageValueRef::persistent(&OFFCHAIN_CACHED_CALL);
|
||||
match storage.mutate::<_, (), _>(|_| Ok(call.clone())) {
|
||||
Ok(Ok(_)) => Ok(()),
|
||||
Ok(Err(_)) => Err(MinerError::FailedToStoreSolution),
|
||||
Err(_) => {
|
||||
Ok(_) => Ok(()),
|
||||
Err(MutateStorageError::ConcurrentModification(_)) => Err(MinerError::FailedToStoreSolution),
|
||||
Err(MutateStorageError::ValueFunctionFailed(_)) => {
|
||||
// this branch should be unreachable according to the definition of
|
||||
// `StorageValueRef::mutate`: that function should only ever `Err` if the closure we
|
||||
// pass it returns an error. however, for safety in case the definition changes, we do
|
||||
@@ -114,6 +117,7 @@ fn save_solution<T: Config>(call: &Call<T>) -> Result<(), MinerError> {
|
||||
fn restore_solution<T: Config>() -> Result<Call<T>, MinerError> {
|
||||
StorageValueRef::persistent(&OFFCHAIN_CACHED_CALL)
|
||||
.get()
|
||||
.ok()
|
||||
.flatten()
|
||||
.ok_or(MinerError::NoStoredSolution)
|
||||
}
|
||||
@@ -135,12 +139,9 @@ fn clear_offchain_repeat_frequency() {
|
||||
}
|
||||
|
||||
/// `true` when OCW storage contains a solution
|
||||
///
|
||||
/// More precise than `restore_solution::<T>().is_ok()`; that invocation will return `false`
|
||||
/// if a solution exists but cannot be decoded, whereas this just checks whether an item is present.
|
||||
#[cfg(test)]
|
||||
fn ocw_solution_exists<T: Config>() -> bool {
|
||||
StorageValueRef::persistent(&OFFCHAIN_CACHED_CALL).get::<Call<T>>().is_some()
|
||||
matches!(StorageValueRef::persistent(&OFFCHAIN_CACHED_CALL).get::<Call<T>>(), Ok(Some(_)))
|
||||
}
|
||||
|
||||
impl<T: Config> Pallet<T> {
|
||||
@@ -584,13 +585,13 @@ impl<T: Config> Pallet<T> {
|
||||
let last_block = StorageValueRef::persistent(&OFFCHAIN_LAST_BLOCK);
|
||||
|
||||
let mutate_stat = last_block.mutate::<_, &'static str, _>(
|
||||
|maybe_head: Option<Option<T::BlockNumber>>| {
|
||||
|maybe_head: Result<Option<T::BlockNumber>, _>| {
|
||||
match maybe_head {
|
||||
Some(Some(head)) if now < head => Err("fork."),
|
||||
Some(Some(head)) if now >= head && now <= head + threshold => {
|
||||
Ok(Some(head)) if now < head => Err("fork."),
|
||||
Ok(Some(head)) if now >= head && now <= head + threshold => {
|
||||
Err("recently executed.")
|
||||
}
|
||||
Some(Some(head)) if now > head + threshold => {
|
||||
Ok(Some(head)) if now > head + threshold => {
|
||||
// we can run again now. Write the new head.
|
||||
Ok(now)
|
||||
}
|
||||
@@ -604,11 +605,12 @@ impl<T: Config> Pallet<T> {
|
||||
|
||||
match mutate_stat {
|
||||
// all good
|
||||
Ok(Ok(_)) => Ok(()),
|
||||
Ok(_) => Ok(()),
|
||||
// failed to write.
|
||||
Ok(Err(_)) => Err(MinerError::Lock("failed to write to offchain db.")),
|
||||
Err(MutateStorageError::ConcurrentModification(_)) =>
|
||||
Err(MinerError::Lock("failed to write to offchain db (concurrent modification).")),
|
||||
// fork etc.
|
||||
Err(why) => Err(MinerError::Lock(why)),
|
||||
Err(MutateStorageError::ValueFunctionFailed(why)) => Err(MinerError::Lock(why)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1117,15 +1119,15 @@ mod tests {
|
||||
assert!(MultiPhase::current_phase().is_unsigned());
|
||||
|
||||
// initially, the lock is not set.
|
||||
assert!(guard.get::<bool>().is_none());
|
||||
assert!(guard.get::<bool>().unwrap().is_none());
|
||||
|
||||
// a successful a-z execution.
|
||||
MultiPhase::offchain_worker(25);
|
||||
assert_eq!(pool.read().transactions.len(), 1);
|
||||
|
||||
// afterwards, the lock is not set either..
|
||||
assert!(guard.get::<bool>().is_none());
|
||||
assert_eq!(last_block.get::<BlockNumber>().unwrap().unwrap(), 25);
|
||||
assert!(guard.get::<bool>().unwrap().is_none());
|
||||
assert_eq!(last_block.get::<BlockNumber>().unwrap(), Some(25));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1280,7 +1282,7 @@ mod tests {
|
||||
// this ensures that when the resubmit window rolls around, we're ready to regenerate
|
||||
// from scratch if necessary
|
||||
let mut call_cache = StorageValueRef::persistent(&OFFCHAIN_CACHED_CALL);
|
||||
assert!(matches!(call_cache.get::<Call<Runtime>>(), Some(Some(_call))));
|
||||
assert!(matches!(call_cache.get::<Call<Runtime>>(), Ok(Some(_call))));
|
||||
call_cache.clear();
|
||||
|
||||
// attempts to resubmit the tx after the threshold has expired
|
||||
|
||||
Reference in New Issue
Block a user