Skip to main content

fraiseql_server/config/
mod.rs

1use std::{collections::HashMap, path::PathBuf};
2
3use serde::Deserialize;
4
5pub mod cors;
6pub mod env;
7pub mod loader;
8pub mod metrics;
9pub mod rate_limiting;
10#[cfg(test)]
11mod tests;
12pub mod tracing;
13pub mod validation;
14
15// Re-export config types
16pub use cors::CorsConfig;
17pub use metrics::{LatencyTargets, MetricsConfig, SloConfig};
18pub use rate_limiting::{BackpressureConfig, RateLimitRule, RateLimitingConfig};
19pub use tracing::TracingConfig;
20
21/// Root configuration structure
22#[derive(Debug, Clone, Deserialize)]
23pub struct RuntimeConfig {
24    pub server:   ServerConfig,
25    pub database: DatabaseConfig,
26
27    #[serde(default)]
28    pub webhooks: HashMap<String, WebhookConfig>,
29
30    #[serde(default)]
31    pub files: HashMap<String, FileConfig>,
32
33    #[serde(default)]
34    pub auth: Option<AuthConfig>,
35
36    #[serde(default)]
37    pub notifications: Option<NotificationsConfig>,
38
39    #[serde(default)]
40    pub observers: HashMap<String, ObserverConfig>,
41
42    #[serde(default)]
43    pub interceptors: HashMap<String, Vec<String>>,
44
45    #[serde(default)]
46    pub rate_limiting: Option<RateLimitingConfig>,
47
48    #[serde(default)]
49    pub cors: Option<CorsConfig>,
50
51    #[serde(default)]
52    pub metrics: Option<MetricsConfig>,
53
54    #[serde(default)]
55    pub tracing: Option<TracingConfig>,
56
57    #[serde(default)]
58    pub logging: Option<LoggingConfig>,
59
60    #[serde(default)]
61    pub storage: HashMap<String, StorageConfig>,
62
63    #[serde(default)]
64    pub search: Option<SearchConfig>,
65
66    #[serde(default)]
67    pub cache: Option<CacheConfig>,
68
69    #[serde(default)]
70    pub queues: Option<QueueConfig>,
71
72    #[serde(default)]
73    pub realtime: Option<RealtimeConfig>,
74
75    #[serde(default)]
76    pub custom_endpoints: Option<CustomEndpointsConfig>,
77
78    #[serde(default)]
79    pub lifecycle: Option<LifecycleConfig>,
80}
81
82#[derive(Debug, Clone, Deserialize)]
83pub struct ServerConfig {
84    #[serde(default = "default_port")]
85    pub port: u16,
86
87    #[serde(default = "default_host")]
88    pub host: String,
89
90    #[serde(default)]
91    pub workers: Option<usize>,
92
93    #[serde(default)]
94    pub tls: Option<TlsConfig>,
95
96    #[serde(default)]
97    pub limits: Option<ServerLimitsConfig>,
98}
99
100fn default_port() -> u16 {
101    4000
102}
103fn default_host() -> String {
104    "127.0.0.1".to_string()
105}
106
107#[derive(Debug, Clone, Deserialize)]
108pub struct TlsConfig {
109    pub cert_file: PathBuf,
110    pub key_file:  PathBuf,
111}
112
113#[derive(Debug, Clone, Deserialize)]
114pub struct ServerLimitsConfig {
115    #[serde(default = "default_max_request_size")]
116    pub max_request_size: String,
117
118    #[serde(default = "default_request_timeout")]
119    pub request_timeout: String,
120
121    #[serde(default = "default_max_concurrent")]
122    pub max_concurrent_requests: usize,
123
124    #[serde(default = "default_max_queue_depth")]
125    pub max_queue_depth: usize,
126}
127
128fn default_max_request_size() -> String {
129    "10MB".to_string()
130}
131fn default_request_timeout() -> String {
132    "30s".to_string()
133}
134fn default_max_concurrent() -> usize {
135    1000
136}
137fn default_max_queue_depth() -> usize {
138    5000
139}
140
141#[derive(Debug, Clone, Deserialize)]
142pub struct DatabaseConfig {
143    pub url_env: String,
144
145    #[serde(default = "default_pool_size")]
146    pub pool_size: u32,
147
148    #[serde(default)]
149    pub pool_timeout: Option<String>,
150
151    #[serde(default)]
152    pub statement_timeout: Option<String>,
153
154    #[serde(default)]
155    pub replicas: Vec<ReplicaConfig>,
156
157    #[serde(default)]
158    pub health_check_interval: Option<String>,
159}
160
161fn default_pool_size() -> u32 {
162    10
163}
164
165#[derive(Debug, Clone, Deserialize)]
166pub struct ReplicaConfig {
167    pub url_env: String,
168
169    #[serde(default = "default_weight")]
170    pub weight: u32,
171}
172
173fn default_weight() -> u32 {
174    1
175}
176
177/// Lifecycle configuration for graceful shutdown
178#[derive(Debug, Clone, Deserialize)]
179pub struct LifecycleConfig {
180    /// Time to wait for in-flight requests to complete
181    #[serde(default = "default_shutdown_timeout")]
182    pub shutdown_timeout: String,
183
184    /// Time to wait before starting shutdown (for load balancer deregistration)
185    #[serde(default = "default_shutdown_delay")]
186    pub shutdown_delay: String,
187
188    /// Health check endpoint path
189    #[serde(default = "default_health_path")]
190    pub health_path: String,
191
192    /// Readiness check endpoint path
193    #[serde(default = "default_ready_path")]
194    pub ready_path: String,
195}
196
197impl Default for LifecycleConfig {
198    fn default() -> Self {
199        Self {
200            shutdown_timeout: default_shutdown_timeout(),
201            shutdown_delay:   default_shutdown_delay(),
202            health_path:      default_health_path(),
203            ready_path:       default_ready_path(),
204        }
205    }
206}
207
208fn default_shutdown_timeout() -> String {
209    "30s".to_string()
210}
211fn default_shutdown_delay() -> String {
212    "5s".to_string()
213}
214fn default_health_path() -> String {
215    "/health".to_string()
216}
217fn default_ready_path() -> String {
218    "/ready".to_string()
219}
220
221// Placeholder structs for future phases (TODO: will be defined in later phases)
222
223#[derive(Debug, Clone, Deserialize)]
224pub struct WebhookConfig {
225    pub secret_env: String,
226    pub provider:   String,
227    #[serde(default)]
228    pub path:       Option<String>,
229}
230
231#[derive(Debug, Clone, Deserialize)]
232pub struct FileConfig {
233    pub storage:  String,
234    pub max_size: String,
235    #[serde(default)]
236    pub path:     Option<String>,
237}
238
239#[derive(Debug, Clone, Deserialize)]
240pub struct AuthConfig {
241    pub jwt:               JwtConfig,
242    #[serde(default)]
243    pub providers:         HashMap<String, OAuthProviderConfig>,
244    #[serde(default)]
245    pub callback_base_url: Option<String>,
246}
247
248#[derive(Debug, Clone, Deserialize)]
249pub struct JwtConfig {
250    pub secret_env: String,
251}
252
253#[derive(Debug, Clone, Deserialize)]
254pub struct OAuthProviderConfig {
255    pub provider_type:     String,
256    pub client_id_env:     String,
257    pub client_secret_env: String,
258    #[serde(default)]
259    pub issuer_url:        Option<String>,
260}
261
262#[derive(Debug, Clone, Deserialize)]
263pub struct NotificationsConfig {
264    // Placeholder for notification system
265}
266
267#[derive(Debug, Clone, Deserialize)]
268pub struct ObserverConfig {
269    pub entity:  String,
270    pub events:  Vec<String>,
271    pub actions: Vec<ActionConfig>,
272}
273
274#[derive(Debug, Clone, Deserialize)]
275pub struct ActionConfig {
276    #[serde(rename = "type")]
277    pub action_type: String,
278    #[serde(default)]
279    pub template:    Option<String>,
280}
281
282// These types are now defined in their own modules and re-exported above
283
284#[derive(Debug, Clone, Deserialize)]
285pub struct LoggingConfig {
286    // Placeholder for advanced logging configuration
287}
288
289#[derive(Debug, Clone, Deserialize)]
290pub struct StorageConfig {
291    pub backend: String,
292    #[serde(default)]
293    pub bucket:  Option<String>,
294    #[serde(default)]
295    pub path:    Option<String>,
296}
297
298#[derive(Debug, Clone, Deserialize)]
299pub struct SearchConfig {
300    // Placeholder for search indexing support
301}
302
303#[derive(Debug, Clone, Deserialize)]
304pub struct CacheConfig {
305    // Placeholder for advanced caching strategies
306}
307
308#[derive(Debug, Clone, Deserialize)]
309pub struct QueueConfig {
310    // Placeholder for job queue support
311}
312
313#[derive(Debug, Clone, Deserialize)]
314pub struct RealtimeConfig {
315    // Placeholder for real-time updates support
316}
317
318#[derive(Debug, Clone, Deserialize)]
319pub struct CustomEndpointsConfig {
320    // Placeholder for custom endpoint support
321}