Skip to content

Commit

Permalink
Merge pull request #194 from semiotic-ai/gusinacio/split-storage
Browse files Browse the repository at this point in the history
refactor: split read and write storage, update trait bounds and new mock feature flag
  • Loading branch information
gusinacio committed Dec 15, 2023
2 parents 63df2b5 + 2aa8877 commit e9770f9
Show file tree
Hide file tree
Showing 17 changed files with 403 additions and 290 deletions.
1 change: 1 addition & 0 deletions rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
edition = "2021"
5 changes: 5 additions & 0 deletions tap_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ tokio = { version = "1.29.1", features = ["macros", "rt-multi-thread"] }
[dev-dependencies]
criterion = { version = "0.5", features = ["async_std"] }
futures = "0.3.17"
tap_core = { path = ".", features = ["mock"] }


[features]
mock = []

[[bench]]
name = 'timeline_aggretion_protocol_benchmark'
Expand Down
7 changes: 7 additions & 0 deletions tap_core/src/adapters/mock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Copyright 2023-, Semiotic AI, Inc.
// SPDX-License-Identifier: Apache-2.0

pub mod escrow_adapter_mock;
pub mod rav_storage_adapter_mock;
pub mod receipt_checks_adapter_mock;
pub mod receipt_storage_adapter_mock;
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ use async_trait::async_trait;
use thiserror::Error;
use tokio::sync::RwLock;

use crate::{adapters::rav_storage_adapter::RAVStorageAdapter, tap_manager::SignedRAV};
use crate::{
adapters::rav_storage_adapter::{RAVRead, RAVStore},
tap_manager::SignedRAV,
};

/// `RAVStorageAdapterMock` is a mock implementation of the `RAVStorageAdapter` trait.
///
Expand Down Expand Up @@ -55,14 +58,20 @@ pub enum AdpaterErrorMock {
}

#[async_trait]
impl RAVStorageAdapter for RAVStorageAdapterMock {
impl RAVStore for RAVStorageAdapterMock {
type AdapterError = AdpaterErrorMock;

async fn update_last_rav(&self, rav: SignedRAV) -> Result<(), Self::AdapterError> {
let mut rav_storage = self.rav_storage.write().await;
*rav_storage = Some(rav);
Ok(())
}
}

#[async_trait]
impl RAVRead for RAVStorageAdapterMock {
type AdapterError = AdpaterErrorMock;

async fn last_rav(&self) -> Result<Option<SignedRAV>, Self::AdapterError> {
Ok(self.rav_storage.read().await.clone())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use async_trait::async_trait;
use tokio::sync::RwLock;

use crate::{
adapters::receipt_storage_adapter::{safe_truncate_receipts, ReceiptStorageAdapter},
adapters::receipt_storage_adapter::{safe_truncate_receipts, ReceiptRead, ReceiptStore},
tap_receipt::ReceivedReceipt,
};

Expand Down Expand Up @@ -84,7 +84,7 @@ pub enum AdapterErrorMock {
}

#[async_trait]
impl ReceiptStorageAdapter for ReceiptStorageAdapterMock {
impl ReceiptStore for ReceiptStorageAdapterMock {
type AdapterError = AdapterErrorMock;
async fn store_receipt(&self, receipt: ReceivedReceipt) -> Result<u64, Self::AdapterError> {
let mut id_pointer = self.unique_id.write().await;
Expand All @@ -94,28 +94,6 @@ impl ReceiptStorageAdapter for ReceiptStorageAdapterMock {
*id_pointer += 1;
Ok(id_previous)
}
async fn retrieve_receipts_in_timestamp_range<R: RangeBounds<u64> + std::marker::Send>(
&self,
timestamp_range_ns: R,
limit: Option<u64>,
) -> Result<Vec<(u64, ReceivedReceipt)>, Self::AdapterError> {
let receipt_storage = self.receipt_storage.read().await;
let mut receipts_in_range: Vec<(u64, ReceivedReceipt)> = receipt_storage
.iter()
.filter(|(_, rx_receipt)| {
timestamp_range_ns.contains(&rx_receipt.signed_receipt.message.timestamp_ns)
})
.map(|(&id, rx_receipt)| (id, rx_receipt.clone()))
.collect();

if limit.is_some_and(|limit| receipts_in_range.len() > limit as usize) {
safe_truncate_receipts(&mut receipts_in_range, limit.unwrap());

Ok(receipts_in_range)
} else {
Ok(receipts_in_range)
}
}
async fn update_receipt_by_id(
&self,
receipt_id: u64,
Expand Down Expand Up @@ -144,3 +122,30 @@ impl ReceiptStorageAdapter for ReceiptStorageAdapterMock {
Ok(())
}
}

#[async_trait]
impl ReceiptRead for ReceiptStorageAdapterMock {
type AdapterError = AdapterErrorMock;
async fn retrieve_receipts_in_timestamp_range<R: RangeBounds<u64> + std::marker::Send>(
&self,
timestamp_range_ns: R,
limit: Option<u64>,
) -> Result<Vec<(u64, ReceivedReceipt)>, Self::AdapterError> {
let receipt_storage = self.receipt_storage.read().await;
let mut receipts_in_range: Vec<(u64, ReceivedReceipt)> = receipt_storage
.iter()
.filter(|(_, rx_receipt)| {
timestamp_range_ns.contains(&rx_receipt.signed_receipt.message.timestamp_ns)
})
.map(|(&id, rx_receipt)| (id, rx_receipt.clone()))
.collect();

if limit.is_some_and(|limit| receipts_in_range.len() > limit as usize) {
safe_truncate_receipts(&mut receipts_in_range, limit.unwrap());

Ok(receipts_in_range)
} else {
Ok(receipts_in_range)
}
}
}
12 changes: 7 additions & 5 deletions tap_core/src/adapters/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ pub mod rav_storage_adapter;
pub mod receipt_checks_adapter;
pub mod receipt_storage_adapter;

mod test;
#[cfg(feature = "mock")]
mod mock;

#[cfg(feature = "mock")]
pub use mock::*;

pub use test::escrow_adapter_mock;
pub use test::rav_storage_adapter_mock;
pub use test::receipt_checks_adapter_mock;
pub use test::receipt_storage_adapter_mock;
#[cfg(test)]
mod test;
39 changes: 32 additions & 7 deletions tap_core/src/adapters/rav_storage_adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ use async_trait::async_trait;

use crate::tap_manager::SignedRAV;

/// `RAVStorageAdapter` defines a trait for storage adapters to handle `SignedRAV` data.
/// `RAVStore` defines a trait for write storage adapters to handle `SignedRAV` data.
///
/// This trait is designed to be implemented by users of this library who want to
/// customize the storage behavior of `SignedRAV` data. The error handling is also
/// customize the write storage behavior of `SignedRAV` data. The error handling is also
/// customizable by defining an `AdapterError` type, which must implement both `Error`
/// and `Debug` from the standard library.
///
Expand All @@ -18,10 +18,6 @@ use crate::tap_manager::SignedRAV;
/// in the storage managed by the adapter. Errors during this operation should be
/// captured and returned in the `AdapterError` format.
///
/// The `last_rav` method is designed to fetch the latest `SignedRAV` from the storage.
/// If there is no `SignedRAV` available, it should return `None`. Any errors during
/// this operation should be captured and returned as an `AdapterError`.
///
/// This trait is utilized by [crate::tap_manager], which relies on these
/// operations for working with `SignedRAV` data.
///
Expand All @@ -30,7 +26,7 @@ use crate::tap_manager::SignedRAV;
/// For example code see [crate::adapters::rav_storage_adapter_mock]

#[async_trait]
pub trait RAVStorageAdapter {
pub trait RAVStore {
/// Defines the user-specified error type.
///
/// This error type should implement the `Error` and `Debug` traits from the standard library.
Expand All @@ -42,6 +38,35 @@ pub trait RAVStorageAdapter {
/// This method should be implemented to store the most recent validated `SignedRAV` into your chosen storage system.
/// Any errors that occur during this process should be captured and returned as an `AdapterError`.
async fn update_last_rav(&self, rav: SignedRAV) -> Result<(), Self::AdapterError>;
}

/// `RAVRead` defines a trait for read storage adapters to handle `SignedRAV` data.
///
/// This trait is designed to be implemented by users of this library who want to
/// customize the read storage behavior of `SignedRAV` data. The error handling is also
/// customizable by defining an `AdapterError` type, which must implement both `Error`
/// and `Debug` from the standard library.
///
/// # Usage
///
/// The `last_rav` method is designed to fetch the latest `SignedRAV` from the storage.
/// If there is no `SignedRAV` available, it should return `None`. Any errors during
/// this operation should be captured and returned as an `AdapterError`.
///
/// This trait is utilized by [crate::tap_manager], which relies on these
/// operations for working with `SignedRAV` data.
///
/// # Example
///
/// For example code see [crate::adapters::rav_storage_adapter_mock]

#[async_trait]
pub trait RAVRead {
/// Defines the user-specified error type.
///
/// This error type should implement the `Error` and `Debug` traits from the standard library.
/// Errors of this type are returned to the user when an operation fails.
type AdapterError: std::error::Error + std::fmt::Debug + Send + Sync + 'static;

/// Retrieves the latest `SignedRAV` from the storage.
///
Expand Down
73 changes: 45 additions & 28 deletions tap_core/src/adapters/receipt_storage_adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ use async_trait::async_trait;

use crate::tap_receipt::ReceivedReceipt;

/// `ReceiptStorageAdapter` defines a trait for storage adapters to manage `ReceivedReceipt` data.
/// `ReceiptStore` defines a trait for write storage adapters to manage `ReceivedReceipt` data.
///
/// This trait is designed to be implemented by users of this library who want to
/// customize the storage behavior of `ReceivedReceipt` data. The error handling is also
/// customize the write storage behavior of `ReceivedReceipt` data. The error handling is also
/// customizable by defining an `AdapterError` type, which must implement both `Error`
/// and `Debug` from the standard library.
///
Expand All @@ -20,10 +20,6 @@ use crate::tap_receipt::ReceivedReceipt;
/// managed by the adapter. It returns a unique receipt_id associated with the stored receipt.
/// Any errors during this operation should be captured and returned in the `AdapterError` format.
///
/// The `retrieve_receipts_in_timestamp_range` method should be implemented to fetch all `ReceivedReceipts`
/// within a specific timestamp range from the storage. The returned receipts should be in the form of a vector
/// of tuples where each tuple contains the unique receipt_id and the corresponding `ReceivedReceipt`.
///
/// The `update_receipt_by_id` method is designed to update a specific `ReceivedReceipt` identified by a unique
/// receipt_id. Any errors during this operation should be captured and returned as an `AdapterError`.
///
Expand All @@ -38,7 +34,7 @@ use crate::tap_receipt::ReceivedReceipt;
/// For example code see [crate::adapters::receipt_storage_adapter_mock]

#[async_trait]
pub trait ReceiptStorageAdapter {
pub trait ReceiptStore {
/// Defines the user-specified error type.
///
/// This error type should implement the `Error` and `Debug` traits from the standard library.
Expand All @@ -52,6 +48,48 @@ pub trait ReceiptStorageAdapter {
/// this process should be captured and returned as an `AdapterError`.
async fn store_receipt(&self, receipt: ReceivedReceipt) -> Result<u64, Self::AdapterError>;

/// Updates a specific `ReceivedReceipt` identified by a unique receipt_id.
///
/// This method should be implemented to update a specific `ReceivedReceipt` identified by a unique
/// receipt_id in your storage system. Any errors that occur during this process should be captured
/// and returned as an `AdapterError`.
async fn update_receipt_by_id(
&self,
receipt_id: u64,
receipt: ReceivedReceipt,
) -> Result<(), Self::AdapterError>;

/// Removes all `ReceivedReceipts` within a specific timestamp range from the storage.
///
/// This method should be implemented to remove all `ReceivedReceipts` within a specific timestamp
/// range from your storage system. Any errors that occur during this process should be captured and
/// returned as an `AdapterError`.
async fn remove_receipts_in_timestamp_range<R: RangeBounds<u64> + std::marker::Send>(
&self,
timestamp_ns: R,
) -> Result<(), Self::AdapterError>;
}

/// `ReceiptRead` defines a trait for read storage adapters to manage `ReceivedReceipt` data.
///
/// This trait is designed to be implemented by users of this library who want to
/// customize the read storage behavior of `ReceivedReceipt` data. The error handling is also
/// customizable by defining an `AdapterError` type, which must implement both `Error`
/// and `Debug` from the standard library.
///
/// # Usage
///
/// The `retrieve_receipts_in_timestamp_range` method should be implemented to fetch all `ReceivedReceipts`
/// within a specific timestamp range from the storage. The returned receipts should be in the form of a vector
/// of tuples where each tuple contains the unique receipt_id and the corresponding `ReceivedReceipt`.
#[async_trait]
pub trait ReceiptRead {
/// Defines the user-specified error type.
///
/// This error type should implement the `Error` and `Debug` traits from the standard library.
/// Errors of this type are returned to the user when an operation fails.
type AdapterError: std::error::Error + std::fmt::Debug + Send + Sync + 'static;

/// Retrieves all `ReceivedReceipts` within a specific timestamp range.
///
/// This method should be implemented to fetch all `ReceivedReceipts` within a specific timestamp range
Expand All @@ -78,27 +116,6 @@ pub trait ReceiptStorageAdapter {
timestamp_range_ns: R,
limit: Option<u64>,
) -> Result<Vec<(u64, ReceivedReceipt)>, Self::AdapterError>;

/// Updates a specific `ReceivedReceipt` identified by a unique receipt_id.
///
/// This method should be implemented to update a specific `ReceivedReceipt` identified by a unique
/// receipt_id in your storage system. Any errors that occur during this process should be captured
/// and returned as an `AdapterError`.
async fn update_receipt_by_id(
&self,
receipt_id: u64,
receipt: ReceivedReceipt,
) -> Result<(), Self::AdapterError>;

/// Removes all `ReceivedReceipts` within a specific timestamp range from the storage.
///
/// This method should be implemented to remove all `ReceivedReceipts` within a specific timestamp
/// range from your storage system. Any errors that occur during this process should be captured and
/// returned as an `AdapterError`.
async fn remove_receipts_in_timestamp_range<R: RangeBounds<u64> + std::marker::Send>(
&self,
timestamp_ns: R,
) -> Result<(), Self::AdapterError>;
}

/// See [`ReceiptStorageAdapter::retrieve_receipts_in_timestamp_range()`] for details.
Expand Down
5 changes: 0 additions & 5 deletions tap_core/src/adapters/test/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,3 @@ pub mod escrow_adapter_test;
pub mod rav_storage_adapter_test;
pub mod receipt_checks_adapter_test;
pub mod receipt_storage_adapter_test;

pub mod escrow_adapter_mock;
pub mod rav_storage_adapter_mock;
pub mod receipt_checks_adapter_mock;
pub mod receipt_storage_adapter_mock;
3 changes: 2 additions & 1 deletion tap_core/src/adapters/test/rav_storage_adapter_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ mod rav_storage_adapter_unit_test {
use rstest::*;
use tokio::sync::RwLock;

use crate::adapters::rav_storage_adapter::RAVRead;
use crate::adapters::{
rav_storage_adapter::RAVStorageAdapter, rav_storage_adapter_mock::RAVStorageAdapterMock,
rav_storage_adapter::RAVStore, rav_storage_adapter_mock::RAVStorageAdapterMock,
};
use crate::{
eip_712_signed_message::EIP712SignedMessage,
Expand Down
2 changes: 1 addition & 1 deletion tap_core/src/adapters/test/receipt_storage_adapter_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ mod receipt_storage_adapter_unit_test {
use tokio::sync::RwLock;

use crate::adapters::{
receipt_storage_adapter::ReceiptStorageAdapter,
receipt_storage_adapter::ReceiptStore,
receipt_storage_adapter_mock::ReceiptStorageAdapterMock,
};
use crate::{
Expand Down
Loading

0 comments on commit e9770f9

Please sign in to comment.