Skip to main content

Crate diidi_travel_common_error

Crate diidi_travel_common_error 

Source
Expand description

Shared error layer for the DiiDi Travel monorepo.

Every service throws the same AppError — categorized, code-stable, context-rich, and source-chained. Cross-cutting concerns (HTTP status, gRPC status, JSON wire shape, severity ↔ tracing-level mapping) live here so each service doesn’t reinvent them.

§Quick start

use diidi_travel_common_error::{AppError, ErrorCategory, Result, ResultExt, bail, ensure};

fn lookup(id: u64) -> Result<&'static str> {
  ensure!(id != 0, ErrorCategory::Validation, "user.id.invalid", "id must be > 0");
  if id == 1 {
    return Ok("alice");
  }
  bail!(ErrorCategory::NotFound, "user.not_found", "no user with id {id}");
}

fn handle() -> Result<()> {
  let _name = lookup(0).err_context("operation", "handle")?;
  Ok(())
}

§Shape

Re-exports§

pub use crate::category::ErrorCategory;
pub use crate::category::UnknownCategory;
pub use crate::code::ErrorCode;
pub use crate::code::UNSPECIFIED;
pub use crate::context::ErrorContext;
pub use crate::error::AppError;
pub use crate::error::BoxedStdError;
pub use crate::response::ErrorResponse;
pub use crate::result::Result;
pub use crate::result::ResultExt;
pub use crate::severity::Severity;

Modules§

category
Broad error classification. Each category maps to standard HTTP / gRPC status codes so the same AppError can be surfaced through REST, gRPC, or message-bus replies without re-encoding.
code
Stable identifier for an error. Use const-able static codes for the common cases (const USER_NOT_FOUND: ErrorCode = ErrorCode::from_static("user.not_found");) and the ErrorCode::new constructor when the code is composed at runtime.
context
Open-ended key/value metadata attached to an AppError. Values are serde_json::Value so anything serializable can land here without expanding the public API.
error
The flagship AppError type. Designed to be the one error every service throws — flexible enough to encode the failure (category + stable code + free-text message + arbitrary context) and scalable across REST / gRPC / message-bus boundaries via the conversions in convert.
macros
Ergonomic macros that mirror anyhow::{bail, ensure} but produce AppError.
response
Wire-shape for sending an AppError back to a caller — typed for REST/JSON today, but the same shape works in any envelope that can carry a JSON object.
result
Result alias and ergonomic extension trait for layering context onto fallible operations.
severity
Severity of an AppError. Maps cleanly to tracing::Level so consumers can route the error through the logging stack without an extra translation table.

Macros§

app_error
Build an AppError inline using format! syntax for the message.
bail
Return early with an Err($crate::AppError::new(...)).
ensure
ensure!(cond, category, code, "message {}", arg) — if cond is false, returns early with an AppError, otherwise no-op.