#![allow(
dead_code,
clippy::missing_docs_in_private_items,
clippy::print_stderr,
reason = "Example"
)]
use ::neuer_error::{NeuErr, Result, provided_attachments, traits::*};
use ::std::time::Duration;
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Default)]
enum ErrorStatus {
#[default]
Permanent,
Temporary,
Persistent,
}
provided_attachments!(
status(single: ErrorStatus) -> ErrorStatus { |status| status.copied().unwrap_or_default() }
);
fn do_request(_request: String) -> Result<(), std::io::Error> {
Err(std::io::Error::new(std::io::ErrorKind::NotFound, "Interface eth1 not found"))
}
fn fetch_data(user: &str) -> Result<()> {
let request = format!("https://test.test/users/{user}?authenticated=yes-trust-me");
do_request(request.clone())
.attach_override_with(|err| match err.kind() {
std::io::ErrorKind::NetworkDown => ErrorStatus::Temporary,
_ => ErrorStatus::Permanent,
})
.context_with(|| format!("Failed fetching data for user {user}"))?;
do_request(request).map_err(|err| {
let status = match err.kind() {
std::io::ErrorKind::NetworkDown => ErrorStatus::Temporary,
_ => ErrorStatus::Permanent,
};
NeuErr::new_with_source(format!("Failed fetching data for user {user}"), err)
.attach_override(status)
})?;
Ok(())
}
fn main() {
loop {
match fetch_data("alice") {
Ok(data) => {
eprintln!("Request successful, data: {data:?}");
break;
}
Err(err) => {
if err.status() == ErrorStatus::Temporary {
eprintln!("Error: {err:#}; Retrying request in a bit..");
std::thread::sleep(Duration::from_secs(2));
} else {
eprintln!("Permanent error fetching data: {err}");
break;
}
}
}
}
}