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}