mithril_common/cardano_block_scanner/interface.rs
1use async_trait::async_trait;
2
3use crate::cardano_block_scanner::{RawCardanoPoint, ScannedBlock};
4use crate::entities::{BlockNumber, SlotNumber};
5use crate::StdResult;
6
7/// A scanner that can read cardano transactions in a cardano database
8///
9/// If you want to mock it using mockall:
10/// ```
11/// mod test {
12/// use std::path::Path;
13///
14/// use anyhow::anyhow;
15/// use async_trait::async_trait;
16/// use mockall::mock;
17///
18/// use mithril_common::cardano_block_scanner::{BlockScanner, BlockStreamer, RawCardanoPoint};
19/// use mithril_common::entities::{BlockNumber};
20/// use mithril_common::StdResult;
21///
22/// mock! {
23/// pub BlockScannerImpl { }
24///
25/// #[async_trait]
26/// impl BlockScanner for BlockScannerImpl {
27/// async fn scan(
28/// &self,
29/// from: Option<RawCardanoPoint>,
30/// until: BlockNumber,
31/// ) -> StdResult<Box<dyn BlockStreamer>>;
32/// }
33/// }
34///
35/// #[test]
36/// fn test_mock() {
37/// let mut mock = MockBlockScannerImpl::new();
38/// mock.expect_scan().return_once(|_, _| {
39/// Err(anyhow!("parse error"))
40/// });
41/// }
42/// }
43/// ```
44#[async_trait]
45pub trait BlockScanner: Sync + Send {
46 /// Scan the transactions
47 async fn scan(
48 &self,
49 from: Option<RawCardanoPoint>,
50 until: BlockNumber,
51 ) -> StdResult<Box<dyn BlockStreamer>>;
52}
53
54/// [ChainScannedBlocks] allows to scan new blocks and handle rollbacks
55#[derive(Debug, Clone, PartialEq)]
56pub enum ChainScannedBlocks {
57 /// Roll forward on the chain to the next list of [ScannedBlock]
58 RollForwards(Vec<ScannedBlock>),
59 /// Roll backward on the chain to the previous [SlotNumber]
60 RollBackward(SlotNumber),
61}
62
63/// Trait that define how blocks are streamed from a Cardano database
64#[async_trait]
65pub trait BlockStreamer: Sync + Send {
66 /// Stream the next available blocks
67 async fn poll_next(&mut self) -> StdResult<Option<ChainScannedBlocks>>;
68
69 /// Get the last polled point of the chain
70 fn last_polled_point(&self) -> Option<RawCardanoPoint>;
71}
72
73cfg_test_tools! {
74 /// Tests extensions methods for the [BlockStreamer] trait.
75 #[async_trait]
76 pub trait BlockStreamerTestExtensions{
77 /// Stream all the available blocks, may be very memory intensive
78 async fn poll_all(&mut self) -> StdResult<Vec<ScannedBlock>>;
79 }
80
81 #[async_trait]
82 impl <S: BlockStreamer + ?Sized> BlockStreamerTestExtensions for S {
83 async fn poll_all(&mut self) -> StdResult<Vec<ScannedBlock>> {
84 let mut all_blocks = Vec::new();
85 while let Some(next_blocks) = self.poll_next().await? {
86 match next_blocks {
87 ChainScannedBlocks::RollForwards(mut forward_blocks) => {
88 all_blocks.append(&mut forward_blocks);
89 }
90 ChainScannedBlocks::RollBackward(_) => {
91 return Err(anyhow::anyhow!("poll_all: RollBackward not supported"));
92 }
93 };
94 }
95 Ok(all_blocks)
96 }
97 }
98
99}