tsubakuro_rust_core/transaction/
error_info.rs

1use std::sync::Arc;
2
3use crate::{
4    error::{DiagnosticCode, TgError},
5    invalid_response_error,
6    jogasaki::proto::sql::response::response::Response as SqlResponseType,
7    prelude::convert_sql_response,
8    session::wire::{response::WireResponse, response_box::SlotEntryHandle},
9    sql_service_error,
10};
11
12/// Transaction error information.
13///
14/// since 0.2.0
15#[derive(Debug)]
16pub struct TransactionErrorInfo {
17    server_error: Option<TgError>,
18}
19
20impl TransactionErrorInfo {
21    pub(crate) fn new(server_error: Option<TgError>) -> TransactionErrorInfo {
22        TransactionErrorInfo { server_error }
23    }
24
25    /// Returns occurred error in the target transaction, only if the transaction has been accidentally aborted.
26    pub fn server_error(&self) -> Option<&TgError> {
27        self.server_error.as_ref()
28    }
29
30    /// Whether the status is normal.
31    pub fn is_normal(&self) -> bool {
32        self.server_error.is_none()
33    }
34
35    /// Whether the status is error.
36    pub fn is_error(&self) -> bool {
37        self.server_error.is_some()
38    }
39
40    /// Returns diagnostic code if error occurred in the target transaction.
41    pub fn diagnostic_code(&self) -> Option<&DiagnosticCode> {
42        match &self.server_error {
43            Some(TgError::ServerError(_, _, code, _)) => Some(code),
44            _ => None,
45        }
46    }
47}
48
49pub(crate) fn transaction_error_info_processor(
50    _: Arc<SlotEntryHandle>,
51    response: WireResponse,
52) -> Result<TransactionErrorInfo, TgError> {
53    const FUNCTION_NAME: &str = "transaction_error_info_processor()";
54
55    let (sql_response, _) = convert_sql_response(FUNCTION_NAME, &response)?;
56    let message = sql_response.ok_or(invalid_response_error!(
57        FUNCTION_NAME,
58        format!("response {:?} is not ResponseSessionPayload", response),
59    ))?;
60
61    use crate::jogasaki::proto::sql::response::get_error_info::Result;
62    match message.response {
63        Some(SqlResponseType::GetErrorInfo(info)) => match info.result {
64            Some(Result::Success(error)) => Ok(TransactionErrorInfo::new(Some(
65                sql_service_error!(FUNCTION_NAME, error),
66            ))),
67            Some(Result::ErrorNotFound(_)) => Ok(TransactionErrorInfo::new(None)),
68            Some(Result::Error(error)) => Err(sql_service_error!(FUNCTION_NAME, error)),
69            None => Err(invalid_response_error!(
70                FUNCTION_NAME,
71                format!("response GetErrorInfo.result is None"),
72            )),
73        },
74        _ => Err(invalid_response_error!(
75            FUNCTION_NAME,
76            format!("response {:?} is not GetErrorInfo", message.response),
77        )),
78    }
79}