feat: add retires and errors on uncessessful attempts
This commit is contained in:
parent
0c2e129bbd
commit
cfc5f01221
5 changed files with 136 additions and 28 deletions
|
|
@ -13,12 +13,19 @@ async fn main() -> Result<()> {
|
|||
tracing_subscriber::fmt::init();
|
||||
|
||||
const DEFAULT_GPIO_PIN: u8 = 17;
|
||||
const DEFAULT_WEBHOOK_RETRIES: u32 = 3;
|
||||
|
||||
let gpio_pin = std::env::var("GPIO_PIN")
|
||||
.ok()
|
||||
.and_then(|v| v.parse().ok())
|
||||
.unwrap_or(DEFAULT_GPIO_PIN);
|
||||
|
||||
let webhook_notifier = webhook::WebhookNotifier::new()?;
|
||||
let webhook_retries = std::env::var("WEBHOOK_RETRIES")
|
||||
.ok()
|
||||
.and_then(|v| v.parse().ok())
|
||||
.unwrap_or(DEFAULT_WEBHOOK_RETRIES);
|
||||
|
||||
let webhook_notifier = webhook::WebhookNotifier::new(webhook_retries)?;
|
||||
let mut gpio_monitor = gpio::GpioMonitor::new(gpio_pin, Duration::from_millis(100))?;
|
||||
|
||||
let callback = move |event: gpio::CircuitEvent| {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ use reqwest::Client;
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::fs;
|
||||
use tracing::{error, info};
|
||||
use std::time::Duration;
|
||||
use futures::future::join_all;
|
||||
|
||||
use crate::gpio::CircuitEvent;
|
||||
|
||||
|
|
@ -28,19 +30,75 @@ struct WebhookPayload {
|
|||
pub struct WebhookNotifier {
|
||||
client: Client,
|
||||
endpoints: Vec<Endpoint>,
|
||||
max_retries: u32,
|
||||
}
|
||||
|
||||
impl WebhookNotifier {
|
||||
pub fn new() -> Result<Self> {
|
||||
pub fn new(max_retries: u32) -> Result<Self> {
|
||||
let config = fs::read_to_string("endpoints.json")?;
|
||||
let endpoints_config: EndpointsConfig = serde_json::from_str(&config)?;
|
||||
|
||||
Ok(Self {
|
||||
client: Client::new(),
|
||||
endpoints: endpoints_config.endpoints,
|
||||
max_retries,
|
||||
})
|
||||
}
|
||||
|
||||
async fn send_webhook(&self, endpoint: &Endpoint, payload: &WebhookPayload) -> Result<()> {
|
||||
match self.client
|
||||
.post(&endpoint.url)
|
||||
.json(payload)
|
||||
.send()
|
||||
.await
|
||||
{
|
||||
Ok(response) => {
|
||||
if response.status().is_success() {
|
||||
info!(
|
||||
"Successfully sent webhook to {}: {}",
|
||||
endpoint.description,
|
||||
response.status()
|
||||
);
|
||||
Ok(())
|
||||
} else {
|
||||
error!(
|
||||
"Webhook request to {} failed with status: {}",
|
||||
endpoint.description,
|
||||
response.status()
|
||||
);
|
||||
Err(anyhow::anyhow!("Failed with status: {}", response.status()))
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
error!(
|
||||
"Failed to send webhook to {}: {}",
|
||||
endpoint.description,
|
||||
e
|
||||
);
|
||||
Err(anyhow::anyhow!("Request failed: {}", e))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn send_webhook_with_retries(&self, endpoint: &Endpoint, payload: &WebhookPayload) {
|
||||
let mut attempts = 0;
|
||||
|
||||
while attempts < self.max_retries {
|
||||
match self.send_webhook(endpoint, payload).await {
|
||||
Ok(_) => break,
|
||||
Err(e) => {
|
||||
attempts += 1;
|
||||
if attempts < self.max_retries {
|
||||
tokio::time::sleep(Duration::from_secs(1)).await;
|
||||
} else {
|
||||
error!("Failed to send webhook to {} after {} attempts: {}",
|
||||
endpoint.description, self.max_retries, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn notify_all(&self, event_type: &str, state: CircuitEvent) {
|
||||
let payload = WebhookPayload {
|
||||
event_type: event_type.to_string(),
|
||||
|
|
@ -48,29 +106,13 @@ impl WebhookNotifier {
|
|||
new_state: state.to_string(),
|
||||
};
|
||||
|
||||
for endpoint in &self.endpoints {
|
||||
info!("Sending webhook to {}: {}", endpoint.description, serde_json::to_string(&payload).unwrap());
|
||||
match self.client
|
||||
.post(&endpoint.url)
|
||||
.json(&payload)
|
||||
.send()
|
||||
.await
|
||||
{
|
||||
Ok(response) => {
|
||||
info!(
|
||||
"Successfully sent webhook to {}: {}",
|
||||
endpoint.description,
|
||||
response.status()
|
||||
);
|
||||
}
|
||||
Err(e) => {
|
||||
error!(
|
||||
"Failed to send webhook to {}: {}",
|
||||
endpoint.description,
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
let webhook_futures: Vec<_> = self.endpoints.iter()
|
||||
.map(|endpoint| {
|
||||
info!("Sending webhook to {}: {}", endpoint.description, serde_json::to_string(&payload).unwrap());
|
||||
self.send_webhook_with_retries(endpoint, &payload)
|
||||
})
|
||||
.collect();
|
||||
|
||||
join_all(webhook_futures).await;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue