use std::sync::Arc;
use std::time::SystemTime;
use crate::error::{Error, Result};
use crate::message::{Accepted, Category, EventType, Message, MetadataValue, Priority, Severity};
#[derive(Clone, Debug)]
pub struct Honk {
inner: crate::Honk,
runtime: Arc<tokio::runtime::Runtime>,
}
impl Honk {
pub fn new(url: impl Into<String>, key: impl Into<String>) -> Result<Honk> {
crate::HonkBuilder::new().url(url).key(key).build_blocking()
}
pub fn from_env() -> Result<Honk> {
crate::HonkBuilder::from_env().build_blocking()
}
pub fn builder() -> crate::HonkBuilder {
crate::HonkBuilder::new()
}
pub(crate) fn from_async(inner: crate::Honk) -> Result<Honk> {
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.map_err(|e| {
Error::InvalidConfiguration(format!("could not start the blocking runtime: {e}"))
})?;
Ok(Honk {
inner,
runtime: Arc::new(runtime),
})
}
pub fn send<'k>(
&self,
message: &Message,
idempotency_key: impl Into<Option<&'k str>>,
) -> Result<Accepted> {
self.runtime
.block_on(self.inner.send(message, idempotency_key))
}
fn pending(&self, p: crate::PendingSend<'_>) -> PendingSend<'_> {
let (message, idempotency_key) = p.into_parts();
PendingSend {
honk: self,
message,
idempotency_key,
}
}
pub fn problem(
&self,
group_key: impl Into<String>,
title: impl Into<String>,
message: impl Into<String>,
) -> PendingSend<'_> {
self.pending(self.inner.problem(group_key, title, message))
}
pub fn recovery(
&self,
group_key: impl Into<String>,
title: impl Into<String>,
message: impl Into<String>,
) -> PendingSend<'_> {
self.pending(self.inner.recovery(group_key, title, message))
}
pub fn light(&self, title: impl Into<String>, message: impl Into<String>) -> PendingSend<'_> {
self.pending(self.inner.light(title, message))
}
pub fn beep(&self, title: impl Into<String>, message: impl Into<String>) -> PendingSend<'_> {
self.pending(self.inner.beep(title, message))
}
pub fn loud(&self, title: impl Into<String>, message: impl Into<String>) -> PendingSend<'_> {
self.pending(self.inner.loud(title, message))
}
pub fn long(&self, title: impl Into<String>, message: impl Into<String>) -> PendingSend<'_> {
self.pending(self.inner.long(title, message))
}
pub fn blast(&self, title: impl Into<String>, message: impl Into<String>) -> PendingSend<'_> {
self.pending(self.inner.blast(title, message))
}
pub fn info(&self, title: impl Into<String>, message: impl Into<String>) -> PendingSend<'_> {
self.light(title, message)
}
pub fn success(&self, title: impl Into<String>, message: impl Into<String>) -> PendingSend<'_> {
self.beep(title, message)
}
pub fn warning(&self, title: impl Into<String>, message: impl Into<String>) -> PendingSend<'_> {
self.loud(title, message)
}
pub fn error(&self, title: impl Into<String>, message: impl Into<String>) -> PendingSend<'_> {
self.long(title, message)
}
pub fn critical(
&self,
title: impl Into<String>,
message: impl Into<String>,
) -> PendingSend<'_> {
self.blast(title, message)
}
}
#[derive(Debug)]
#[must_use = "a PendingSend does nothing until send() is called"]
pub struct PendingSend<'a> {
honk: &'a Honk,
message: Message,
idempotency_key: Option<String>,
}
macro_rules! blocking_setters {
($($(#[$doc:meta])* $name:ident: $t:ty $(=> $conv:ident)?;)+) => {
$(
$(#[$doc])*
pub fn $name(mut self, value: $t) -> Self {
self.message = self.message.$name(value $(.$conv())?);
self
}
)+
};
}
impl PendingSend<'_> {
pub fn idempotency_key(mut self, key: impl Into<String>) -> Self {
self.idempotency_key = Some(key.into());
self
}
blocking_setters! {
severity: Severity;
priority: Priority;
category: Category;
source: impl Into<String> => into;
environment: impl Into<String> => into;
channel: impl Into<String> => into;
group_key: impl Into<String> => into;
event_type: EventType;
occurred_at: SystemTime;
url: impl Into<String> => into;
image_url: impl Into<String> => into;
ttl_seconds: u32;
source_sequence: u64;
}
pub fn action(mut self, title: impl Into<String>, url: impl Into<String>) -> Self {
self.message = self.message.action(title, url);
self
}
pub fn metadata(mut self, key: impl Into<String>, value: impl Into<MetadataValue>) -> Self {
self.message = self.message.metadata(key, value);
self
}
pub fn message(&self) -> &Message {
&self.message
}
pub fn send(self) -> Result<Accepted> {
self.honk
.send(&self.message, self.idempotency_key.as_deref())
}
}