Skip to content

Commit

Permalink
Ocean: Cleanup data acess (#2837)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jouzo authored Feb 27, 2024
1 parent dbb21cc commit 025640b
Show file tree
Hide file tree
Showing 10 changed files with 119 additions and 89 deletions.
5 changes: 3 additions & 2 deletions lib/ain-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ pub fn repository_derive(input: TokenStream) -> TokenStream {
// Generate the implementation
let expanded = quote! {
impl RepositoryOps<#key_type_ident, #value_type_ident> for #name {
type ListItem = std::result::Result<(#key_type_ident, #value_type_ident), ain_db::DBError>;

fn get(&self, id: &#key_type_ident) -> Result<Option<#value_type_ident>> {
Ok(self.col.get(id)?)
}
Expand All @@ -115,8 +117,7 @@ pub fn repository_derive(input: TokenStream) -> TokenStream {
Ok(self.col.delete(id)?)
}

fn list<'a>(&'a self, from: Option<#key_type_ident>, dir: crate::storage::SortOrder) -> crate::repository::ListResult<#key_type_ident, #value_type_ident>
{
fn list<'a>(&'a self, from: Option<#key_type_ident>, dir: crate::storage::SortOrder) -> Result<Box<dyn Iterator<Item = Self::ListItem> + 'a>> {
let it = self.col.iter(from, dir.into())?;
Ok(Box::new(it))
}
Expand Down
59 changes: 21 additions & 38 deletions lib/ain-ocean/src/api/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ use crate::{
api::common::Paginate,
error::{ApiError, Error},
model::{Block, BlockContext, Transaction},
repository::RepositoryOps,
repository::{
InitialKeyProvider, RepositoryOps, SecondaryIndex, TransactionByBlockHashRepository,
},
storage::SortOrder,
Result,
};
Expand Down Expand Up @@ -100,23 +102,11 @@ async fn list_blocks(
})
.transpose()?;

let blocks = ctx
.services
.block
.by_height
let repository = &ctx.services.block.by_height;
let blocks = repository
.list(next, SortOrder::Descending)?
.paginate(&query)
.map(|item| {
let (_, id) = item?;
let b = ctx
.services
.block
.by_id
.get(&id)?
.ok_or("Missing block index")?;

Ok(b)
})
.map(|e| repository.retrieve_primary_value(e))
.collect::<Result<Vec<_>>>()?;

Ok(ApiPagedResponse::of(blocks, query.size, |block| {
Expand Down Expand Up @@ -147,34 +137,27 @@ async fn get_transactions(
Query(query): Query<PaginationQuery>,
Extension(ctx): Extension<Arc<AppContext>>,
) -> Result<ApiPagedResponse<TransactionResponse>> {
let next = query.next.as_ref().map_or(Ok((hash, 0)), |q| {
let height = q
.parse::<usize>()
.map_err(|_| format_err!("Invalid height"))?;
Ok::<(BlockHash, usize), Error>((hash, height))
})?;

let txs = ctx
.services
.transaction
.by_block_hash
let repository = &ctx.services.transaction.by_block_hash;

let next = query.next.as_ref().map_or(
Ok(TransactionByBlockHashRepository::initial_key(hash)),
|q| {
let height = q
.parse::<usize>()
.map_err(|_| format_err!("Invalid height"))?;
Ok::<(BlockHash, usize), Error>((hash, height))
},
)?;

let txs = repository
.list(Some(next), SortOrder::Ascending)?
.paginate(&query)
.take_while(|item| match item {
Ok(((h, _), _)) => h == &hash,
_ => true,
})
.map(|item| {
let (_, id) = item?;
let tx = ctx
.services
.transaction
.by_id
.get(&id)?
.ok_or("Missing tx index")?;

Ok(tx.into())
})
.map(|el| repository.retrieve_primary_value(el))
.map(|v| v.map(TransactionResponse::from))
.collect::<Result<Vec<_>>>()?;

Ok(ApiPagedResponse::of(txs, query.size, |tx| tx.order))
Expand Down
21 changes: 5 additions & 16 deletions lib/ain-ocean/src/api/masternode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::{
api::common::Paginate,
error::{ApiError, Error, NotFoundKind},
model::Masternode,
repository::RepositoryOps,
repository::{RepositoryOps, SecondaryIndex},
storage::SortOrder,
Result,
};
Expand Down Expand Up @@ -105,6 +105,7 @@ async fn list_masternodes(
Query(query): Query<PaginationQuery>,
Extension(ctx): Extension<Arc<AppContext>>,
) -> Result<ApiPagedResponse<MasternodeData>> {
let repository = &ctx.services.masternode.by_height;
let next = query
.next
.as_ref()
Expand All @@ -120,23 +121,11 @@ async fn list_masternodes(
})
.transpose()?;

let masternodes = ctx
.services
.masternode
.by_height
let masternodes = repository
.list(next, SortOrder::Descending)?
.paginate(&query)
.map(|item| {
let ((_, id), _) = item?;
let mn = ctx
.services
.masternode
.by_id
.get(&id)?
.ok_or("Missing masternode index")?;

Ok(mn.into())
})
.map(|el| repository.retrieve_primary_value(el))
.map(|v| v.map(MasternodeData::from))
.collect::<Result<Vec<_>>>()?;

Ok(ApiPagedResponse::of(
Expand Down
28 changes: 8 additions & 20 deletions lib/ain-ocean/src/api/transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ use serde::Deserialize;

use super::{path::Path, query::PaginationQuery, response::ApiPagedResponse, AppContext};
use crate::{
api::common::Paginate,
api::response::Response,
api::{common::Paginate, response::Response},
error::ApiError,
model::{Transaction, TransactionVin, TransactionVout},
repository::RepositoryOps,
repository::{InitialKeyProvider, RepositoryOps, TransactionVinRepository},
storage::SortOrder,
Result,
};
Expand All @@ -37,7 +36,10 @@ async fn get_vins(
Query(query): Query<PaginationQuery>,
Extension(ctx): Extension<Arc<AppContext>>,
) -> Result<ApiPagedResponse<TransactionVin>> {
let next = query.next.clone().unwrap_or(format!("{}00", id));
let next = query
.next
.clone()
.unwrap_or(TransactionVinRepository::initial_key(id));

let list = ctx
.services
Expand All @@ -50,14 +52,7 @@ async fn get_vins(
_ => true,
})
.map(|item| {
let (id, _) = item?;
let v = ctx
.services
.transaction
.vin_by_id
.get(&id)?
.ok_or("Missing vin index")?;

let (_, v) = item?;
Ok(v)
})
.collect::<Result<Vec<_>>>()?;
Expand Down Expand Up @@ -85,14 +80,7 @@ async fn get_vouts(
_ => true,
})
.map(|item| {
let (id, _) = item?;
let v = ctx
.services
.transaction
.vout_by_id
.get(&id)?
.ok_or("Missing vout index")?;

let (_, v) = item?;
Ok(v)
})
.collect::<Result<Vec<_>>>()?;
Expand Down
2 changes: 2 additions & 0 deletions lib/ain-ocean/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ pub enum Error {
#[error("Unable to find {0:}")]
NotFound(NotFoundKind),
#[error("Decimal conversion error")]
SecondaryIndex,
#[error("Error fetching primary value")]
DecimalError,
#[error(transparent)]
Other(#[from] anyhow::Error),
Expand Down
17 changes: 15 additions & 2 deletions lib/ain-ocean/src/repository/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ use ain_db::LedgerColumn;
use ain_macros::Repository;
use bitcoin::BlockHash;

use super::RepositoryOps;
use super::{RepositoryOps, SecondaryIndex};
use crate::{
model::Block,
storage::{columns, ocean_store::OceanStore, SortOrder},
Result,
Error, Result,
};

#[derive(Repository)]
Expand Down Expand Up @@ -55,3 +55,16 @@ impl BlockByHeightRepository {
}
}
}

impl SecondaryIndex<u32, BlockHash> for BlockByHeightRepository {
type Value = Block;

fn retrieve_primary_value(&self, el: Self::ListItem) -> Result<Self::Value> {
let (_, id) = el?;

let col = self.store.column::<columns::Block>();
let tx = col.get(&id)?.ok_or(Error::SecondaryIndex)?;

Ok(tx)
}
}
15 changes: 13 additions & 2 deletions lib/ain-ocean/src/repository/masternode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ use ain_db::LedgerColumn;
use ain_macros::Repository;
use bitcoin::Txid;

use super::RepositoryOps;
use super::{RepositoryOps, SecondaryIndex};
use crate::{
model::Masternode,
storage::{columns, ocean_store::OceanStore},
Result,
Error, Result,
};

#[derive(Repository)]
Expand Down Expand Up @@ -44,3 +44,14 @@ impl MasternodeByHeightRepository {
}
}
}

impl SecondaryIndex<MasternodeByHeightKey, u8> for MasternodeByHeightRepository {
type Value = Masternode;

fn retrieve_primary_value(&self, el: Self::ListItem) -> Result<Self::Value> {
let ((_, id), _) = el?;
let col = self.store.column::<columns::Masternode>();
let tx = col.get(&id)?.ok_or(Error::SecondaryIndex)?;
Ok(tx)
}
}
20 changes: 16 additions & 4 deletions lib/ain-ocean/src/repository/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,24 @@ pub use transaction_vout::*;
pub use tx_result::*;
pub use vault_auction_batch_history::*;

pub type ListResult<'a, K, V> =
Result<Box<dyn Iterator<Item = std::result::Result<(K, V), ain_db::DBError>> + 'a>>;

pub trait RepositoryOps<K, V> {
type ListItem;
fn get(&self, key: &K) -> Result<Option<V>>;
fn put(&self, key: &K, value: &V) -> Result<()>;
fn delete(&self, key: &K) -> Result<()>;
fn list(&self, from: Option<K>, direction: SortOrder) -> ListResult<K, V>;
fn list<'a>(
&'a self,
from: Option<K>,
direction: SortOrder,
) -> Result<Box<dyn Iterator<Item = Self::ListItem> + 'a>>;
}

pub trait InitialKeyProvider<K, V>: RepositoryOps<K, V> {
type PartialKey;
fn initial_key(pk: Self::PartialKey) -> K;
}

pub trait SecondaryIndex<K, V>: RepositoryOps<K, V> {
type Value;
fn retrieve_primary_value(&self, el: Self::ListItem) -> Result<Self::Value>;
}
25 changes: 22 additions & 3 deletions lib/ain-ocean/src/repository/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ use std::sync::Arc;

use ain_db::LedgerColumn;
use ain_macros::Repository;
use bitcoin::Txid;
use bitcoin::{BlockHash, Txid};

use super::RepositoryOps;
use super::{InitialKeyProvider, RepositoryOps, SecondaryIndex};
use crate::{
model::{Transaction, TransactionByBlockHashKey},
storage::{columns, ocean_store::OceanStore},
Result,
Error, Result,
};

#[derive(Repository)]
Expand Down Expand Up @@ -42,3 +42,22 @@ impl TransactionByBlockHashRepository {
}
}
}

impl InitialKeyProvider<TransactionByBlockHashKey, Txid> for TransactionByBlockHashRepository {
type PartialKey = BlockHash;

fn initial_key(pk: Self::PartialKey) -> TransactionByBlockHashKey {
(pk, 0)
}
}

impl SecondaryIndex<TransactionByBlockHashKey, Txid> for TransactionByBlockHashRepository {
type Value = Transaction;

fn retrieve_primary_value(&self, el: Self::ListItem) -> Result<Self::Value> {
let (_, id) = el?;
let col = self.store.column::<columns::Transaction>();
let tx = col.get(&id)?.ok_or(Error::SecondaryIndex)?;
Ok(tx)
}
}
16 changes: 14 additions & 2 deletions lib/ain-ocean/src/repository/transaction_vin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@ use std::sync::Arc;

use ain_db::LedgerColumn;
use ain_macros::Repository;
use bitcoin::Txid;

use super::RepositoryOps;
use super::{InitialKeyProvider, RepositoryOps};
use crate::{
model::TransactionVin,
storage::{columns, ocean_store::OceanStore},
storage::{
columns::{self},
ocean_store::OceanStore,
},
Result,
};

Expand All @@ -25,3 +29,11 @@ impl TransactionVinRepository {
}
}
}

impl InitialKeyProvider<String, TransactionVin> for TransactionVinRepository {
type PartialKey = Txid;

fn initial_key(pk: Self::PartialKey) -> String {
format!("{}00", pk)
}
}

0 comments on commit 025640b

Please sign in to comment.