recoverable_spawn/thread/async.rs
1use super::{r#trait::*, r#type::*};
2use once_cell::sync::Lazy;
3use runtime::Runtime;
4use std::sync::Arc;
5use std::thread::{JoinHandle, spawn};
6use task::JoinError;
7use tokio::*;
8
9static GLOBAL_RUNTIME: Lazy<Runtime> = Lazy::new(|| {
10 loop {
11 match Runtime::new() {
12 Ok(runtime) => return runtime,
13 Err(_) => {}
14 }
15 }
16});
17
18/// Executes a recoverable function within a panic-safe context.
19///
20/// - `func`: A function implementing the `AsyncRecoverableFunction` trait.
21/// - Returns: A `AsyncSpawnResult` indicating the success or failure of the function execution.
22pub fn run_function<F: AsyncRecoverableFunction>(func: F) -> AsyncSpawnResult {
23 let res: Result<(), JoinError> = GLOBAL_RUNTIME.block_on(async move {
24 let func = async move {
25 func.call().await;
26 };
27 return tokio::spawn(func).await;
28 });
29 return res;
30}
31
32/// Executes an error-handling function with a given error message within a panic-safe context.
33///
34/// - `func`: A function implementing the `AsyncErrorHandlerFunction` trait.
35/// - `error`: A string slice representing the error message.
36/// - Returns: A `AsyncSpawnResult` indicating the success or failure of the error-handling function execution.
37pub fn run_error_handle_function<E: AsyncErrorHandlerFunction>(
38 func: E,
39 error: Arc<String>,
40) -> AsyncSpawnResult {
41 let res: Result<(), JoinError> = GLOBAL_RUNTIME.block_on(async move {
42 let func = async move {
43 func.call(error.clone()).await;
44 };
45 return tokio::spawn(func).await;
46 });
47 return res;
48}
49
50/// Executes a recoverable function within a panic-safe context.
51///
52/// - `func`: A function implementing the `AsyncRecoverableFunction` trait.
53/// - Returns: A `AsyncSpawnResult` indicating the success or failure of the function execution.
54pub async fn async_run_function<F: AsyncRecoverableFunction>(func: F) -> AsyncSpawnResult {
55 let func = async move {
56 func.call().await;
57 };
58 return tokio::spawn(func).await;
59}
60
61/// Executes an error-handling function with a given error message within a panic-safe context.
62///
63/// - `func`: A function implementing the `AsyncErrorHandlerFunction` trait.
64/// - `error`: A string slice representing the error message.
65/// - Returns: A `AsyncSpawnResult` indicating the success or failure of the error-handling function execution.
66pub async fn async_run_error_handle_function<E: AsyncErrorHandlerFunction>(
67 func: E,
68 error: Arc<String>,
69) -> AsyncSpawnResult {
70 let func = async move {
71 func.call(error.clone()).await;
72 };
73 return tokio::spawn(func).await;
74}
75
76/// Converts a panic-captured error value into a string.
77///
78/// - `err`: The captured error value, of type `JoinError `.
79/// - Returns: A string representation of the error value.
80pub fn tokio_error_to_string(err: JoinError) -> String {
81 err.to_string()
82}
83
84/// Spawns a new thread to run the provided function `function` in a recoverable manner.
85/// If the function `function` panics during execution, the panic will be caught, and the thread
86/// will terminate without crashing the entire program.
87///
88/// # Parameters
89/// - `function`: A function of type `function` to be executed in the spawned thread. It must implement `FnOnce()`, `Send`, `Sync`, and `'static` traits.
90/// - `FnOnce()`: The function is callable with no arguments and no return value.
91/// - `Send`: The function can be safely transferred across thread boundaries.
92/// - `Sync`: The function can be shared across threads safely.
93/// - `'static`: The function does not contain references to non-static data (i.e., data that lives beyond the function's scope).
94///
95/// # Returns
96/// - A `JoinHandle<()>` representing the spawned thread. The thread can be joined later to wait for its completion.
97///
98///
99/// # Panics
100/// - This function itself will not panic, but the function `function` could panic during execution.
101/// The panic will be caught, preventing the program from crashing.
102pub fn recoverable_spawn<F>(function: F) -> JoinHandle<()>
103where
104 F: AsyncRecoverableFunction,
105{
106 spawn(|| {
107 let _: AsyncSpawnResult = run_function(function);
108 })
109}
110
111/// Spawns a new thread to run the provided function `function` in a recoverable manner.
112/// If the function `function` panics during execution, the panic will be caught, and the thread
113/// will terminate without crashing the entire program.
114///
115/// # Parameters
116/// - `function`: A function of type `function` to be executed in the spawned thread. It must implement `FnOnce()`, `Send`, `Sync`, and `'static` traits.
117/// - `FnOnce()`: The function is callable with no arguments and no return value.
118/// - `Send`: The function can be safely transferred across thread boundaries.
119/// - `Sync`: The function can be shared across threads safely.
120/// - `'static`: The function does not contain references to non-static data (i.e., data that lives beyond the function's scope).
121///
122/// # Returns
123/// - A `JoinHandle<()>` representing the spawned thread. The thread can be joined later to wait for its completion.
124///
125///
126/// # Panics
127/// - This function itself will not panic, but the function `function` could panic during execution.
128/// The panic will be caught, preventing the program from crashing.
129pub async fn async_recoverable_spawn<F>(function: F)
130where
131 F: AsyncRecoverableFunction,
132{
133 let _ = async_run_function(function).await;
134}
135
136/// Spawns a recoverable function with an error-handling function in a new thread.
137///
138/// - `function`: The primary function to execute, implementing the `AsyncRecoverableFunction` trait.
139/// - `error_handle_function`: A function to handle errors, implementing the `AsyncErrorHandlerFunction` trait.
140/// - Returns: A `JoinHandle<()>` that can be used to manage the spawned thread.
141pub fn recoverable_spawn_catch<F, E>(function: F, error_handle_function: E) -> JoinHandle<()>
142where
143 F: AsyncRecoverableFunction,
144 E: AsyncErrorHandlerFunction,
145{
146 spawn(|| {
147 let run_result: AsyncSpawnResult = run_function(function);
148 if let Err(err) = run_result {
149 let err_string: String = tokio_error_to_string(err);
150 let _: AsyncSpawnResult =
151 run_error_handle_function(error_handle_function, Arc::new(err_string));
152 }
153 })
154}
155
156/// Spawns a recoverable function with an error-handling function in a new thread.
157///
158/// - `function`: The primary function to execute, implementing the `AsyncRecoverableFunction` trait.
159/// - `error_handle_function`: A function to handle errors, implementing the `AsyncErrorHandlerFunction` trait.
160pub async fn async_recoverable_spawn_catch<F, E>(function: F, error_handle_function: E)
161where
162 F: AsyncRecoverableFunction,
163 E: AsyncErrorHandlerFunction,
164{
165 let run_result: AsyncSpawnResult = async_run_function(function).await;
166 if let Err(err) = run_result {
167 let err_string: String = tokio_error_to_string(err);
168 let _: AsyncSpawnResult =
169 async_run_error_handle_function(error_handle_function, Arc::new(err_string)).await;
170 }
171}
172
173/// Spawns an asynchronous recoverable function, catches any errors with an error-handling function,
174/// and ensures that a final function is always executed, regardless of whether an error occurred.
175///
176/// This function runs a series of operations in an asynchronous context, where:
177/// - `function` is executed first. If it results in an error, the `error_handle_function` is called.
178/// - After either the main function or the error handler finishes, the `finally` function is executed.
179/// This guarantees that the `finally` function runs regardless of the success or failure of the main operation.
180///
181/// # Parameters
182/// - `function`: The primary function to execute, which must implement the `AsyncRecoverableFunction` trait.
183/// - `error_handle_function`: A function that handles errors, which must implement the `AsyncErrorHandlerFunction` trait.
184/// - `finally`: A function that will be executed after the main function and error handler, which must implement the `AsyncRecoverableFunction` trait.
185///
186/// # Returns
187/// - A `JoinHandle<()>` that can be used to manage the spawned thread, ensuring that all the functions execute
188/// in a recoverable context and the final block always runs.
189///
190/// # Errors
191/// - If the `function` fails, the `error_handle_function` is invoked. If this fails as well, it will not stop the execution
192/// of the `finally` block.
193/// - The final block (`finally`) is always executed, even if the main function (`function`) or the error handler (`error_handle_function`) fails.
194/// Spawns an asynchronous recoverable function, catches any errors with an error-handling function,
195/// and ensures that a final function is always executed, regardless of whether an error occurred.
196///
197/// This function runs a series of operations in an asynchronous context, where:
198/// - `function` is executed first. If it results in an error, the `error_handle_function` is called.
199/// - After either the main function or the error handler finishes, the `finally` function is executed.
200/// This guarantees that the `finally` function runs regardless of the success or failure of the main operation.
201///
202/// # Parameters
203/// - `function`: The primary function to execute, which must implement the `AsyncRecoverableFunction` trait.
204/// - `error_handle_function`: A function that handles errors, which must implement the `AsyncErrorHandlerFunction` trait.
205/// - `finally`: A function that will be executed after the main function and error handler, which must implement the `AsyncRecoverableFunction` trait.
206///
207/// # Returns
208/// - A `JoinHandle<()>` that can be used to manage the spawned thread, ensuring that all the functions execute
209/// in a recoverable context and the final block always runs.
210///
211/// # Errors
212/// - If the `function` fails, the `error_handle_function` is invoked. If this fails as well, it will not stop the execution
213/// of the `finally` block.
214/// - The final block (`finally`) is always executed, even if the main function (`function`) or the error handler (`error_handle_function`) fails.
215pub fn recoverable_spawn_catch_finally<F, E, L>(
216 function: F,
217 error_handle_function: E,
218 finally: L,
219) -> JoinHandle<()>
220where
221 F: AsyncRecoverableFunction,
222 E: AsyncErrorHandlerFunction,
223 L: AsyncRecoverableFunction,
224{
225 spawn(|| {
226 let run_result: AsyncSpawnResult = run_function(function);
227 if let Err(err) = run_result {
228 let err_string: String = tokio_error_to_string(err);
229 let _: AsyncSpawnResult =
230 run_error_handle_function(error_handle_function, Arc::new(err_string));
231 }
232 let _: AsyncSpawnResult = run_function(finally);
233 })
234}
235
236/// Spawns an asynchronous recoverable function, catches any errors with an error-handling function,
237/// and ensures that a final function is always executed, regardless of whether an error occurred.
238///
239/// This function runs a series of operations in an asynchronous context, where:
240/// - `function` is executed first. If it results in an error, the `error_handle_function` is called.
241/// - After either the main function or the error handler finishes, the `finally` function is executed.
242/// This guarantees that the `finally` function runs regardless of the success or failure of the main operation.
243///
244/// # Parameters
245/// - `function`: The primary function to execute, which must implement the `AsyncRecoverableFunction` trait.
246/// - `error_handle_function`: A function that handles errors, which must implement the `AsyncErrorHandlerFunction` trait.
247/// - `finally`: A function that will be executed after the main function and error handler, which must implement the `AsyncRecoverableFunction` trait.
248///
249/// # Returns
250/// - A `JoinHandle<()>` that can be used to manage the spawned thread, ensuring that all the functions execute
251/// in a recoverable context and the final block always runs.
252///
253/// # Errors
254/// - If the `function` fails, the `error_handle_function` is invoked. If this fails as well, it will not stop the execution
255/// of the `finally` block.
256/// - The final block (`finally`) is always executed, even if the main function (`function`) or the error handler (`error_handle_function`) fails.
257/// Spawns an asynchronous recoverable function, catches any errors with an error-handling function,
258/// and ensures that a final function is always executed, regardless of whether an error occurred.
259///
260/// This function runs a series of operations in an asynchronous context, where:
261/// - `function` is executed first. If it results in an error, the `error_handle_function` is called.
262/// - After either the main function or the error handler finishes, the `finally` function is executed.
263/// This guarantees that the `finally` function runs regardless of the success or failure of the main operation.
264///
265/// # Parameters
266/// - `function`: The primary function to execute, which must implement the `AsyncRecoverableFunction` trait.
267/// - `error_handle_function`: A function that handles errors, which must implement the `AsyncErrorHandlerFunction` trait.
268/// - `finally`: A function that will be executed after the main function and error handler, which must implement the `AsyncRecoverableFunction` trait.
269///
270/// # Returns
271/// - A `JoinHandle<()>` that can be used to manage the spawned thread, ensuring that all the functions execute
272/// in a recoverable context and the final block always runs.
273///
274/// # Errors
275/// - If the `function` fails, the `error_handle_function` is invoked. If this fails as well, it will not stop the execution
276/// of the `finally` block.
277/// - The final block (`finally`) is always executed, even if the main function (`function`) or the error handler (`error_handle_function`) fails.
278pub async fn async_recoverable_spawn_catch_finally<F, E, L>(
279 function: F,
280 error_handle_function: E,
281 finally: L,
282) where
283 F: AsyncRecoverableFunction,
284 E: AsyncErrorHandlerFunction,
285 L: AsyncRecoverableFunction,
286{
287 let run_result: AsyncSpawnResult = async_run_function(function).await;
288 if let Err(err) = run_result {
289 let err_string: String = tokio_error_to_string(err);
290 let _: AsyncSpawnResult =
291 async_run_error_handle_function(error_handle_function, Arc::new(err_string)).await;
292 }
293 let _: AsyncSpawnResult = async_run_function(finally).await;
294}