event_notification/
config.rs1use crate::Error;
2use figment::providers::Format;
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct WebhookConfig {
9 pub endpoint: String,
10 pub auth_token: Option<String>,
11 pub custom_headers: Option<HashMap<String, String>>,
12 pub max_retries: u32,
13 pub timeout: u64,
14}
15
16impl WebhookConfig {
17 pub fn validate(&self) -> Result<(), String> {
19 if self.endpoint.trim().is_empty() {
21 return Err("Webhook endpoint cannot be empty".to_string());
22 }
23
24 if self.timeout == 0 {
26 return Err("Webhook timeout must be greater than 0".to_string());
27 }
28
29 if self.max_retries > 10 {
31 return Err("Maximum retry count cannot exceed 10".to_string());
32 }
33
34 Ok(())
35 }
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct KafkaConfig {
41 pub brokers: String,
42 pub topic: String,
43 pub max_retries: u32,
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize)]
48pub struct MqttConfig {
49 pub broker: String,
50 pub port: u16,
51 pub client_id: String,
52 pub topic: String,
53 pub max_retries: u32,
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize)]
58#[serde(tag = "type")]
59pub enum AdapterConfig {
60 Webhook(WebhookConfig),
61 Kafka(KafkaConfig),
62 Mqtt(MqttConfig),
63}
64
65#[derive(Debug, Clone, Serialize, Deserialize)]
67pub struct NotificationConfig {
68 #[serde(default = "default_store_path")]
69 pub store_path: String,
70 #[serde(default = "default_channel_capacity")]
71 pub channel_capacity: usize,
72 pub adapters: Vec<AdapterConfig>,
73}
74
75impl Default for NotificationConfig {
76 fn default() -> Self {
77 Self {
78 store_path: default_store_path(),
79 channel_capacity: default_channel_capacity(),
80 adapters: Vec::new(),
81 }
82 }
83}
84
85impl NotificationConfig {
86 pub fn new() -> Self {
88 Self::default()
89 }
90
91 pub fn from_file(path: &str) -> Result<Self, Error> {
93 let config = figment::Figment::new()
94 .merge(figment::providers::Toml::file(path))
95 .extract()?;
96
97 Ok(config)
98 }
99
100 pub fn load() -> Result<Self, Error> {
102 let figment = figment::Figment::new()
103 .merge(figment::providers::Toml::file("event.toml"))
105 .merge(figment::providers::Yaml::file("event.yaml"))
107 .merge(figment::providers::Env::prefixed("EVENT_NOTIF_"));
109
110 Ok(figment.extract()?)
111 }
112
113 pub fn from_env_file(path: &str) -> Result<Self, Error> {
115 dotenv::from_path(path)
117 .map_err(|e| Error::ConfigError(format!("unable to load env file: {}", e)))?;
118
119 let figment =
121 figment::Figment::new().merge(figment::providers::Env::prefixed("EVENT_NOTIF_"));
122
123 Ok(figment.extract()?)
124 }
125}
126
127fn default_store_path() -> String {
129 std::env::temp_dir()
130 .join("event-notification")
131 .to_string_lossy()
132 .to_string()
133}
134
135fn default_channel_capacity() -> usize {
137 10000 }