use crate::error::ClientError;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct SeqBlock {
pub start: u64,
pub count: u32,
pub epoch: u128,
}
#[cfg_attr(test, derive(Debug))]
pub(crate) enum SeqAttemptOutcome {
LeaderHint {
endpoint: String,
epoch: Option<u128>,
},
Uncertain,
Err(ClientError),
}
pub(crate) fn classify_seq_status(status: tonic::Status, sent: bool) -> SeqAttemptOutcome {
use tonic::Code;
match status.code() {
Code::InvalidArgument | Code::ResourceExhausted | Code::Unimplemented => {
SeqAttemptOutcome::Err(ClientError::from(status))
}
_ if sent => SeqAttemptOutcome::Uncertain,
_ => SeqAttemptOutcome::Err(ClientError::from(status)),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn classify_unavailable_after_send_is_uncertain() {
let status = tonic::Status::unavailable("connection reset");
let outcome = classify_seq_status(status, true);
assert!(matches!(outcome, SeqAttemptOutcome::Uncertain));
}
#[test]
fn classify_unavailable_before_send_is_definitive() {
let status = tonic::Status::unavailable("no connection established");
let outcome = classify_seq_status(status, false);
assert!(matches!(
outcome,
SeqAttemptOutcome::Err(ClientError::Rpc(_))
));
}
#[test]
fn classify_internal_after_send_is_uncertain() {
let status = tonic::Status::internal("permanent driver fault");
let outcome = classify_seq_status(status, true);
assert!(
matches!(outcome, SeqAttemptOutcome::Uncertain),
"post-send INTERNAL must be Uncertain",
);
}
#[test]
fn classify_resource_exhausted_after_send_is_definitive() {
let status = tonic::Status::resource_exhausted("cardinality cap reached");
let outcome = classify_seq_status(status, true);
assert!(
matches!(outcome, SeqAttemptOutcome::Err(_)),
"post-send ResourceExhausted is pre-commit-certain → definitive Err",
);
}
#[test]
fn classify_unimplemented_after_send_is_definitive() {
let status = tonic::Status::unimplemented("dense sequences unsupported");
let outcome = classify_seq_status(status, true);
assert!(
matches!(outcome, SeqAttemptOutcome::Err(_)),
"post-send UNIMPLEMENTED is pre-commit-certain → definitive Err",
);
}
}