Skip to content

Commit

Permalink
Prepare the GraphQL service for the switching to async methods (#2334)
Browse files Browse the repository at this point in the history
To avoid blocking all threads with heavy sync requests to the database,
we decided to move the main database lookups to a separate thread pool.

After we introduced `ReadView` in the GraphQL service, we duplicated all
ports for this type to avoid breaking many places in the codebase(plus
simplifying the review process of the change that caused the creation of
`ReadView`). But after adding the `ReadView` type, we don't need ports
on this type anymore since it is an internal database wrapper type of
the GraphQL service, and it has full control over how it works. So, it
was an old tech debt to remove the usage of ports. The time is come. To
simplify the introduction of the `async` and not affect ports with it,
this PR decouples ports and `ReadView`.

This PR prepares the switching from `sync` to `async` logic(it will be a
follow-up PR).

### Before requesting review
- [x] I have reviewed the code myself
  • Loading branch information
xgreenx authored Oct 14, 2024
1 parent 03a3554 commit f37f73d
Show file tree
Hide file tree
Showing 29 changed files with 151 additions and 419 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

### Changed

- [2334](https://github.com/FuelLabs/fuel-core/pull/2334): Prepare the GraphQL service for the switching to `async` methods.

## [Version 0.39.0]

### Added
Expand Down
2 changes: 0 additions & 2 deletions crates/fuel-core/src/coins_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1002,7 +1002,6 @@ mod tests {
}

pub fn owned_coins(&self, owner: &Address) -> Vec<Coin> {
use crate::query::CoinQueryData;
let query = self.service_database();
let query = query.test_view();
query
Expand All @@ -1013,7 +1012,6 @@ mod tests {
}

pub fn owned_messages(&self, owner: &Address) -> Vec<Message> {
use crate::query::MessageQueryData;
let query = self.service_database();
let query = query.test_view();
query
Expand Down
114 changes: 42 additions & 72 deletions crates/fuel-core/src/graphql_api/database.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
use crate::fuel_core_graphql_api::{
database::arc_wrapper::ArcWrapper,
ports::{
DatabaseBlocks,
DatabaseChain,
DatabaseContracts,
DatabaseMessageProof,
DatabaseMessages,
DatabaseRelayedTransactions,
OffChainDatabase,
OnChainDatabase,
},
Expand Down Expand Up @@ -72,8 +66,6 @@ use std::{
sync::Arc,
};

use super::ports::DatabaseDaCompressedBlocks;

mod arc_wrapper;

/// The on-chain view of the database used by the [`ReadView`] to fetch on-chain data.
Expand Down Expand Up @@ -132,13 +124,13 @@ impl ReadDatabase {

#[derive(Clone)]
pub struct ReadView {
genesis_height: BlockHeight,
on_chain: OnChainView,
off_chain: OffChainView,
pub(crate) genesis_height: BlockHeight,
pub(crate) on_chain: OnChainView,
pub(crate) off_chain: OffChainView,
}

impl DatabaseBlocks for ReadView {
fn transaction(&self, tx_id: &TxId) -> StorageResult<Transaction> {
impl ReadView {
pub fn transaction(&self, tx_id: &TxId) -> StorageResult<Transaction> {
let result = self.on_chain.transaction(tx_id);
if result.is_not_found() {
if let Some(tx) = self.old_transaction(tx_id)? {
Expand All @@ -151,15 +143,15 @@ impl DatabaseBlocks for ReadView {
}
}

fn block(&self, height: &BlockHeight) -> StorageResult<CompressedBlock> {
pub fn block(&self, height: &BlockHeight) -> StorageResult<CompressedBlock> {
if *height >= self.genesis_height {
self.on_chain.block(height)
} else {
self.off_chain.old_block(height)
}
}

fn blocks(
pub fn blocks(
&self,
height: Option<BlockHeight>,
direction: IterDirection,
Expand Down Expand Up @@ -202,11 +194,11 @@ impl DatabaseBlocks for ReadView {
}
}

fn latest_height(&self) -> StorageResult<BlockHeight> {
pub fn latest_height(&self) -> StorageResult<BlockHeight> {
self.on_chain.latest_height()
}

fn consensus(&self, id: &BlockHeight) -> StorageResult<Consensus> {
pub fn consensus(&self, id: &BlockHeight) -> StorageResult<Consensus> {
if *id >= self.genesis_height {
self.on_chain.consensus(id)
} else {
Expand All @@ -215,45 +207,34 @@ impl DatabaseBlocks for ReadView {
}
}

impl DatabaseDaCompressedBlocks for ReadView {
fn da_compressed_block(&self, id: &BlockHeight) -> StorageResult<Vec<u8>> {
self.off_chain.da_compressed_block(id)
}

fn latest_height(&self) -> StorageResult<BlockHeight> {
self.on_chain.latest_height()
}
}

impl<M> StorageInspect<M> for ReadView
where
M: Mappable,
dyn OnChainDatabase: StorageInspect<M, Error = StorageError>,
{
impl StorageInspect<BlobData> for ReadView {
type Error = StorageError;

fn get(&self, key: &M::Key) -> StorageResult<Option<Cow<M::OwnedValue>>> {
self.on_chain.get(key)
fn get(
&self,
key: &<BlobData as Mappable>::Key,
) -> StorageResult<Option<Cow<<BlobData as Mappable>::OwnedValue>>> {
StorageInspect::<BlobData>::get(self.on_chain.as_ref(), key)
}

fn contains_key(&self, key: &M::Key) -> StorageResult<bool> {
self.on_chain.contains_key(key)
fn contains_key(&self, key: &<BlobData as Mappable>::Key) -> StorageResult<bool> {
StorageInspect::<BlobData>::contains_key(self.on_chain.as_ref(), key)
}
}

impl StorageSize<BlobData> for ReadView {
fn size_of_value(&self, key: &BlobId) -> Result<Option<usize>, Self::Error> {
self.on_chain.size_of_value(key)
StorageSize::<BlobData>::size_of_value(self.on_chain.as_ref(), key)
}
}

impl StorageRead<BlobData> for ReadView {
fn read(&self, key: &BlobId, buf: &mut [u8]) -> Result<Option<usize>, Self::Error> {
self.on_chain.read(key, buf)
StorageRead::<BlobData>::read(self.on_chain.as_ref(), key, buf)
}

fn read_alloc(&self, key: &BlobId) -> Result<Option<Vec<u8>>, Self::Error> {
self.on_chain.read_alloc(key)
StorageRead::<BlobData>::read_alloc(self.on_chain.as_ref(), key)
}
}

Expand All @@ -263,32 +244,27 @@ impl PredicateStorageRequirements for ReadView {
}
}

impl DatabaseMessages for ReadView {
fn all_messages(
impl ReadView {
pub fn all_messages(
&self,
start_message_id: Option<Nonce>,
direction: IterDirection,
) -> BoxedIter<'_, StorageResult<Message>> {
self.on_chain.all_messages(start_message_id, direction)
}

fn message_exists(&self, nonce: &Nonce) -> StorageResult<bool> {
pub fn message_exists(&self, nonce: &Nonce) -> StorageResult<bool> {
self.on_chain.message_exists(nonce)
}
}

impl DatabaseRelayedTransactions for ReadView {
fn transaction_status(
pub fn relayed_transaction_status(
&self,
id: Bytes32,
) -> StorageResult<Option<RelayedTransactionStatus>> {
let maybe_status = self.off_chain.relayed_tx_status(id)?;
Ok(maybe_status)
self.off_chain.relayed_tx_status(id)
}
}

impl DatabaseContracts for ReadView {
fn contract_balances(
pub fn contract_balances(
&self,
contract: ContractId,
start_asset: Option<AssetId>,
Expand All @@ -297,16 +273,12 @@ impl DatabaseContracts for ReadView {
self.on_chain
.contract_balances(contract, start_asset, direction)
}
}

impl DatabaseChain for ReadView {
fn da_height(&self) -> StorageResult<DaBlockHeight> {
pub fn da_height(&self) -> StorageResult<DaBlockHeight> {
self.on_chain.da_height()
}
}

impl DatabaseMessageProof for ReadView {
fn block_history_proof(
pub fn block_history_proof(
&self,
message_block_height: &BlockHeight,
commit_block_height: &BlockHeight,
Expand All @@ -316,22 +288,20 @@ impl DatabaseMessageProof for ReadView {
}
}

impl OnChainDatabase for ReadView {}

impl OffChainDatabase for ReadView {
fn block_height(&self, block_id: &BlockId) -> StorageResult<BlockHeight> {
impl ReadView {
pub fn block_height(&self, block_id: &BlockId) -> StorageResult<BlockHeight> {
self.off_chain.block_height(block_id)
}

fn da_compressed_block(&self, height: &BlockHeight) -> StorageResult<Vec<u8>> {
pub fn da_compressed_block(&self, height: &BlockHeight) -> StorageResult<Vec<u8>> {
self.off_chain.da_compressed_block(height)
}

fn tx_status(&self, tx_id: &TxId) -> StorageResult<TransactionStatus> {
pub fn tx_status(&self, tx_id: &TxId) -> StorageResult<TransactionStatus> {
self.off_chain.tx_status(tx_id)
}

fn owned_coins_ids(
pub fn owned_coins_ids(
&self,
owner: &Address,
start_coin: Option<UtxoId>,
Expand All @@ -340,7 +310,7 @@ impl OffChainDatabase for ReadView {
self.off_chain.owned_coins_ids(owner, start_coin, direction)
}

fn owned_message_ids(
pub fn owned_message_ids(
&self,
owner: &Address,
start_message_id: Option<Nonce>,
Expand All @@ -350,7 +320,7 @@ impl OffChainDatabase for ReadView {
.owned_message_ids(owner, start_message_id, direction)
}

fn owned_transactions_ids(
pub fn owned_transactions_ids(
&self,
owner: Address,
start: Option<TxPointer>,
Expand All @@ -360,41 +330,41 @@ impl OffChainDatabase for ReadView {
.owned_transactions_ids(owner, start, direction)
}

fn contract_salt(&self, contract_id: &ContractId) -> StorageResult<Salt> {
pub fn contract_salt(&self, contract_id: &ContractId) -> StorageResult<Salt> {
self.off_chain.contract_salt(contract_id)
}

fn old_block(&self, height: &BlockHeight) -> StorageResult<CompressedBlock> {
pub fn old_block(&self, height: &BlockHeight) -> StorageResult<CompressedBlock> {
self.off_chain.old_block(height)
}

fn old_blocks(
pub fn old_blocks(
&self,
height: Option<BlockHeight>,
direction: IterDirection,
) -> BoxedIter<'_, StorageResult<CompressedBlock>> {
self.off_chain.old_blocks(height, direction)
}

fn old_block_consensus(&self, height: &BlockHeight) -> StorageResult<Consensus> {
pub fn old_block_consensus(&self, height: &BlockHeight) -> StorageResult<Consensus> {
self.off_chain.old_block_consensus(height)
}

fn old_transaction(
pub fn old_transaction(
&self,
id: &TxId,
) -> StorageResult<Option<fuel_core_types::fuel_tx::Transaction>> {
self.off_chain.old_transaction(id)
}

fn relayed_tx_status(
pub fn relayed_tx_status(
&self,
id: Bytes32,
) -> StorageResult<Option<RelayedTransactionStatus>> {
self.off_chain.relayed_tx_status(id)
}

fn message_is_spent(&self, nonce: &Nonce) -> StorageResult<bool> {
pub fn message_is_spent(&self, nonce: &Nonce) -> StorageResult<bool> {
self.off_chain.message_is_spent(nonce)
}
}
8 changes: 0 additions & 8 deletions crates/fuel-core/src/query.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
mod balance;
mod blob;
mod block;
mod chain;
mod coin;
mod contract;
mod message;
Expand All @@ -13,12 +12,5 @@ pub mod da_compressed;

// TODO: Remove reexporting of everything
pub use balance::*;
pub use blob::*;
pub use block::*;
pub use chain::*;
pub use coin::*;
pub use contract::*;
pub use message::*;
pub(crate) use subscriptions::*;
pub use tx::*;
pub use upgrades::*;
22 changes: 3 additions & 19 deletions crates/fuel-core/src/query/balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,8 @@ use std::{

pub mod asset_query;

pub trait BalanceQueryData: Send + Sync {
fn balance(
&self,
owner: Address,
asset_id: AssetId,
base_asset_id: AssetId,
) -> StorageResult<AddressBalance>;

fn balances(
&self,
owner: Address,
direction: IterDirection,
base_asset_id: AssetId,
) -> BoxedIter<StorageResult<AddressBalance>>;
}

impl BalanceQueryData for ReadView {
fn balance(
impl ReadView {
pub fn balance(
&self,
owner: Address,
asset_id: AssetId,
Expand Down Expand Up @@ -75,7 +59,7 @@ impl BalanceQueryData for ReadView {
})
}

fn balances(
pub fn balances(
&self,
owner: Address,
direction: IterDirection,
Expand Down
8 changes: 1 addition & 7 deletions crates/fuel-core/src/query/balance/asset_query.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
use crate::{
graphql_api::database::ReadView,
query::{
CoinQueryData,
MessageQueryData,
},
};
use crate::graphql_api::database::ReadView;
use fuel_core_storage::{
iter::IterDirection,
Error as StorageError,
Expand Down
Loading

0 comments on commit f37f73d

Please sign in to comment.