recoverable_spawn/thread/async.rs
1use super::{r#trait::*, r#type::*};
2use crate::*;
3use task::JoinError;
4use tokio::*;
5
6/// Executes a recoverable function within a panic-safe context.
7///
8/// - `func`: A function implementing the `AsyncRecoverableFunction` trait.
9/// - Returns: A `AsyncSpawnResult` indicating the success or failure of the function execution.
10pub async fn async_run_function<F: AsyncRecoverableFunction>(func: F) -> AsyncSpawnResult {
11 set_hook(Box::new(move |_| {}));
12 let func = async move {
13 func.call().await;
14 };
15 return tokio::spawn(func).await;
16}
17
18/// Executes an error-handling function with a given error message within a panic-safe context.
19///
20/// - `func`: A function implementing the `AsyncErrorHandlerFunction` trait.
21/// - `error`: A string slice representing the error message.
22/// - Returns: A `AsyncSpawnResult` indicating the success or failure of the error-handling function execution.
23pub async fn async_run_error_handle_function<E: AsyncErrorHandlerFunction>(
24 func: E,
25 error: Arc<String>,
26) -> AsyncSpawnResult {
27 set_hook(Box::new(move |_| {}));
28 let func = async move {
29 func.call(error.clone()).await;
30 };
31 return tokio::spawn(func).await;
32}
33
34/// Converts a panic-captured error value into a string.
35///
36/// - `err`: The captured error value, of type `&JoinError `.
37/// - Returns: A string representation of the error value.
38pub fn tokio_error_to_string(err: &JoinError) -> String {
39 err.to_string()
40}
41
42/// Spawns a new thread to run the provided function `function` in a recoverable manner.
43/// If the function `function` panics during execution, the panic will be caught, and the thread
44/// will terminate without crashing the entire program.
45///
46/// # Parameters
47/// - `function`: A function of type `function` to be executed in the spawned thread. It must implement `FnOnce()`, `Send`, `Sync`, and `'static` traits.
48/// - `FnOnce()`: The function is callable with no arguments and no return value.
49/// - `Send`: The function can be safely transferred across thread boundaries.
50/// - `Sync`: The function can be shared across threads safely.
51/// - `'static`: The function does not contain references to non-static data (i.e., data that lives beyond the function's scope).
52///
53/// # Returns
54/// - A `AsyncSpawnResult`
55///
56///
57/// # Panics
58/// - This function itself will not panic, but the function `function` could panic during execution.
59/// The panic will be caught, preventing the program from crashing.
60pub async fn async_recoverable_spawn<F>(function: F) -> AsyncSpawnResult
61where
62 F: AsyncRecoverableFunction,
63{
64 async_run_function(function).await
65}
66
67/// Spawns a recoverable function with an error-handling function in a new thread.
68///
69/// - `function`: The primary function to execute, implementing the `AsyncRecoverableFunction` trait.
70/// - `error_handle_function`: A function to handle errors, implementing the `AsyncErrorHandlerFunction` trait.
71pub async fn async_recoverable_spawn_catch<F, E>(
72 function: F,
73 error_handle_function: E,
74) -> AsyncSpawnResult
75where
76 F: AsyncRecoverableFunction,
77 E: AsyncErrorHandlerFunction,
78{
79 let run_result: AsyncSpawnResult = async_run_function(function).await;
80 if let Err(err) = run_result.as_ref() {
81 let err_string: String = tokio_error_to_string(err);
82 let _: AsyncSpawnResult =
83 async_run_error_handle_function(error_handle_function, Arc::new(err_string)).await;
84 }
85 return run_result;
86}
87
88/// Spawns an asynchronous recoverable function, catches any errors with an error-handling function,
89/// and ensures that a final function is always executed, regardless of whether an error occurred.
90///
91/// This function runs a series of operations in an asynchronous context, where:
92/// - `function` is executed first. If it results in an error, the `error_handle_function` is called.
93/// - After either the main function or the error handler finishes, the `finally` function is executed.
94/// This guarantees that the `finally` function runs regardless of the success or failure of the main operation.
95///
96/// # Parameters
97/// - `function`: The primary function to execute, which must implement the `AsyncRecoverableFunction` trait.
98/// - `error_handle_function`: A function that handles errors, which must implement the `AsyncErrorHandlerFunction` trait.
99/// - `finally`: A function that will be executed after the main function and error handler, which must implement the `AsyncRecoverableFunction` trait.
100///
101/// # Returns
102/// - A `JoinHandle<()>` that can be used to manage the spawned thread, ensuring that all the functions execute
103/// in a recoverable context and the final block always runs.
104///
105/// # Errors
106/// - If the `function` fails, the `error_handle_function` is invoked. If this fails as well, it will not stop the execution
107/// of the `finally` block.
108/// - The final block (`finally`) is always executed, even if the main function (`function`) or the error handler (`error_handle_function`) fails.
109/// Spawns an asynchronous recoverable function, catches any errors with an error-handling function,
110/// and ensures that a final function is always executed, regardless of whether an error occurred.
111///
112/// This function runs a series of operations in an asynchronous context, where:
113/// - `function` is executed first. If it results in an error, the `error_handle_function` is called.
114/// - After either the main function or the error handler finishes, the `finally` function is executed.
115/// This guarantees that the `finally` function runs regardless of the success or failure of the main operation.
116///
117/// # Parameters
118/// - `function`: The primary function to execute, which must implement the `AsyncRecoverableFunction` trait.
119/// - `error_handle_function`: A function that handles errors, which must implement the `AsyncErrorHandlerFunction` trait.
120/// - `finally`: A function that will be executed after the main function and error handler, which must implement the `AsyncRecoverableFunction` trait.
121///
122/// # Returns
123/// - A `AsyncSpawnResult`
124///
125/// # Errors
126/// - If the `function` fails, the `error_handle_function` is invoked. If this fails as well, it will not stop the execution
127/// of the `finally` block.
128/// - The final block (`finally`) is always executed, even if the main function (`function`) or the error handler (`error_handle_function`) fails.
129pub async fn async_recoverable_spawn_catch_finally<F, E, L>(
130 function: F,
131 error_handle_function: E,
132 finally: L,
133) -> AsyncSpawnResult
134where
135 F: AsyncRecoverableFunction,
136 E: AsyncErrorHandlerFunction,
137 L: AsyncRecoverableFunction,
138{
139 let run_result: AsyncSpawnResult = async_run_function(function).await;
140 if let Err(err) = run_result.as_ref() {
141 let err_string: String = tokio_error_to_string(err);
142 let _: AsyncSpawnResult =
143 async_run_error_handle_function(error_handle_function, Arc::new(err_string)).await;
144 }
145 let _: AsyncSpawnResult = async_run_function(finally).await;
146 return run_result;
147}