Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[common/exception] concat ErrorCodes with its cause in display_text, instead of using cause #719

Merged
merged 1 commit into from
Jun 4, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 16 additions & 17 deletions common/exception/src/exception.rs
Original file line number Diff line number Diff line change
@@ -33,6 +33,8 @@ impl ToString for ErrorCodesBacktrace {
pub struct ErrorCodes {
code: u16,
display_text: String,
// cause is only used to contain an `anyhow::Error`.
// TODO: remove `cause` when we completely get rid of `anyhow::Error`.
cause: Option<Box<dyn std::error::Error + Sync + Send>>,
backtrace: Option<ErrorCodesBacktrace>,
}
@@ -266,41 +268,38 @@ impl ErrorCodes {
///
/// let x: std::result::Result<(), std::fmt::Error> = Err(std::fmt::Error {});
/// let y: common_exception::Result<()> =
/// x.map_err_to_code(ErrorCodes::UnknownException, || format!("{}", 123));
/// x.map_err_to_code(ErrorCodes::UnknownException, || 123);
///
/// assert_eq!(
/// "Code: 1000, displayText = Error.",
/// "Code: 1000, displayText = 123, cause: an error occurred when formatting an argument.",
/// format!("{}", y.unwrap_err())
/// );
/// ```
pub trait ToErrorCodes<T, E, ToStrFn> {
pub trait ToErrorCodes<T, E, CtxFn> {
/// Wrap the error value with ErrorCodes that is evaluated lazily
/// only once an error does occur.
///
/// `err_code_fn` is one of the ErrorCodes builder function such as `ErrorCodes::Ok`.
/// `context_fn` builds display_text for the ErrorCodes.
fn map_err_to_code<ToStr, ErrFn>(self, err_code_fn: ErrFn, context_fn: ToStrFn) -> Result<T>
fn map_err_to_code<ErrFn, D>(self, err_code_fn: ErrFn, context_fn: CtxFn) -> Result<T>
where
ToStr: Into<String>,
ErrFn: FnOnce(ToStr) -> ErrorCodes,
ToStrFn: FnOnce() -> ToStr;
ErrFn: FnOnce(String) -> ErrorCodes,
D: Display,
CtxFn: FnOnce() -> D;
}

impl<T, E, ToStrFn> ToErrorCodes<T, E, ToStrFn> for std::result::Result<T, E>
impl<T, E, CtxFn> ToErrorCodes<T, E, CtxFn> for std::result::Result<T, E>
where E: std::error::Error + Send + Sync + 'static
{
fn map_err_to_code<ToStr, ErrFn>(self, make_exception: ErrFn, context_fn: ToStrFn) -> Result<T>
fn map_err_to_code<ErrFn, D>(self, make_exception: ErrFn, context_fn: CtxFn) -> Result<T>
where
ToStr: Into<String>,
ErrFn: FnOnce(ToStr) -> ErrorCodes,
ToStrFn: FnOnce() -> ToStr,
ErrFn: FnOnce(String) -> ErrorCodes,
D: Display,
CtxFn: FnOnce() -> D,
{
self.map_err(|error| {
let mut x = make_exception(context_fn());
x.cause = Some(Box::new(error));
x
let err_text = format!("{}, cause: {}", context_fn(), error);
make_exception(err_text)
})

// read().with(ErrorCodes::FileKeyNotFound, || format!("{}", key))
}
}
18 changes: 13 additions & 5 deletions common/exception/src/exception_test.rs
Original file line number Diff line number Diff line change
@@ -30,12 +30,20 @@ fn test_derive_from_std_error() {
use crate::exception::ErrorCodes;
use crate::exception::ToErrorCodes;

let x: std::result::Result<(), std::fmt::Error> = Err(std::fmt::Error {});
let y: crate::exception::Result<()> =
x.map_err_to_code(ErrorCodes::UnknownException, || format!("{}", 123));
let fmt_rst: std::result::Result<(), std::fmt::Error> = Err(std::fmt::Error {});

let rst1: crate::exception::Result<()> =
fmt_rst.map_err_to_code(ErrorCodes::UnknownException, || 123);

assert_eq!(
"Code: 1000, displayText = 123, cause: an error occurred when formatting an argument.",
format!("{}", rst1.as_ref().unwrap_err())
);

let rst2: crate::exception::Result<()> = rst1.map_err_to_code(ErrorCodes::Ok, || "wrapper");

assert_eq!(
"Code: 1000, displayText = Error.",
format!("{}", y.unwrap_err())
"Code: 0, displayText = wrapper, cause: Code: 1000, displayText = 123, cause: an error occurred when formatting an argument..",
format!("{}", rst2.as_ref().unwrap_err())
);
}