use axum::Json;
use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use thiserror::Error;
#[derive(Debug, Error, PartialEq, Eq)]
pub enum BusError {
#[error(
"no live instance registered for definition '{definition_id}' \
(durable inbox queueing is DOC-60 §7, not implemented)"
)]
NoLiveInstance {
definition_id: String,
},
#[error(
"instance '{instance_id}' is no longer live; the sender's specific \
target is gone and was NOT redirected to another instance of its \
definition — re-resolve by definition_id if any instance will do"
)]
InstanceGone {
instance_id: String,
},
#[error(
"instance '{instance_id}' is registered but has no attached \
subscriber; the message was not delivered"
)]
NoSubscriber {
instance_id: String,
},
#[error(
"sender instance '{instance_id}' is not a live registration; a peer \
message must be sent by a registered instance (DOC-60 §6b/§6c)"
)]
UnregisteredSender {
instance_id: String,
},
#[error(
"caller kind {kind:?} may not publish on the peer path; DOC-60 §5.3 \
carries assistant_instance senders only (§5.1/§5.2 edges are not \
routed here)"
)]
CallerKindNotPermitted {
kind: super::envelope::CallerKind,
},
#[error("invalid definition id '{definition_id}': {reason}")]
InvalidDefinitionId {
definition_id: String,
reason: String,
},
#[error("invalid target: {0}")]
InvalidTarget(String),
#[error("invalid caller identity: {0}")]
InvalidCaller(String),
}
impl BusError {
pub fn status(&self) -> StatusCode {
match self {
Self::UnregisteredSender { .. } => StatusCode::FORBIDDEN,
Self::NoLiveInstance { .. } => StatusCode::NOT_FOUND,
Self::InstanceGone { .. } => StatusCode::GONE,
Self::NoSubscriber { .. } => StatusCode::CONFLICT,
Self::InvalidDefinitionId { .. }
| Self::InvalidTarget(_)
| Self::InvalidCaller(_)
| Self::CallerKindNotPermitted { .. } => StatusCode::BAD_REQUEST,
}
}
}
impl IntoResponse for BusError {
fn into_response(self) -> Response {
let status = self.status();
(
status,
Json(serde_json::json!({ "error": self.to_string() })),
)
.into_response()
}
}