pub enum ApiError {
NotFound(String),
Conflict(String),
BadRequest(String),
Forbidden(String),
TooManyRequests {
message: String,
retry_after_secs: u64,
},
GlobalCapacity {
message: String,
retry_after_secs: u64,
},
Unauthorized(String),
Internal(Error),
}Expand description
Every way a request can fail, already carrying the HTTP status it maps to – handlers
return Result<_, ApiError> and let ? do the conversion (see the From impls below),
the same “one error enum, converted at the boundary” shape bhtune-cli’s commands use
with anyhow::Result.
Variants§
NotFound(String)
The requested resource doesn’t exist (a template name, a run id). 404.
Conflict(String)
The request conflicts with existing state (a name collision on create, a delete blocked by a foreign-key reference). 409.
BadRequest(String)
The request body/query itself is malformed or fails domain validation
(DcsTemplate::validate, an unparseable filter value axum’s extractors didn’t already
reject). 400.
Forbidden(String)
The request was authenticated but is not permitted. 403.
TooManyRequests
A per-client or per-session limit was exceeded. 429, with a Retry-After header.
GlobalCapacity
The public demo has exhausted a global capacity limit. 503, with a Retry-After
header. Keeping this distinct from per-client throttling lets callers avoid telling a
client that its own request rate caused shared service saturation.
No valid demo identity was supplied. 401.
Internal(Error)
Anything else: a database connection/query failure, or any other unexpected error.
Deliberately doesn’t echo the underlying error’s Display text into the response body
(logged via tracing::error! instead) – an internal error’s detail is for the
server’s own logs, not a client that can’t act on it. 500.
Trait Implementations§
Source§impl From<DbError> for ApiError
impl From<DbError> for ApiError
Source§fn from(err: DbError) -> Self
fn from(err: DbError) -> Self
bhtune_db::DbError::TemplateInUse is the one variant a client can actually act on
(stop trying to delete a template still referenced by a saved loop) – everything else
is an infrastructure-level failure the client can’t distinguish or fix, so it collapses
to ApiError::Internal.
Auto Trait Implementations§
impl Freeze for ApiError
impl RefUnwindSafe for ApiError
impl Send for ApiError
impl Sync for ApiError
impl Unpin for ApiError
impl UnsafeUnpin for ApiError
impl UnwindSafe for ApiError
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request§impl<L> LayerExt<L> for L
impl<L> LayerExt<L> for L
§fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>where
L: Layer<S>,
fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>where
L: Layer<S>,
Layered].