aimdb_tokio_adapter/
error.rs1use aimdb_core::DbError;
10
11const RUNTIME_ERROR_BASE: u16 = 0x7100;
13
14const TASK_COMPONENT_ID: u8 = 12;
16
17pub trait TokioErrorSupport {
26 fn from_join_error(error: tokio::task::JoinError) -> Self;
39}
40
41impl TokioErrorSupport for DbError {
42 fn from_join_error(error: tokio::task::JoinError) -> Self {
48 if error.is_cancelled() {
49 DbError::ResourceUnavailable {
50 resource_type: TASK_COMPONENT_ID,
51 resource_name: "Task was cancelled".to_string(),
52 }
53 } else if error.is_panic() {
54 DbError::Internal {
55 code: (RUNTIME_ERROR_BASE | 0x02) as u32,
56 message: "Task panicked".to_string(),
57 }
58 } else {
59 DbError::ResourceUnavailable {
60 resource_type: TASK_COMPONENT_ID,
61 resource_name: format!("Task join error: {}", error),
62 }
63 }
64 }
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70 use std::time::Duration;
71
72 #[tokio::test]
73 async fn test_join_error_conversion_cancelled() {
74 let handle = tokio::spawn(async {
76 tokio::time::sleep(Duration::from_millis(1000)).await;
77 });
78 handle.abort();
79
80 let result = handle.await;
81 match result {
82 Err(join_error) => {
83 let db_error = DbError::from_join_error(join_error);
84 if let DbError::ResourceUnavailable { resource_name, .. } = db_error {
85 assert!(resource_name.contains("cancelled"));
86 } else {
87 panic!("Expected ResourceUnavailable variant for cancelled task");
88 }
89 }
90 Ok(_) => panic!("Expected join error"),
91 }
92 }
93
94 #[tokio::test]
95 async fn test_join_error_conversion_panic() {
96 let handle = tokio::spawn(async { panic!("test panic") });
98
99 let result = handle.await;
100 match result {
101 Err(join_error) => {
102 let db_error = DbError::from_join_error(join_error);
103 if let DbError::Internal { code, message } = db_error {
104 assert_eq!(code, (RUNTIME_ERROR_BASE | 0x02) as u32);
105 assert!(message.contains("panicked"));
106 } else {
107 panic!("Expected Internal variant for panicked task");
108 }
109 }
110 Ok(_) => panic!("Expected join error"),
111 }
112 }
113
114 #[test]
115 fn test_error_categorization() {
116 let rt = tokio::runtime::Runtime::new().unwrap();
118 let handle = rt.spawn(async {
119 tokio::time::sleep(Duration::from_secs(10)).await;
120 });
121 handle.abort();
122
123 let result = rt.block_on(handle);
124 if let Err(join_error) = result {
125 let db_error = DbError::from_join_error(join_error);
126 assert!(matches!(db_error, DbError::ResourceUnavailable { .. }));
127 }
128 }
129}