mirror of
https://github.com/rustfs/rustfs.git
synced 2026-01-17 01:30:33 +00:00
- Add core event notification interfaces - Support multiple notification backends: - Webhook (default) - Kafka - MQTT - HTTP Producer - Implement configurable event filtering - Add async event dispatching with backpressure handling - Provide serialization/deserialization for event payloads This module enables system events to be published to various endpoints with consistent delivery guarantees and failure handling.
64 lines
2.0 KiB
Rust
64 lines
2.0 KiB
Rust
use crate::ChannelAdapter;
|
|
use crate::Error;
|
|
use crate::Event;
|
|
use crate::WebhookConfig;
|
|
use async_trait::async_trait;
|
|
use reqwest::{Client, RequestBuilder};
|
|
use std::time::Duration;
|
|
use tokio::time::sleep;
|
|
|
|
/// Webhook adapter for sending events to a webhook endpoint.
|
|
pub struct WebhookAdapter {
|
|
config: WebhookConfig,
|
|
client: Client,
|
|
}
|
|
|
|
impl WebhookAdapter {
|
|
/// Creates a new Webhook adapter.
|
|
pub fn new(config: WebhookConfig) -> Self {
|
|
let client = Client::builder()
|
|
.timeout(Duration::from_secs(config.timeout))
|
|
.build()
|
|
.expect("Failed to build reqwest client");
|
|
Self { config, client }
|
|
}
|
|
/// Builds the request to send the event.
|
|
fn build_request(&self, event: &Event) -> RequestBuilder {
|
|
let mut request = self.client.post(&self.config.endpoint).json(event);
|
|
if let Some(token) = &self.config.auth_token {
|
|
request = request.header("Authorization", format!("Bearer {}", token));
|
|
}
|
|
if let Some(headers) = &self.config.custom_headers {
|
|
for (key, value) in headers {
|
|
request = request.header(key, value);
|
|
}
|
|
}
|
|
request
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl ChannelAdapter for WebhookAdapter {
|
|
fn name(&self) -> String {
|
|
"webhook".to_string()
|
|
}
|
|
|
|
async fn send(&self, event: &Event) -> Result<(), Error> {
|
|
let mut attempt = 0;
|
|
loop {
|
|
match self.build_request(event).send().await {
|
|
Ok(response) => {
|
|
response.error_for_status().map_err(Error::Http)?;
|
|
return Ok(());
|
|
}
|
|
Err(e) if attempt < self.config.max_retries => {
|
|
attempt += 1;
|
|
tracing::warn!("Webhook attempt {} failed: {}. Retrying...", attempt, e);
|
|
sleep(Duration::from_secs(2u64.pow(attempt))).await;
|
|
}
|
|
Err(e) => return Err(Error::Http(e)),
|
|
}
|
|
}
|
|
}
|
|
}
|