use std::time::Duration;
pub mod error;
pub mod models;
pub mod providers;
pub mod validacao;
pub use error::CepError;
pub use models::Endereco;
pub use providers::{ProviderType, consultar as consultar_provedor};
pub use validacao::{normalizar_cep, formatar_cep};
pub use providers::consultar;
pub use providers::{
opencep,
brasilapi,
viacep,
apicep
};
const PROVEDORES_FALLBACK: &[ProviderType] = &[
ProviderType::OpenCep,
ProviderType::BrasilApi,
ProviderType::ViaCep,
ProviderType::ApiCep,
];
pub async fn consultar_com_fallback(
cep: &str,
timeout: Option<Duration>,
) -> Result<Endereco, CepError> {
let cep_normalizado = validacao::normalizar_cep(cep)?;
let timeout = timeout.unwrap_or(Duration::from_secs(3));
let mut ultimo_erro = None;
for &provedor in PROVEDORES_FALLBACK {
match tokio::time::timeout(timeout, consultar_provedor(provedor, &cep_normalizado)).await {
Ok(Ok(endereco)) => return Ok(endereco),
Ok(Err(e)) => {
log::warn!("Falha no provedor {}: {}", provedor, e);
ultimo_erro = Some(e);
},
Err(_) => {
log::warn!("Timeout no provedor {}", provedor);
ultimo_erro = Some(CepError::ProvedorIndisponivel(provedor.to_string()));
},
}
}
Err(ultimo_erro.unwrap_or(CepError::SemProvedoresDisponiveis))
}