Rust
El crate honk-me es un cliente asíncrono sobre Tokio y reqwest con rustls, así que no necesita OpenSSL. La feature blocking añade un cliente síncrono para scripts y CLI.
- Paquete
-
honk-mePublicado - Código fuente
- github.com/honk-me/honk-rust · Licencia MIT
- Requisitos
- Rust 1.85 o posterior.
Instalación
Para código síncrono: cargo add honk-me --features blocking.
cargo add honk-me
cargo add tokio --features macros,rt-multi-thread # if you don't have a runtime yet Quien tenga una clave de ingesta (honk_…) puede enviar mensajes a su proyecto. Guárdala en servidores, tareas y secretos de CI, nunca en un navegador ni en una app móvil o de escritorio.
Enviar un evento
O de forma explícita: Honk::new("https://honk-me.app", key)?. Clonar Honk es barato: crea uno y compártelo, para que las conexiones sigan abiertas.
use honk_me::Honk;
#[tokio::main]
async fn main() -> honk_me::Result<()> {
let honk = Honk::from_env()?; // HONK_URL, HONK_KEY (+ HONK_SOURCE, HONK_ENVIRONMENT, HONK_CHANNEL)
honk.beep("Backup finished", "nightly pg_dump took 42 s").await?;
Ok(())
} Receta: una solicitud de cliente en tu teléfono
Un grupo por solicitud y tu propia clave de idempotencia, para que un webhook reintentado nunca suene dos veces.
use honk_me::{Category, Message, Priority, Severity};
let msg = Message::new(format!("{} asked for a quote: {}", req.name, req.summary))
.title("New quote request")
.severity(Severity::LOUD)
.priority(Priority::High)
.category(Category::Customers)
.group_key(format!("requests/{}", req.id))
.url(format!("https://shop.example.com/admin/requests/{}", req.id)); // https only, "Open link"
honk.send(&msg, format!("request-{}", req.id).as_str()).await?; La escala Honk e incidentes
Cada helper devuelve un PendingSend: encadena más campos y después haz .await.
use honk_me::Priority;
honk.loud("Disk 91% full", "db-1 /var is at 91%")
.group_key("disk/db-1/var")
.priority(Priority::High)
.metadata("used_percent", 91)
.await?;
honk.problem("db/backup", "Backup failed", "pg_dump exited with 1").await?;
honk.recovery("db/backup", "Backup OK", "pg_dump finished").await?; El cliente bloqueante
Ejecuta el cliente asíncrono en un runtime privado de un solo hilo, con los mismos reintentos. No lo llames desde dentro de un runtime asíncrono.
// Cargo.toml: honk-me = { version = "0.2", features = ["blocking"] }
use honk_me::blocking::Honk;
let honk = Honk::from_env()?;
honk.beep("Backup finished", "nightly pg_dump took 42 s").send()?;
honk.send(&honk_me::Message::new("Imported 1 204 rows"), None)?; Errores
Cada variante de Error lleva un Failure con el estado, el código, cada campo no válido y retry_after.
use honk_me::Error;
match honk.send(&msg, "order-1042-failed").await {
Ok(_) => {}
Err(Error::Validation(f)) => tracing::error!(?f.fields, "a bug: don't retry"),
Err(e) if e.is_retryable() => queue.retry_later(e.idempotency_key(), e.retry_after()),
Err(e) => return Err(e.into()),
} Reintentos que nunca envían dos veces
- Cada envío lleva una
Idempotency-Key: la tuya o un UUIDv7 nuevo. La misma clave se reutiliza en cada reintento y, durante 24 horas, Honk responde a una repetición con el id original yduplicate: true, así que una respuesta perdida nunca crea un segundo mensaje. - Solo se reintentan los errores de red, los tiempos de espera agotados,
429y5xx, con backoff exponencial y jitter completo, y nunca antes delRetry-Afterdel servidor. Las demás respuestas4xxno se reintentan nunca: hay que corregir la solicitud. - Cada intento se corta a los 5 segundos y todo se detiene a los 30. Una espera que superaría ese plazo, como una cuota diaria que se reinicia a medianoche, falla al momento y te dice cuándo reintentar.
- Los campos se validan antes de enviar, y todos los errores de validación se devuelven juntos.