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 HttpProducerConfig {
68 #[serde(default = "default_http_port")]
69 pub port: u16,
70}
71
72impl Default for HttpProducerConfig {
73 fn default() -> Self {
74 Self {
75 port: default_http_port(),
76 }
77 }
78}
79
80fn default_http_port() -> u16 {
81 3000
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct NotificationConfig {
87 #[serde(default = "default_store_path")]
88 pub store_path: String,
89 #[serde(default = "default_channel_capacity")]
90 pub channel_capacity: usize,
91 pub adapters: Vec<AdapterConfig>,
92 #[serde(default)]
93 pub http: HttpProducerConfig,
94}
95
96impl Default for NotificationConfig {
97 fn default() -> Self {
98 Self {
99 store_path: default_store_path(),
100 channel_capacity: default_channel_capacity(),
101 adapters: Vec::new(),
102 http: HttpProducerConfig::default(),
103 }
104 }
105}
106
107impl NotificationConfig {
108 pub fn new() -> Self {
110 Self::default()
111 }
112
113 pub fn from_file(path: &str) -> Result<Self, Error> {
115 let config = figment::Figment::new()
116 .merge(figment::providers::Toml::file(path))
117 .extract()?;
118
119 Ok(config)
120 }
121
122 pub fn load() -> Result<Self, Error> {
124 let figment = figment::Figment::new()
125 .merge(figment::providers::Toml::file("event.toml"))
127 .merge(figment::providers::Yaml::file("event.yaml"))
129 .merge(figment::providers::Env::prefixed("EVENT_NOTIF_"));
131
132 Ok(figment.extract()?)
133 }
134
135 pub fn from_env_file(path: &str) -> Result<Self, Error> {
137 dotenv::from_path(path)
139 .map_err(|e| Error::ConfigError(format!("unable to load env file: {}", e)))?;
140
141 let figment =
143 figment::Figment::new().merge(figment::providers::Env::prefixed("EVENT_NOTIF_"));
144
145 Ok(figment.extract()?)
146 }
147}
148
149fn default_store_path() -> String {
151 std::env::temp_dir()
152 .join("event-notification")
153 .to_string_lossy()
154 .to_string()
155}
156
157fn default_channel_capacity() -> usize {
159 10000 }