Skip to content

Commit

Permalink
In memory ledger response caching (#855)
Browse files Browse the repository at this point in the history
In memory ledger response caching (#855)

Signed-off-by: Miroslav Kovar <miroslav.kovar@absa.africa>
  • Loading branch information
mirgee authored May 22, 2023
1 parent 1711b3d commit 516cd3a
Show file tree
Hide file tree
Showing 14 changed files with 430 additions and 22 deletions.
40 changes: 35 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions aries_vcx/src/core/profile/modular_libs_profile.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use std::sync::Arc;
use std::time::Duration;

use aries_vcx_core::anoncreds::base_anoncreds::BaseAnonCreds;
use aries_vcx_core::anoncreds::credx_anoncreds::IndyCredxAnonCreds;
use aries_vcx_core::ledger::base_ledger::BaseLedger;
use aries_vcx_core::ledger::indy_vdr_ledger::{IndyVdrLedger, IndyVdrLedgerConfig};
use aries_vcx_core::ledger::request_signer::base_wallet::BaseWalletRequestSigner;
use aries_vcx_core::ledger::request_submitter::vdr_ledger::{IndyVdrLedgerPool, IndyVdrSubmitter, LedgerPoolConfig};
use aries_vcx_core::ledger::response_cacher::in_memory::{InMemoryResponseCacher, InMemoryResponseCacherConfig};
use aries_vcx_core::wallet::base_wallet::BaseWallet;
use aries_vcx_core::ResponseParser;

Expand All @@ -28,10 +30,16 @@ impl ModularLibsProfile {
let request_signer = Arc::new(BaseWalletRequestSigner::new(wallet.clone()));
let request_submitter = Arc::new(IndyVdrSubmitter::new(ledger_pool));
let response_parser = Arc::new(ResponseParser::new());
let cacher_config = InMemoryResponseCacherConfig::builder()
.ttl(Duration::from_secs(60))
.capacity(1000)?
.build();
let response_cacher = Arc::new(InMemoryResponseCacher::new(cacher_config));
let config = IndyVdrLedgerConfig {
request_signer,
request_submitter,
response_parser,
response_cacher,
};
let ledger = Arc::new(IndyVdrLedger::new(config));
Ok(ModularLibsProfile {
Expand Down
17 changes: 13 additions & 4 deletions aries_vcx/src/core/profile/vdr_proxy_profile.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::sync::Arc;
use std::{sync::Arc, time::Duration};

use aries_vcx_core::{
anoncreds::{base_anoncreds::BaseAnonCreds, indy_anoncreds::IndySdkAnonCreds},
Expand All @@ -7,11 +7,14 @@ use aries_vcx_core::{
indy_vdr_ledger::{IndyVdrLedger, IndyVdrLedgerConfig},
request_signer::base_wallet::BaseWalletRequestSigner,
request_submitter::vdr_proxy::VdrProxySubmitter,
response_cacher::in_memory::{InMemoryResponseCacher, InMemoryResponseCacherConfig},
},
wallet::{base_wallet::BaseWallet, indy_wallet::IndySdkWallet},
ResponseParser, VdrProxyClient, WalletHandle,
};

use crate::errors::error::VcxResult;

use super::profile::Profile;

#[derive(Debug)]
Expand All @@ -22,23 +25,29 @@ pub struct VdrProxyProfile {
}

impl VdrProxyProfile {
pub fn new(wallet_handle: WalletHandle, client: VdrProxyClient) -> Self {
pub fn new(wallet_handle: WalletHandle, client: VdrProxyClient) -> VcxResult<Self> {
let wallet = Arc::new(IndySdkWallet::new(wallet_handle));
let anoncreds = Arc::new(IndySdkAnonCreds::new(wallet_handle));
let request_signer = Arc::new(BaseWalletRequestSigner::new(wallet.clone()));
let request_submitter = Arc::new(VdrProxySubmitter::new(Arc::new(client)));
let response_parser = Arc::new(ResponseParser::new());
let cacher_config = InMemoryResponseCacherConfig::builder()
.ttl(Duration::from_secs(60))
.capacity(1000)?
.build();
let response_cacher = Arc::new(InMemoryResponseCacher::new(cacher_config));
let config = IndyVdrLedgerConfig {
request_signer,
request_submitter,
response_parser,
response_cacher,
};
let ledger = Arc::new(IndyVdrLedger::new(config));
VdrProxyProfile {
Ok(VdrProxyProfile {
wallet,
ledger,
anoncreds,
}
})
}
}

Expand Down
2 changes: 1 addition & 1 deletion aries_vcx/src/utils/devsetup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ impl SetupProfile {
let client_url = env::var("VDR_PROXY_CLIENT_URL").unwrap_or_else(|_| "http://127.0.0.1:3030".to_string());
let client = VdrProxyClient::new(&client_url).unwrap();

let profile: Arc<dyn Profile> = Arc::new(VdrProxyProfile::new(wallet_handle, client));
let profile: Arc<dyn Profile> = Arc::new(VdrProxyProfile::new(wallet_handle, client).unwrap());

async fn vdr_proxy_teardown() {
// nothing to do
Expand Down
5 changes: 3 additions & 2 deletions aries_vcx_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ edition = "2021"
# Feature flag to include the libvdrtools dependency
vdrtools = ["dep:libvdrtools"]
# Feature flag to include the 'modular library' dependencies (vdrtools alternatives; indy-vdr, indy-credx)
modular_libs = ["dep:indy-vdr", "dep:indy-credx", "dep:indy-ledger-response-parser"]
vdr_proxy_ledger = ["dep:indy-vdr", "dep:indy-credx", "dep:indy-vdr-proxy-client", "dep:indy-ledger-response-parser"]
modular_libs = ["dep:indy-vdr", "dep:indy-credx", "dep:indy-ledger-response-parser", "dep:lru"]
vdr_proxy_ledger = ["dep:indy-vdr", "dep:indy-credx", "dep:indy-vdr-proxy-client", "dep:indy-ledger-response-parser", "dep:lru"]

[dependencies]
agency_client = { path = "../agency_client" }
Expand Down Expand Up @@ -43,6 +43,7 @@ tokio = { version = "1.20" }
# TODO: Point to the official repo if / when vdr-proxy-client PR is merged: https://github.com/hyperledger/indy-vdr/pull/184
indy-vdr-proxy-client = { git = "https://github.com/mirgee/indy-vdr.git", rev = "fab0535", optional = true }
indy-ledger-response-parser = { path = "../indy_ledger_response_parser", optional = true }
lru = { version = "0.10.0", optional = true }

[dev-dependencies]
tokio = { version = "1.20", features = ["rt", "macros", "rt-multi-thread"] }
38 changes: 29 additions & 9 deletions aries_vcx_core/src/ledger/indy_vdr_ledger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,37 +25,44 @@ use crate::global::settings;
use super::base_ledger::BaseLedger;
use super::request_signer::RequestSigner;
use super::request_submitter::RequestSubmitter;
use super::response_cacher::ResponseCacher;

pub struct IndyVdrLedgerConfig<T, U>
pub struct IndyVdrLedgerConfig<T, U, V>
where
T: RequestSubmitter + Send + Sync,
U: RequestSigner + Send + Sync,
V: ResponseCacher + Send + Sync,
{
pub request_signer: Arc<U>,
pub request_submitter: Arc<T>,
pub response_parser: Arc<ResponseParser>,
pub response_cacher: Arc<V>,
}

pub struct IndyVdrLedger<T, U>
pub struct IndyVdrLedger<T, U, V>
where
T: RequestSubmitter + Send + Sync,
U: RequestSigner + Send + Sync,
V: ResponseCacher + Send + Sync,
{
request_signer: Arc<U>,
request_submitter: Arc<T>,
response_parser: Arc<ResponseParser>,
response_cacher: Arc<V>,
}

impl<T, U> IndyVdrLedger<T, U>
impl<T, U, V> IndyVdrLedger<T, U, V>
where
T: RequestSubmitter + Send + Sync,
U: RequestSigner + Send + Sync,
V: ResponseCacher + Send + Sync,
{
pub fn new(config: IndyVdrLedgerConfig<T, U>) -> Self {
pub fn new(config: IndyVdrLedgerConfig<T, U, V>) -> Self {
Self {
request_signer: config.request_signer,
request_submitter: config.request_submitter,
response_parser: config.response_parser,
response_cacher: config.response_cacher,
}
}

Expand All @@ -66,6 +73,17 @@ where
Ok(RequestBuilder::new(version))
}

async fn _submit_request_cached(&self, id: &str, request: PreparedRequest) -> VcxCoreResult<String> {
match self.response_cacher.get(id, None).await? {
Some(response) => Ok(response),
None => {
let response = self.request_submitter.submit(request).await?;
self.response_cacher.put(id, response.clone()).await?;
Ok(response)
}
}
}

async fn _submit_request(&self, request: PreparedRequest) -> VcxCoreResult<String> {
self.request_submitter.submit(request).await
}
Expand Down Expand Up @@ -193,21 +211,23 @@ where
}
}

impl<T, U> Debug for IndyVdrLedger<T, U>
impl<T, U, V> Debug for IndyVdrLedger<T, U, V>
where
T: RequestSubmitter + Send + Sync,
U: RequestSigner + Send + Sync,
V: ResponseCacher + Send + Sync,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "IndyVdrLedger instance")
}
}

#[async_trait]
impl<T, U> BaseLedger for IndyVdrLedger<T, U>
impl<T, U, V> BaseLedger for IndyVdrLedger<T, U, V>
where
T: RequestSubmitter + Send + Sync,
U: RequestSigner + Send + Sync,
V: ResponseCacher + Send + Sync,
{
async fn sign_and_submit_request(&self, submitter_did: &str, request_json: &str) -> VcxCoreResult<String> {
let request = PreparedRequest::from_request_json(request_json)?;
Expand Down Expand Up @@ -247,7 +267,7 @@ where
let dest = DidValue::from_str(did)?;
let request = self.request_builder()?.build_get_nym_request(None, &dest)?;

self._submit_request(request).await
self._submit_request_cached(did, request).await
}

async fn publish_nym(
Expand Down Expand Up @@ -275,7 +295,7 @@ where
let request = self
.request_builder()?
.build_get_schema_request(None, &SchemaId::from_str(schema_id)?)?;
let response = self._submit_request(request).await?;
let response = self._submit_request_cached(schema_id, request).await?;
let schema = self.response_parser.parse_get_schema_response(&response, None)?;
Ok(serde_json::to_string(&schema)?)
}
Expand Down Expand Up @@ -303,7 +323,7 @@ where
async fn get_rev_reg_def_json(&self, rev_reg_id: &str) -> VcxCoreResult<String> {
let id = RevocationRegistryId::from_str(rev_reg_id)?;
let request = self.request_builder()?.build_get_revoc_reg_def_request(None, &id)?;
let res = self._submit_request(request).await?;
let res = self._submit_request_cached(rev_reg_id, request).await?;

let rev_reg_def = self.response_parser.parse_get_revoc_reg_def_response(&res)?;

Expand Down
2 changes: 2 additions & 0 deletions aries_vcx_core/src/ledger/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ pub mod indy_vdr_ledger;
pub mod request_signer;
#[cfg(any(feature = "modular_libs", feature = "vdr_proxy_ledger"))]
pub mod request_submitter;
#[cfg(any(feature = "modular_libs", feature = "vdr_proxy_ledger"))]
pub mod response_cacher;
62 changes: 62 additions & 0 deletions aries_vcx_core/src/ledger/response_cacher/in_memory/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use std::{num::NonZeroUsize, time::Duration};

use crate::errors::error::{AriesVcxCoreError, AriesVcxCoreErrorKind};

pub struct InMemoryResponseCacherConfig {
ttl: Duration,
capacity: NonZeroUsize,
}

impl InMemoryResponseCacherConfig {
pub fn builder() -> InMemoryResponseCacherConfigBuilder {
InMemoryResponseCacherConfigBuilder::default()
}

pub fn ttl(&self) -> Duration {
self.ttl
}

pub fn capacity(&self) -> NonZeroUsize {
self.capacity
}
}

#[derive(Default)]
pub struct InMemoryResponseCacherConfigBuilder {}

pub struct InMemoryResponseCacherConfigBuilderTtlSet {
ttl: Duration,
}

pub struct InMemoryResponseCacherConfigBuilderReady {
ttl: Duration,
capacity: NonZeroUsize,
}

impl InMemoryResponseCacherConfigBuilder {
pub fn ttl(self, ttl: Duration) -> InMemoryResponseCacherConfigBuilderTtlSet {
InMemoryResponseCacherConfigBuilderTtlSet { ttl }
}
}

impl InMemoryResponseCacherConfigBuilderTtlSet {
pub fn capacity(self, capacity: usize) -> Result<InMemoryResponseCacherConfigBuilderReady, AriesVcxCoreError> {
let capacity = NonZeroUsize::new(capacity).ok_or(AriesVcxCoreError::from_msg(
AriesVcxCoreErrorKind::InvalidOption,
"Failed to parse cache capacity into NonZeroUsize",
))?;
Ok(InMemoryResponseCacherConfigBuilderReady {
ttl: self.ttl,
capacity,
})
}
}

impl InMemoryResponseCacherConfigBuilderReady {
pub fn build(self) -> InMemoryResponseCacherConfig {
InMemoryResponseCacherConfig {
ttl: self.ttl,
capacity: self.capacity,
}
}
}
Loading

0 comments on commit 516cd3a

Please sign in to comment.