Skip to content
Snippets Groups Projects
Commit bbff027a authored by Éloïs's avatar Éloïs
Browse files

Merge branch 'ref/cm-to-global' into 'dev'

[feat] server: create global cache

See merge request !1366
parents 8fb9eca8 6ce60364
Branches
No related tags found
1 merge request!1366[feat] server: create global cache
Showing
with 313 additions and 308 deletions
......@@ -25,7 +25,6 @@ pub mod uds;
pub mod utxos_of_script;
use crate::*;
use duniter_dbs::databases::cm_v1::CmV1DbReadable as _;
#[derive(async_graphql::MergedObject, Default)]
pub struct QueryRoot(
......@@ -60,11 +59,15 @@ impl Node {
) -> async_graphql::Result<Option<PeerCardGva>> {
let data = ctx.data::<GvaSchemaData>()?;
Ok(data
.dbs_pool
.execute(move |dbs| dbs.cm_db.self_peer_old().get(&()))
.await??
.map(Into::into))
if let Some(self_peer_old) = data
.cm_accessor()
.get_self_peer_old(|self_peer_old| self_peer_old.clone())
.await
{
Ok(Some(PeerCardGva::from(self_peer_old)))
} else {
Ok(None)
}
}
/// Software
async fn software(&self) -> &'static str {
......
......@@ -92,7 +92,7 @@ mod tests {
})
.times(1)
.returning(|_| Ok(Some(SourceAmountValV2(SourceAmount::with_base0(38)))));
let schema = create_schema(dbs_reader)?;
let schema = create_schema(MockAsyncAccessor::new(), dbs_reader)?;
assert_eq!(
exec_graphql_request(
&schema,
......@@ -123,7 +123,7 @@ mod tests {
})
.times(1)
.returning(|_| Ok(Some(SourceAmountValV2(SourceAmount::with_base0(38)))));
let schema = create_schema(dbs_reader)?;
let schema = create_schema(MockAsyncAccessor::new(), dbs_reader)?;
assert_eq!(
exec_graphql_request(
&schema,
......
......@@ -83,7 +83,7 @@ mod tests {
.withf(|_, s| s.0 == 0)
.times(1)
.returning(|_, _| Ok(Some(BlockMetaV2::default())));
let schema = create_schema(dbs_reader)?;
let schema = create_schema(MockAsyncAccessor::new(), dbs_reader)?;
assert_eq!(
exec_graphql_request(&schema, r#"{ blockByNumber(number: 0) {number} }"#).await?,
serde_json::json!({
......@@ -112,7 +112,7 @@ mod tests {
has_previous_page: false,
})
});
let schema = create_schema(dbs_reader)?;
let schema = create_schema(MockAsyncAccessor::new(), dbs_reader)?;
assert_eq!(
exec_graphql_request(
&schema,
......
......@@ -23,37 +23,33 @@ impl CurrentBlockQuery {
async fn current_block(
&self,
ctx: &async_graphql::Context<'_>,
) -> async_graphql::Result<Block> {
) -> async_graphql::Result<BlockMeta> {
let data = ctx.data::<GvaSchemaData>()?;
let dbs_reader = data.dbs_reader();
data.dbs_pool
.execute(move |dbs| {
if let Some(current_block) = dbs_reader.get_current_block(&dbs.cm_db)? {
Ok(Block::from(&current_block))
if let Some(current_block_meta) = data
.cm_accessor()
.get_current_meta(|cm| cm.current_block_meta)
.await
{
Ok(current_block_meta.into())
} else {
Err(async_graphql::Error::new("no blockchain"))
}
})
.await?
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::tests::*;
use dubp::block::DubpBlockV10;
use duniter_dbs::databases::cm_v1::CmV1Db;
#[tokio::test]
async fn query_current_block() -> anyhow::Result<()> {
let mut dbs_reader = MockDbsReader::new();
dbs_reader
.expect_get_current_block::<CmV1Db<MemSingleton>>()
let mut mock_cm = MockAsyncAccessor::new();
mock_cm
.expect_get_current_meta::<duniter_dbs::BlockMetaV2>()
.times(1)
.returning(|_| Ok(Some(DubpBlockV10::default())));
let schema = create_schema(dbs_reader)?;
.returning(|f| Some(f(&CurrentMeta::default())));
let schema = create_schema(mock_cm, MockDbsReader::new())?;
assert_eq!(
exec_graphql_request(&schema, r#"{ currentBlock {nonce} }"#).await?,
serde_json::json!({
......
......@@ -27,13 +27,23 @@ impl CurrentFrameQuery {
let data = ctx.data::<GvaSchemaData>()?;
let dbs_reader = data.dbs_reader();
if let Some(current_block_meta) = data
.cm_accessor()
.get_current_meta(|cm| cm.current_block_meta)
.await
{
Ok(data
.dbs_pool
.execute(move |dbs| dbs_reader.get_current_frame(&dbs.bc_db_ro, &dbs.cm_db))
.execute(move |dbs| {
dbs_reader.get_current_frame(&dbs.bc_db_ro, &current_block_meta)
})
.await??
.into_iter()
.map(Into::into)
.collect())
} else {
Ok(vec![])
}
}
}
......@@ -42,21 +52,33 @@ mod tests {
use super::*;
use crate::tests::*;
use duniter_dbs::databases::bc_v2::BcV2DbRo;
use duniter_dbs::databases::cm_v1::CmV1Db;
use duniter_dbs::BlockMetaV2;
#[tokio::test]
async fn query_current_frame() -> anyhow::Result<()> {
let mut mock_cm = MockAsyncAccessor::new();
mock_cm
.expect_get_current_meta::<BlockMetaV2>()
.times(1)
.returning(|f| {
Some(f(&CurrentMeta {
current_block_meta: BlockMetaV2 {
issuers_frame: 1,
..Default::default()
},
..Default::default()
}))
});
let mut dbs_reader = MockDbsReader::new();
dbs_reader
.expect_get_current_frame::<BcV2DbRo<FileBackend>, CmV1Db<MemSingleton>>()
.expect_get_current_frame::<BcV2DbRo<FileBackend>>()
.times(1)
.returning(|_, _| {
Ok(vec![BlockMetaV2 {
..Default::default()
}])
});
let schema = create_schema(dbs_reader)?;
let schema = create_schema(mock_cm, dbs_reader)?;
assert_eq!(
exec_graphql_request(&schema, r#"{ currentFrame {nonce} }"#).await?,
serde_json::json!({
......
......@@ -42,7 +42,7 @@ impl FirstUtxosQuery {
let utxos_matrice: Vec<arrayvec::ArrayVec<_>> = data
.dbs_pool
.execute(move |_| db_reader.first_scripts_utxos(first as usize, &scripts))
.execute(move |_| db_reader.first_scripts_utxos(None, first as usize, &scripts))
.await??;
Ok(utxos_matrice
......
......@@ -113,36 +113,33 @@ impl GenTxsQuery {
let db_reader = data.dbs_reader();
let currency = data.server_meta_data.currency.clone();
let (current_block, (inputs, inputs_sum)) = data
if let Some(current_block_meta) = data
.cm_accessor
.get_current_meta(|cm| cm.current_block_meta)
.await
{
let (inputs, inputs_sum) = data
.dbs_pool
.execute(move |dbs| {
if let Some(current_block) = duniter_bc_reader::get_current_block_meta(&dbs.cm_db)?
{
Ok((
current_block,
db_reader.find_inputs(
&dbs.bc_db_ro,
&dbs.txs_mp_db,
SourceAmount::new(amount as i64, current_block.unit_base as i64),
SourceAmount::new(amount as i64, current_block_meta.unit_base as i64),
&WalletScriptV10::single(WalletConditionV10::Sig(issuer)),
use_mempool_sources,
)?,
))
} else {
Err(anyhow::Error::msg("no blockchain"))
}
)
})
.await??;
let amount = SourceAmount::new(amount as i64, current_block.unit_base as i64);
let amount = SourceAmount::new(amount as i64, current_block_meta.unit_base as i64);
if inputs_sum < amount {
return Err(async_graphql::Error::new("insufficient balance"));
}
let current_blockstamp = Blockstamp {
number: BlockNumber(current_block.number),
hash: BlockHash(current_block.hash),
number: BlockNumber(current_block_meta.number),
hash: BlockHash(current_block_meta.hash),
};
Ok(TransactionDocumentV10::generate_simple_txs(
......@@ -157,6 +154,9 @@ impl GenTxsQuery {
.into_iter()
.map(|tx| tx.as_text().to_owned())
.collect())
} else {
Err(async_graphql::Error::new("no blockchain"))
}
}
/// Generate complex transaction document
async fn gen_complex_tx(
......@@ -191,11 +191,14 @@ impl GenTxsQuery {
let db_reader = data.dbs_reader();
let currency = data.server_meta_data.currency.clone();
let (current_block, issuers_inputs_with_sum) = data
if let Some(current_block_meta) = data
.cm_accessor
.get_current_meta(|cm| cm.current_block_meta)
.await
{
let issuers_inputs_with_sum = data
.dbs_pool
.execute(move |dbs| {
if let Some(current_block) = duniter_bc_reader::get_current_block_meta(&dbs.cm_db)?
{
let mut issuers_inputs_with_sum = Vec::new();
for issuer in issuers {
issuers_inputs_with_sum.push((
......@@ -204,7 +207,7 @@ impl GenTxsQuery {
&dbs.txs_mp_db,
SourceAmount::new(
issuer.amount as i64,
current_block.unit_base as i64,
current_block_meta.unit_base as i64,
),
&issuer.script,
use_mempool_sources,
......@@ -212,15 +215,13 @@ impl GenTxsQuery {
issuer,
));
}
Ok((current_block, issuers_inputs_with_sum))
} else {
Err(anyhow::Error::msg("no blockchain"))
}
Ok::<_, anyhow::Error>(issuers_inputs_with_sum)
})
.await??;
for ((_inputs, inputs_sum), issuer) in &issuers_inputs_with_sum {
let amount = SourceAmount::new(issuer.amount as i64, current_block.unit_base as i64);
let amount =
SourceAmount::new(issuer.amount as i64, current_block_meta.unit_base as i64);
if *inputs_sum < amount {
return Err(async_graphql::Error::new(format!(
"Insufficient balance for issuer {}",
......@@ -230,10 +231,10 @@ impl GenTxsQuery {
}
let current_blockstamp = Blockstamp {
number: BlockNumber(current_block.number),
hash: BlockHash(current_block.hash),
number: BlockNumber(current_block_meta.number),
hash: BlockHash(current_block_meta.hash),
};
let base = current_block.unit_base as i64;
let base = current_block_meta.unit_base as i64;
let (final_tx_opt, changes_txs) = TransactionDocV10ComplexGen {
blockstamp: current_blockstamp,
......@@ -269,5 +270,8 @@ impl GenTxsQuery {
.collect(),
))
}
} else {
Err(async_graphql::Error::new("no blockchain"))
}
}
}
......@@ -60,7 +60,7 @@ mod tests {
username: String::from("JohnDoe"),
}))
});
let schema = create_schema(dbs_reader)?;
let schema = create_schema(MockAsyncAccessor::new(), dbs_reader)?;
assert_eq!(
exec_graphql_request(
&schema,
......
......@@ -299,7 +299,7 @@ mod tests {
has_next_page: false,
})
});
let schema = create_schema(dbs_reader)?;
let schema = create_schema(MockAsyncAccessor::new(), dbs_reader)?;
assert_eq!(
exec_graphql_request(
&schema,
......
......@@ -28,16 +28,17 @@ impl UdsQuery {
ctx: &async_graphql::Context<'_>,
) -> async_graphql::Result<Option<CurrentUdGva>> {
let data = ctx.data::<GvaSchemaData>()?;
let dbs_reader = data.dbs_reader();
Ok(data
.dbs_pool
.execute(move |dbs| dbs_reader.get_current_ud(&dbs.bc_db_ro))
.await??
.map(|sa| CurrentUdGva {
amount: sa.amount(),
base: sa.base(),
}))
Ok(
if let Some(current_ud) = data.cm_accessor.get_current_meta(|cm| cm.current_ud).await {
Some(CurrentUdGva {
amount: current_ud.amount(),
base: current_ud.base(),
})
} else {
None
},
)
}
/// Universal dividends issued by a public key
#[allow(clippy::clippy::too_many_arguments)]
......@@ -55,6 +56,11 @@ impl UdsQuery {
let data = ctx.data::<GvaSchemaData>()?;
let dbs_reader = data.dbs_reader();
if let Some(current_base) = data
.cm_accessor
.get_current_meta(|cm| cm.current_block_meta.unit_base)
.await
{
let (
PagedData {
data: UdsWithSum { uds, sum },
......@@ -65,8 +71,6 @@ impl UdsQuery {
) = data
.dbs_pool
.execute(move |dbs| {
if let Some(current_block) = duniter_bc_reader::get_current_block_meta(&dbs.cm_db)?
{
let paged_data = match filter {
UdsFilter::All => {
dbs_reader.all_uds_of_pubkey(&dbs.bc_db_ro, pubkey.0, pagination)
......@@ -76,9 +80,7 @@ impl UdsQuery {
pubkey.0,
pagination,
None,
amount.map(|amount| {
SourceAmount::new(amount, current_block.unit_base as i64)
}),
amount.map(|amount| SourceAmount::new(amount, current_base as i64)),
),
}?;
......@@ -87,9 +89,6 @@ impl UdsQuery {
times.push(dbs_reader.get_blockchain_time(*bn)?);
}
Ok::<_, anyhow::Error>((paged_data, times))
} else {
Err(anyhow::Error::msg("no blockchain"))
}
})
.await??;
......@@ -126,6 +125,9 @@ impl UdsQuery {
conn.append(uds_timed.rev());
}
Ok(conn)
} else {
Err(async_graphql::Error::new("no blockchain"))
}
}
/// Universal dividends revaluations
async fn uds_reval(
......@@ -157,13 +159,17 @@ mod tests {
#[tokio::test]
async fn query_current_ud() -> anyhow::Result<()> {
let mut dbs_reader = MockDbsReader::new();
use duniter_dbs::databases::bc_v2::BcV2DbRo;
dbs_reader
.expect_get_current_ud::<BcV2DbRo<FileBackend>>()
let mut mock_cm = MockAsyncAccessor::new();
mock_cm
.expect_get_current_meta::<SourceAmount>()
.times(1)
.returning(|_| Ok(Some(SourceAmount::with_base0(100))));
let schema = create_schema(dbs_reader)?;
.returning(|f| {
Some(f(&CurrentMeta {
current_ud: SourceAmount::with_base0(100),
..Default::default()
}))
});
let schema = create_schema(mock_cm, MockDbsReader::new())?;
assert_eq!(
exec_graphql_request(&schema, r#"{ currentUd {amount} }"#).await?,
serde_json::json!({
......
......@@ -37,8 +37,13 @@ impl UtxosQuery {
let pagination = Pagination::convert_to_page_info(pagination, *is_whitelisted)?;
let data = ctx.data::<GvaSchemaData>()?;
let cm_accessor = data.cm_accessor();
let db_reader = data.dbs_reader();
if let Some(current_base) = cm_accessor
.get_current_meta(|cm| cm.current_block_meta.unit_base)
.await
{
let (
PagedData {
data: UtxosWithSum { utxos, sum },
......@@ -49,13 +54,9 @@ impl UtxosQuery {
) = data
.dbs_pool
.execute(move |dbs| {
if let Some(current_block) = duniter_bc_reader::get_current_block_meta(&dbs.cm_db)?
{
let paged_data = db_reader.find_script_utxos(
&dbs.txs_mp_db,
amount.map(|amount| {
SourceAmount::new(amount, current_block.unit_base as i64)
}),
amount.map(|amount| SourceAmount::new(amount, current_base as i64)),
pagination,
&script.0,
)?;
......@@ -64,9 +65,6 @@ impl UtxosQuery {
times.push(db_reader.get_blockchain_time(*block_number)?);
}
Ok::<_, anyhow::Error>((paged_data, times))
} else {
Err(anyhow::Error::msg("no blockchain"))
}
})
.await??;
......@@ -98,5 +96,8 @@ impl UtxosQuery {
},
));
Ok(conn)
} else {
Err(async_graphql::Error::new("no blockchain"))
}
}
}
......@@ -45,6 +45,7 @@ pub fn build_schema_with_data(data: GvaSchemaData, logger: bool) -> GvaSchema {
}
pub struct GvaSchemaData {
pub cm_accessor: AsyncAccessor,
pub dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<SharedDbs<FileBackend>>,
pub dbs_reader: DbsReaderImpl,
pub server_meta_data: ServerMetaData,
......@@ -53,6 +54,10 @@ pub struct GvaSchemaData {
#[cfg(not(test))]
impl GvaSchemaData {
#[inline(always)]
pub fn cm_accessor(&self) -> AsyncAccessor {
self.cm_accessor
}
#[inline(always)]
pub fn dbs_reader(&self) -> DbsReaderImpl {
self.dbs_reader
......@@ -60,6 +65,9 @@ impl GvaSchemaData {
}
#[cfg(test)]
impl GvaSchemaData {
pub fn cm_accessor(&self) -> AsyncAccessor {
self.cm_accessor.clone()
}
pub fn dbs_reader(&self) -> DbsReaderImpl {
self.dbs_reader.clone()
}
......
......@@ -15,8 +15,7 @@
use super::create_subscription;
use crate::*;
use duniter_dbs::databases::cm_v1::{CmV1DbReadable, CurrentBlockEvent, CurrentBlockMetaEvent};
use futures::future::Either;
use duniter_dbs::databases::cm_v1::{CmV1DbReadable, CurrentBlockEvent};
#[derive(Clone, Copy, Default)]
pub struct NewBlocksSubscription;
......@@ -27,41 +26,6 @@ impl NewBlocksSubscription {
&self,
ctx: &async_graphql::Context<'_>,
) -> impl Stream<Item = async_graphql::Result<Vec<Block>>> {
let meta_only = !(ctx.look_ahead().field("identities").exists()
|| ctx.look_ahead().field("joiners").exists()
|| ctx.look_ahead().field("actives").exists()
|| ctx.look_ahead().field("leavers").exists()
|| ctx.look_ahead().field("revoked").exists()
|| ctx.look_ahead().field("excluded").exists()
|| ctx.look_ahead().field("certifications").exists()
|| ctx.look_ahead().field("transactions").exists());
if meta_only {
Either::Left(
create_subscription(
ctx,
|dbs| dbs.cm_db.current_block_meta(),
|events| {
let mut blocks = Vec::new();
for event in events.deref() {
if let CurrentBlockMetaEvent::Upsert {
value: ref block_meta,
..
} = event
{
blocks.push(Block::from(block_meta));
}
}
if blocks.is_empty() {
futures::future::ready(None)
} else {
futures::future::ready(Some(Ok(blocks)))
}
},
)
.await,
)
} else {
Either::Right(
create_subscription(
ctx,
|dbs| dbs.cm_db.current_block(),
......@@ -82,8 +46,6 @@ impl NewBlocksSubscription {
}
},
)
.await,
)
}
.await
}
}
......@@ -39,6 +39,7 @@ use duniter_conf::DuniterMode;
use duniter_dbs::databases::txs_mp_v2::TxsMpV2DbReadable;
use duniter_dbs::prelude::*;
use duniter_dbs::{kv_typed::prelude::*, FileBackend};
use duniter_global::AsyncAccessor;
use duniter_gva_db::*;
use duniter_gva_gql::{GvaSchema, QueryContext};
use duniter_gva_indexer::{get_gva_db_ro, get_gva_db_rw};
......@@ -243,6 +244,7 @@ impl GvaModule {
let self_pubkey = self_keypair.public_key();
duniter_bca::set_bca_executor(
currency.clone(),
AsyncAccessor::new(),
dbs_pool.clone(),
duniter_gva_dbs_reader::create_dbs_reader(gva_db_ro),
self_keypair,
......@@ -251,6 +253,7 @@ impl GvaModule {
);
let gva_schema = duniter_gva_gql::build_schema_with_data(
duniter_gva_gql::GvaSchemaData {
cm_accessor: AsyncAccessor::new(),
dbs_reader: duniter_gva_dbs_reader::create_dbs_reader(gva_db_ro),
dbs_pool,
server_meta_data: duniter_gva_gql::ServerMetaData {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment