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