| 
					
				 | 
			
			
				@@ -0,0 +1,149 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use super::CacheStorage; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use crate::{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    changelog::Changelog, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    storage::{Batch, Error, Storage}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    transaction::from_db, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    AccountId, Amount, Payment, PaymentId, Status, Transaction, TransactionId, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use serde::{de::DeserializeOwned, Serialize}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use std::{collections::HashMap, marker::PhantomData}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#[derive(Debug, Clone, PartialEq, Eq, Hash)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+pub enum Ids { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    Transaction(TransactionId), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    Payment(PaymentId), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    Account(AccountId), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+pub struct CacheBatch<'a, S> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+where 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    S: Storage<'a>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    inner: S::Batch, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    payments: CacheStorage<PaymentId, Payment>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    balances: CacheStorage<AccountId, Vec<Amount>>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    transactions: CacheStorage<TransactionId, from_db::Transaction>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    to_invalidate: HashMap<Ids, ()>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    _phantom: PhantomData<&'a ()>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+impl<'a, S> CacheBatch<'a, S> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+where 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    S: Storage<'a> + Sync + Send, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    pub fn new( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        batch: S::Batch, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        payments: CacheStorage<PaymentId, Payment>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        balances: CacheStorage<AccountId, Vec<Amount>>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        transactions: CacheStorage<TransactionId, from_db::Transaction>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ) -> Self { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Self { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            inner: batch, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            payments, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            balances, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            transactions, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            to_invalidate: HashMap::new(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            _phantom: PhantomData, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#[async_trait::async_trait] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+impl<'a, S> Batch<'a> for CacheBatch<'a, S> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+where 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    S: Storage<'a> + Sync + Send, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    async fn commit(self) -> Result<(), Error> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let mut payments = self.payments.write().await; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let mut balances = self.balances.write().await; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let mut transactions = self.transactions.write().await; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.inner.commit().await?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for (id, _) in self.to_invalidate { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            match id { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                Ids::Transaction(id) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    transactions.remove(&id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                Ids::Payment(id) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    payments.remove(&id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                Ids::Account(id) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    balances.remove(&id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Ok(()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    async fn rollback(self) -> Result<(), Error> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.inner.rollback().await 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    async fn store_changelogs<T: DeserializeOwned + Serialize + Send + Sync>( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        &mut self, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        changelog: &[Changelog<T>], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ) -> Result<(), Error> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.inner.store_changelogs(changelog).await 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    async fn update_payment( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        &mut self, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        payment_id: &PaymentId, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        spent_by: &TransactionId, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        spent_status: Status, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ) -> Result<(), Error> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.to_invalidate 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .insert(Ids::Payment(payment_id.clone()), ()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.to_invalidate 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .insert(Ids::Transaction(spent_by.clone()), ()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.inner 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .update_payment(payment_id, spent_by, spent_status) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .await 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    async fn get_payment_status( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        &mut self, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        transaction_id: &TransactionId, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ) -> Result<Option<Status>, Error> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.to_invalidate 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .insert(Ids::Transaction(transaction_id.clone()), ()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.inner.get_payment_status(transaction_id).await 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    async fn store_new_payment(&mut self, payment: &Payment) -> Result<(), Error> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.to_invalidate 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .insert(Ids::Payment(payment.id.clone()), ()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.inner.store_new_payment(payment).await 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    async fn store_transaction(&mut self, transaction: &Transaction) -> Result<(), Error> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.to_invalidate 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .insert(Ids::Transaction(transaction.id().clone()), ()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.inner.store_transaction(transaction).await 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    async fn tag_transaction( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        &mut self, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        transaction: &Transaction, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        tags: &[String], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ) -> Result<(), Error> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.to_invalidate 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .insert(Ids::Transaction(transaction.id().clone()), ()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.inner.tag_transaction(transaction, tags).await 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    async fn relate_account_to_transaction( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        &mut self, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        transaction: &Transaction, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        account: &AccountId, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ) -> Result<(), Error> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.to_invalidate 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .insert(Ids::Transaction(transaction.id().clone()), ()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.to_invalidate.insert(Ids::Account(account.clone()), ()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self.inner 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .relate_account_to_transaction(transaction, account) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            .await 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 |