use std::ops::RangeBounds;
use async_trait::async_trait;
use crate::receipt::{
state::{Checking, ReceiptState},
ReceiptWithState, WithValueAndTimestamp,
};
#[async_trait]
pub trait ReceiptStore<Rcpt> {
type AdapterError: std::error::Error + std::fmt::Debug + Send + Sync + 'static;
async fn store_receipt(
&self,
receipt: ReceiptWithState<Checking, Rcpt>,
) -> Result<u64, Self::AdapterError>;
}
#[async_trait]
pub trait ReceiptDelete {
type AdapterError: std::error::Error + std::fmt::Debug + Send + Sync + 'static;
async fn remove_receipts_in_timestamp_range<R: RangeBounds<u64> + std::marker::Send>(
&self,
timestamp_ns: R,
) -> Result<(), Self::AdapterError>;
}
#[async_trait]
pub trait ReceiptRead<Rcpt> {
type AdapterError: std::error::Error + std::fmt::Debug + Send + Sync + 'static;
async fn retrieve_receipts_in_timestamp_range<R: RangeBounds<u64> + std::marker::Send>(
&self,
timestamp_range_ns: R,
limit: Option<u64>,
) -> Result<Vec<ReceiptWithState<Checking, Rcpt>>, Self::AdapterError>;
}
pub fn safe_truncate_receipts<T: ReceiptState, Rcpt: WithValueAndTimestamp>(
receipts: &mut Vec<ReceiptWithState<T, Rcpt>>,
limit: u64,
) {
if receipts.len() <= limit as usize {
return;
} else if limit == 0 {
receipts.clear();
return;
}
receipts.sort_unstable_by_key(|rx_receipt| rx_receipt.signed_receipt().timestamp_ns());
let last_timestamp = receipts[limit as usize - 1].signed_receipt().timestamp_ns();
let after_last_timestamp = receipts[limit as usize].signed_receipt().timestamp_ns();
receipts.truncate(limit as usize);
if last_timestamp == after_last_timestamp {
receipts.retain(|rx_receipt| rx_receipt.signed_receipt().timestamp_ns() != last_timestamp);
}
}