use google_cloud_gax::error::rpc::Status;
use std::error::Error;
pub use crate::from_value::ConvertError;
pub use wkt::{DurationError, TimestampError};
#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum SpannerInternalError {
#[error("unexpected data received from Spanner: {0}")]
UnexpectedData(String),
}
impl SpannerInternalError {
pub(crate) fn new(message: impl Into<String>) -> Self {
Self::UnexpectedData(message.into())
}
}
pub(crate) fn internal_error(message: impl Into<String>) -> crate::Error {
crate::Error::deser(SpannerInternalError::new(message))
}
#[derive(thiserror::Error, Debug)]
#[error("{status}")]
#[non_exhaustive]
pub struct BatchUpdateError {
pub update_counts: Vec<i64>,
#[source]
pub status: crate::Error,
}
impl BatchUpdateError {
pub fn extract(err: &crate::Error) -> Option<&Self> {
err.source()
.and_then(|source| source.downcast_ref::<BatchUpdateError>())
}
pub(crate) fn build_error(update_counts: Vec<i64>, grpc_status: Status) -> crate::Error {
let status = crate::Error::service(grpc_status.clone());
let err = Self {
update_counts,
status,
};
crate::Error::service_full(grpc_status, None, None, Some(Box::new(err)))
}
}
#[cfg(test)]
mod tests {
use super::*;
use google_cloud_gax::error::rpc::Code;
use static_assertions::assert_impl_all;
#[test]
fn auto_traits() {
assert_impl_all!(BatchUpdateError: Send, Sync, std::fmt::Debug);
}
#[test]
fn extract_success() {
let update_counts = vec![1, 2, 3];
let grpc_status = Status::default()
.set_code(Code::Aborted)
.set_message("Batch failed");
let err = BatchUpdateError::build_error(update_counts.clone(), grpc_status);
let extracted = BatchUpdateError::extract(&err).expect("should extract BatchUpdateError");
assert_eq!(extracted.update_counts, update_counts);
assert_eq!(
extracted
.status
.status()
.expect("status should be populated")
.code,
Code::Aborted
);
}
#[test]
fn extract_failure() {
let grpc_status = Status::default()
.set_code(Code::Unknown)
.set_message("Regular error");
let err = crate::Error::service(grpc_status);
let extracted = BatchUpdateError::extract(&err);
assert!(
extracted.is_none(),
"should not extract BatchUpdateError from standard service error"
);
}
}