switchboard_solana/
macros.rs

1/// Macro used to include code if the target_os is not 'solana'.
2/// This is intended to be used for code that is primarily for off-chain Switchboard Functions.
3#[macro_export]
4macro_rules! cfg_client {
5    ($($item:item)*) => {
6        $(
7            #[cfg_attr(doc_cfg, doc(cfg(feature = "client")))]
8            #[cfg(feature = "client")]
9            $item
10        )*
11    };
12}
13
14/// Macro used to include code only if the target_os is 'solana'.
15/// This is intended to be used for code that is primarily for on-chain programs.
16#[macro_export]
17macro_rules! cfg_program {
18    ($($item:item)*) => {
19        $(
20            #[cfg_attr(doc_cfg, doc(cfg(not(feature = "client"))))]
21            #[cfg(not(feature = "client"))]
22            $item
23        )*
24    };
25}
26
27/// Macro used to include code if the feature 'secrets' is enabled.
28/// This is intended to be used for code that is primarily for off-chain Switchboard Secrets.
29#[macro_export]
30macro_rules! cfg_secrets {
31    ($($item:item)*) => {
32        $(
33            #[cfg(all(feature = "secrets", not(target_os = "solana")))]
34            #[cfg_attr(doc_cfg, doc(cfg(all(feature = "secrets", not(target_os = "solana")))))]
35            $item
36        )*
37    };
38}
39
40/// Macro used to include code if the feature 'macros' is enabled.
41#[macro_export]
42macro_rules! cfg_macros {
43    ($($item:item)*) => {
44        $(
45            #[cfg(all(feature = "macros", not(target_os = "solana")))]
46            #[cfg_attr(doc_cfg, doc(cfg(all(feature = "macros", not(target_os = "solana")))))]
47            $item
48        )*
49    };
50}
51
52/// Macro used to include IPFS code if the feature 'ipfs' is enabled.
53#[macro_export]
54macro_rules! cfg_ipfs {
55    ($($item:item)*) => {
56        $(
57            #[cfg(all(feature = "ipfs", not(target_os = "solana")))]
58            #[cfg_attr(doc_cfg, doc(cfg(all(feature = "ipfs", not(target_os = "solana")))))]
59            $item
60        )*
61    };
62}
63
64/// Retry a given expression a specified number of times with a delay between each attempt.
65///
66/// # Arguments
67///
68/// * `attempts` - The number of attempts to make.
69/// * `delay_ms` - The delay in milliseconds between each attempt.
70/// * `expr` - The expression to be retried.
71///
72/// # Returns
73///
74/// Returns a `Result` containing the value of the expression if it succeeds within the specified number of attempts,
75/// or an error if it fails on all attempts.
76///
77/// # Examples
78/// ```
79/// use switchboard_solana::retry;
80///
81/// // Retry a blockhash fetch 3 times with a delay of 500ms in between each failure
82/// let blockhash = retry!(3, 500, rpc.get_latest_blockhash().await)
83///     .await
84///     .map_err(|e| SbError::SolanaBlockhashFetchError(Arc::new(e)))?;
85/// ```
86#[cfg(not(target_os = "solana"))]
87#[cfg_attr(doc_cfg, doc(cfg(not(target_os = "solana"))))]
88#[macro_export]
89macro_rules! retry {
90    ($attempts:expr, $delay_ms:expr, $expr:expr) => {{
91        async {
92            let mut attempts = $attempts;
93            loop {
94                match $expr {
95                    Ok(val) => break Ok(val),
96                    Err(_) if attempts > 1 => {
97                        attempts -= 1;
98                        tokio::time::sleep(tokio::time::Duration::from_millis($delay_ms)).await;
99                    }
100                    Err(e) => break Err(e),
101                }
102            }
103        }
104    }};
105}
106
107/// Retry a given expression a specified number of times with a delay between each attempt.
108/// This will block the current thread until a value is resolved or the maximum number of attempts is reached.
109///
110/// # Arguments
111///
112/// * `attempts` - The number of attempts to make.
113/// * `delay_ms` - The delay in milliseconds between each attempt.
114/// * `expr` - The expression to be retried.
115///
116/// # Returns
117///
118/// Returns a `Result` containing the value of the expression if it succeeds within the specified number of attempts,
119/// or an error if it fails on all attempts.
120///
121/// # Examples
122/// ```
123/// use switchboard_solana::blocking_retry;
124///
125/// // Retry a blockhash fetch 3 times with a delay of 500ms in between each failure
126/// let blockhash = blocking_retry!(3, 500, rpc.get_latest_blockhash())
127///     .map_err(|e| SbError::SolanaBlockhashFetchError(Arc::new(e)))?;
128/// ```
129#[cfg(not(target_os = "solana"))]
130#[cfg_attr(doc_cfg, doc(cfg(not(target_os = "solana"))))]
131#[macro_export]
132macro_rules! blocking_retry {
133    ($attempts:expr, $delay_ms:expr, $expr:expr) => {{
134        let mut attempts = $attempts;
135        loop {
136            match $expr {
137                Ok(val) => break Ok(val),
138                Err(_) if attempts > 1 => {
139                    attempts -= 1;
140                    std::thread::sleep(tokio::time::Duration::from_millis($delay_ms));
141                }
142                Err(e) => break Err(e),
143            }
144        }
145    }};
146}