use thiserror::Error;
pub use crate::messenger::RequestError;
pub use crate::protocol::error::Error as ProtocolError;
#[derive(Debug)]
#[non_exhaustive]
pub enum RequestContext {
Topic(String),
Partition(String, i32),
#[non_exhaustive]
Fetch {
topic_name: String,
partition_id: i32,
offset: i64,
},
}
#[derive(Debug)]
#[allow(missing_copy_implementations)] #[non_exhaustive]
pub enum ServerErrorResponse {
LeaderForward {
broker: i32,
new_leader: i32,
},
PartitionFetchState {
high_watermark: i64,
last_stable_offset: Option<i64>,
},
}
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum Error {
#[error("Connection error: {0}")]
Connection(#[from] crate::connection::Error),
#[error("Request error: {0}")]
Request(#[from] RequestError),
#[error("Invalid response: {0}")]
InvalidResponse(String),
#[error(
"Server error {} with message \"{}\", request: {:?}, response: {:?}, virtual: {}",
protocol_error,
string_or_na(error_message),
request,
response,
is_virtual
)]
ServerError {
protocol_error: ProtocolError,
error_message: Option<String>,
request: RequestContext,
response: Option<ServerErrorResponse>,
is_virtual: bool,
},
#[error("All retries failed: {0}")]
RetryFailed(#[from] crate::backoff::BackoffError),
#[error("Timeout")]
Timeout,
}
impl Error {
pub(crate) fn exactly_one_topic(len: usize) -> Self {
Self::InvalidResponse(format!("Expected a single topic in response, got {len}"))
}
pub(crate) fn exactly_one_partition(len: usize) -> Self {
Self::InvalidResponse(format!(
"Expected a single partition in response, got {len}"
))
}
}
pub type Result<T, E = Error> = std::result::Result<T, E>;
fn string_or_na(s: &Option<String>) -> &str {
match s {
Some(s) => s.as_str(),
None => "n/a",
}
}