mithril_client_cli/utils/
cardano_db.rs

1use anyhow::anyhow;
2use futures::Future;
3use indicatif::{MultiProgress, ProgressBar};
4use std::time::Duration;
5
6use super::CardanoDbDownloadCheckerError;
7use mithril_client::{MithrilError, MithrilResult};
8
9/// Utility functions for to the CardanoDb commands
10pub struct CardanoDbUtils;
11
12impl CardanoDbUtils {
13    /// Handle the error return by `check_prerequisites`
14    pub fn check_disk_space_error(error: MithrilError) -> MithrilResult<String> {
15        match error.downcast_ref::<CardanoDbDownloadCheckerError>() {
16            Some(CardanoDbDownloadCheckerError::NotEnoughSpaceForArchive { .. })
17            | Some(CardanoDbDownloadCheckerError::NotEnoughSpaceForUncompressedData { .. }) => {
18                Ok(format!("Warning: {error}"))
19            }
20            _ => Err(error),
21        }
22    }
23
24    /// Display a spinner while waiting for the result of a future
25    pub async fn wait_spinner<T, E>(
26        progress_bar: &MultiProgress,
27        future: impl Future<Output = Result<T, E>>,
28    ) -> MithrilResult<T>
29    where
30        MithrilError: From<E>,
31    {
32        let pb = progress_bar.add(ProgressBar::new_spinner());
33        let spinner = async move {
34            loop {
35                pb.tick();
36                tokio::time::sleep(Duration::from_millis(50)).await;
37            }
38        };
39
40        tokio::select! {
41            _ = spinner => Err(anyhow!("timeout")),
42            res = future => res.map_err(Into::into),
43        }
44    }
45
46    pub fn format_bytes_to_gigabytes(bytes: u64) -> String {
47        let size_in_giga = bytes as f64 / (1024.0 * 1024.0 * 1024.0);
48
49        format!("{size_in_giga:.2} GiB")
50    }
51}
52
53#[cfg(test)]
54mod test {
55    use super::*;
56    use std::path::PathBuf;
57
58    #[test]
59    fn check_disk_space_error_should_return_warning_message_if_error_is_not_enough_space_for_archive()
60     {
61        let not_enough_space_error = CardanoDbDownloadCheckerError::NotEnoughSpaceForArchive {
62            left_space: 1_f64,
63            pathdir: PathBuf::new(),
64            archive_size: 2_f64,
65        };
66        let expected = format!("Warning: {not_enough_space_error}");
67
68        let result = CardanoDbUtils::check_disk_space_error(anyhow!(not_enough_space_error))
69            .expect("check_disk_space_error should not error");
70
71        assert!(result.contains(&expected));
72    }
73
74    #[test]
75    fn check_disk_space_error_should_return_warning_message_if_error_is_not_enough_space_for_uncompressed_data()
76     {
77        let not_enough_space_error =
78            CardanoDbDownloadCheckerError::NotEnoughSpaceForUncompressedData {
79                left_space: 1_f64,
80                pathdir: PathBuf::new(),
81                db_size: 2_f64,
82            };
83        let expected = format!("Warning: {not_enough_space_error}");
84
85        let result = CardanoDbUtils::check_disk_space_error(anyhow!(not_enough_space_error))
86            .expect("check_disk_space_error should not error");
87
88        assert!(result.contains(&expected));
89    }
90
91    #[test]
92    fn check_disk_space_error_should_return_error_if_error_is_not_error_not_enough_space() {
93        let error = CardanoDbDownloadCheckerError::UnpackDirectoryNotEmpty(PathBuf::new());
94
95        let error = CardanoDbUtils::check_disk_space_error(anyhow!(error))
96            .expect_err("check_disk_space_error should fail");
97
98        assert!(
99            matches!(
100                error.downcast_ref::<CardanoDbDownloadCheckerError>(),
101                Some(CardanoDbDownloadCheckerError::UnpackDirectoryNotEmpty(_))
102            ),
103            "Unexpected error: {error:?}"
104        );
105    }
106
107    #[test]
108    fn format_bytes_to_gigabytes_zero() {
109        let one_gigabyte = 1024 * 1024 * 1024;
110
111        assert_eq!(CardanoDbUtils::format_bytes_to_gigabytes(0), "0.00 GiB");
112
113        assert_eq!(
114            CardanoDbUtils::format_bytes_to_gigabytes(one_gigabyte),
115            "1.00 GiB"
116        );
117
118        assert_eq!(
119            CardanoDbUtils::format_bytes_to_gigabytes(one_gigabyte / 2),
120            "0.50 GiB"
121        );
122
123        assert_eq!(
124            CardanoDbUtils::format_bytes_to_gigabytes(one_gigabyte * 10),
125            "10.00 GiB"
126        );
127    }
128}