Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposals to multi get PR #2419

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions crates/fuel-core/src/graphql_api/ports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ use fuel_core_storage::{
},
Error as StorageError,
Result as StorageResult,
StorageBatchInspect,
StorageInspect,
StorageRead,
};
Expand Down Expand Up @@ -174,9 +173,7 @@ pub trait DatabaseDaCompressedBlocks {
}

/// Trait that specifies all the getters required for messages.
pub trait DatabaseMessages:
StorageInspect<Messages, Error = StorageError> + StorageBatchInspect<Messages>
{
pub trait DatabaseMessages: StorageInspect<Messages, Error = StorageError> {
fn all_messages(
&self,
start_message_id: Option<Nonce>,
Expand All @@ -199,10 +196,9 @@ pub trait DatabaseRelayedTransactions {
}

/// Trait that specifies all the getters required for coins
pub trait DatabaseCoins:
StorageInspect<Coins, Error = StorageError> + StorageBatchInspect<Coins>
{
pub trait DatabaseCoins: StorageInspect<Coins, Error = StorageError> {
fn coin(&self, utxo_id: UtxoId) -> StorageResult<Coin>;

fn coins<'a>(
&'a self,
utxo_ids: BoxedIter<'a, &'a UtxoId>,
Expand Down
10 changes: 7 additions & 3 deletions crates/fuel-core/src/state/generic_database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,14 @@ where
M: Mappable,
StructuredStorage<Storage>: StorageBatchInspect<M>,
{
fn get_batch<'a>(
fn get_batch<'a, Iter>(
&'a self,
keys: BoxedIter<'a, &'a M::Key>,
) -> BoxedIter<'a, StorageResult<Option<<M as Mappable>::OwnedValue>>> {
keys: Iter,
) -> impl Iterator<Item = fuel_core_storage::Result<Option<M::OwnedValue>>> + 'a
where
Iter: 'a + Iterator<Item = &'a M::Key> + Send,
M::Key: 'a,
{
self.storage.get_batch(keys)
}
}
Expand Down
18 changes: 18 additions & 0 deletions crates/fuel-core/src/state/historical_rocksdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@ use crate::{
use fuel_core_storage::{
iter::{
BoxedIter,
IntoBoxedIter,
IterDirection,
IterableStore,
IteratorOverTable,
},
kv_store::{
KVItem,
KeyValueInspect,
StorageColumn,
Value,
WriteOperation,
},
Expand All @@ -56,6 +58,7 @@ use serde::{
Serialize,
};
use std::{
borrow::Cow,
num::NonZeroU64,
path::Path,
};
Expand Down Expand Up @@ -395,6 +398,21 @@ where
self.db.get(key, Column::OriginalColumn(column))
}

fn get_batch<'a>(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding this implementation as well.

&'a self,
keys: BoxedIter<'a, Cow<'a, [u8]>>,
column: Self::Column,
) -> BoxedIter<'a, StorageResult<Option<Value>>> {
self.db
.multi_get(Column::<Description>::OriginalColumn(column).id(), keys)
.map(|result| {
result
.map(|value| value.map(Into::into))
.map_err(Into::into)
})
.into_boxed()
}

fn read(
&self,
key: &[u8],
Expand Down
30 changes: 13 additions & 17 deletions crates/storage/src/blueprint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ use crate::{
Encode,
Encoder,
},
iter::{
BoxedIter,
IntoBoxedIter,
},
iter::IntoBoxedIter,
kv_store::{
BatchOperations,
KeyValueInspect,
Expand Down Expand Up @@ -81,30 +78,29 @@ where
}

/// Returns multiple values from the storage.
fn get_batch<'a>(
fn get_batch<'a, Iter>(
storage: &'a S,
keys: BoxedIter<'a, &'a M::Key>,
keys: Iter,
column: S::Column,
) -> BoxedIter<'a, StorageResult<Option<M::OwnedValue>>>
) -> impl Iterator<Item = crate::Result<Option<M::OwnedValue>>> + 'a
where
Iter: 'a + Iterator<Item = &'a M::Key> + Send,
M::Key: 'a,
Self::KeyCodec: 'a,
{
let keys = keys
.map(|key| Self::KeyCodec::encode(key).into_bytes())
.into_boxed();

storage
.get_batch(keys, column)
.map(|result| {
result.and_then(|opt| {
opt.map(|value| {
Self::ValueCodec::decode_from_value(value)
.map_err(crate::Error::Codec)
})
.transpose()
storage.get_batch(keys, column).map(|result| {
result.and_then(|opt| {
opt.map(|value| {
Self::ValueCodec::decode_from_value(value)
.map_err(crate::Error::Codec)
})
.transpose()
})
.into_boxed()
})
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/storage/src/codec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub trait Encode<T: ?Sized> {
T: 'a;

/// Encodes the object to the bytes and passes it to the `Encoder`.
fn encode<'a>(t: &'a T) -> Self::Encoder<'a>;
fn encode(t: &T) -> Self::Encoder<'_>;

/// Returns the serialized object as an [`Value`].
fn encode_as_value(t: &T) -> Value {
Expand Down
16 changes: 11 additions & 5 deletions crates/storage/src/kv_store.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
//! The module provides plain abstract definition of the key-value store.

use crate::{
iter::{
BoxedIter,
IntoBoxedIter,
},
iter::BoxedIter,
Error as StorageError,
Result as StorageResult,
};
Expand All @@ -17,6 +14,7 @@ use alloc::{
vec::Vec,
};

use crate::iter::IntoBoxedIter;
#[cfg(feature = "std")]
use core::ops::Deref;

Expand All @@ -31,7 +29,7 @@ pub type KVItem = StorageResult<(Key, Value)>;
pub type KeyItem = StorageResult<Key>;

/// A column of the storage.
pub trait StorageColumn: Copy + core::fmt::Debug + Send + Sync {
pub trait StorageColumn: Copy + core::fmt::Debug + Send + Sync + 'static {
/// Returns the name of the column.
fn name(&self) -> String;

Expand Down Expand Up @@ -121,6 +119,14 @@ where
self.deref().get(key, column)
}

fn get_batch<'a>(
&'a self,
keys: BoxedIter<'a, Cow<'a, [u8]>>,
column: Self::Column,
) -> BoxedIter<'a, StorageResult<Option<Value>>> {
self.deref().get_batch(keys, column)
}

fn read(
&self,
key: &[u8],
Expand Down
10 changes: 6 additions & 4 deletions crates/storage/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ extern crate alloc;
use anyhow::anyhow;
use core::array::TryFromSliceError;
use fuel_core_types::services::executor::Error as ExecutorError;
use iter::BoxedIter;

#[cfg(feature = "alloc")]
use alloc::{
Expand Down Expand Up @@ -182,10 +181,13 @@ pub trait StorageBatchMutate<Type: Mappable>: StorageMutate<Type> {
/// getting values one by one.
pub trait StorageBatchInspect<Type: Mappable> {
/// Get a batch of values associated with the provided keys.
fn get_batch<'a>(
fn get_batch<'a, Iter>(
&'a self,
keys: BoxedIter<'a, &'a Type::Key>,
) -> BoxedIter<'a, Result<Option<Type::OwnedValue>>>;
keys: Iter,
) -> impl Iterator<Item = Result<Option<Type::OwnedValue>>> + 'a
where
Iter: 'a + Iterator<Item = &'a Type::Key> + Send,
Type::Key: 'a;
}

/// Creates `StorageError::NotFound` error with file and line information inside.
Expand Down
10 changes: 7 additions & 3 deletions crates/storage/src/structured_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,10 +285,14 @@ where
M::Blueprint: BlueprintInspect<M, StructuredStorage<S>>,
<M::Blueprint as BlueprintInspect<M, StructuredStorage<S>>>::KeyCodec: 'static,
{
fn get_batch<'a>(
fn get_batch<'a, Iter>(
&'a self,
keys: BoxedIter<'a, &'a M::Key>,
) -> BoxedIter<'a, StorageResult<Option<M::OwnedValue>>> {
keys: Iter,
) -> impl Iterator<Item = crate::Result<Option<M::OwnedValue>>> + 'a
where
Iter: 'a + Iterator<Item = &'a M::Key> + Send,
M::Key: 'a,
{
M::Blueprint::get_batch(self, keys, M::column())
}
}
Expand Down
18 changes: 17 additions & 1 deletion crates/storage/src/transactional.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
//! The primitives to work with storage in transactional mode.

use crate::{
iter::{
BoxedIter,
IntoBoxedIter,
},
kv_store::{
BatchOperations,
KeyValueInspect,
Expand All @@ -14,6 +18,7 @@ use crate::{
};
use core::borrow::Borrow;

use alloc::borrow::Cow;
#[cfg(feature = "alloc")]
use alloc::{
boxed::Box,
Expand All @@ -27,7 +32,6 @@ use alloc::{
#[cfg(feature = "test-helpers")]
use crate::{
iter::{
BoxedIter,
IterDirection,
IterableStore,
},
Expand Down Expand Up @@ -384,6 +388,18 @@ where
}
}

fn get_batch<'a>(
&'a self,
keys: BoxedIter<'a, Cow<'a, [u8]>>,
column: Self::Column,
) -> BoxedIter<'a, StorageResult<Option<Value>>> {
if !self.changes.contains_key(&column.id()) {
return self.storage.get_batch(keys, column);
} else {
keys.map(move |key| self.get(&key, column)).into_boxed()
}
}

fn read(
&self,
key: &[u8],
Expand Down
Loading