use std::sync::Arc;
use sc_client_api::{Backend, ChildInfo, StorageKey, StorageProvider};
use sp_runtime::traits::Block as BlockT;
use crate::common::{
events::{ArchiveStorageResult, PaginatedStorageQuery, StorageQueryType},
storage::{IterQueryType, QueryIter, Storage},
};
pub struct ArchiveStorage<Client, Block, BE> {
client: Storage<Client, Block, BE>,
storage_max_descendant_responses: usize,
storage_max_queried_items: usize,
}
impl<Client, Block, BE> ArchiveStorage<Client, Block, BE> {
pub fn new(
client: Arc<Client>,
storage_max_descendant_responses: usize,
storage_max_queried_items: usize,
) -> Self {
Self {
client: Storage::new(client),
storage_max_descendant_responses,
storage_max_queried_items,
}
}
}
impl<Client, Block, BE> ArchiveStorage<Client, Block, BE>
where
Block: BlockT + 'static,
BE: Backend<Block> + 'static,
Client: StorageProvider<Block, BE> + 'static,
{
pub fn handle_query(
&self,
hash: Block::Hash,
mut items: Vec<PaginatedStorageQuery<StorageKey>>,
child_key: Option<ChildInfo>,
) -> ArchiveStorageResult {
let discarded_items = items.len().saturating_sub(self.storage_max_queried_items);
items.truncate(self.storage_max_queried_items);
let mut storage_results = Vec::with_capacity(items.len());
for item in items {
match item.query_type {
StorageQueryType::Value => {
match self.client.query_value(hash, &item.key, child_key.as_ref()) {
Ok(Some(value)) => storage_results.push(value),
Ok(None) => continue,
Err(error) => return ArchiveStorageResult::err(error),
}
},
StorageQueryType::Hash =>
match self.client.query_hash(hash, &item.key, child_key.as_ref()) {
Ok(Some(value)) => storage_results.push(value),
Ok(None) => continue,
Err(error) => return ArchiveStorageResult::err(error),
},
StorageQueryType::ClosestDescendantMerkleValue =>
match self.client.query_merkle_value(hash, &item.key, child_key.as_ref()) {
Ok(Some(value)) => storage_results.push(value),
Ok(None) => continue,
Err(error) => return ArchiveStorageResult::err(error),
},
StorageQueryType::DescendantsValues => {
match self.client.query_iter_pagination(
QueryIter {
query_key: item.key,
ty: IterQueryType::Value,
pagination_start_key: item.pagination_start_key,
},
hash,
child_key.as_ref(),
self.storage_max_descendant_responses,
) {
Ok((results, _)) => storage_results.extend(results),
Err(error) => return ArchiveStorageResult::err(error),
}
},
StorageQueryType::DescendantsHashes => {
match self.client.query_iter_pagination(
QueryIter {
query_key: item.key,
ty: IterQueryType::Hash,
pagination_start_key: item.pagination_start_key,
},
hash,
child_key.as_ref(),
self.storage_max_descendant_responses,
) {
Ok((results, _)) => storage_results.extend(results),
Err(error) => return ArchiveStorageResult::err(error),
}
},
};
}
ArchiveStorageResult::ok(storage_results, discarded_items)
}
}