use anyhow::{Context, Result as AnyhowResult};
use tonic::Status;
pub type LiquidCacheResult<T> = AnyhowResult<T>;
pub trait LiquidCacheErrorExt<T> {
fn with_liquid_context(self, message: impl Into<String>) -> LiquidCacheResult<T>;
}
impl<T, E> LiquidCacheErrorExt<T> for Result<T, E>
where
E: std::error::Error + Send + Sync + 'static,
{
fn with_liquid_context(self, message: impl Into<String>) -> LiquidCacheResult<T> {
self.map_err(anyhow::Error::from).context(message.into())
}
}
pub fn anyhow_to_status(err: anyhow::Error) -> Status {
let error_with_context = format!("{err:?}");
if let Some(datafusion_err) = err.downcast_ref::<datafusion::error::DataFusionError>() {
match datafusion_err {
datafusion::error::DataFusionError::Plan(_) => {
Status::invalid_argument(error_with_context)
}
datafusion::error::DataFusionError::SchemaError(_, _) => {
Status::invalid_argument(error_with_context)
}
_ => Status::internal(error_with_context),
}
} else if err.downcast_ref::<url::ParseError>().is_some()
|| err.downcast_ref::<uuid::Error>().is_some()
{
Status::invalid_argument(error_with_context)
} else if err.downcast_ref::<object_store::Error>().is_some() {
Status::internal(error_with_context)
} else {
Status::internal(error_with_context)
}
}
pub fn df_error_to_status_with_trace(err: datafusion::error::DataFusionError) -> Status {
anyhow_to_status(err.into())
}