@@ -9,6 +9,7 @@ use serde::de::Error;
99use serde:: { Deserialize , Deserializer , Serialize } ;
1010use std:: net:: { SocketAddr , ToSocketAddrs } ;
1111use std:: path:: { Path , PathBuf } ;
12+ use std:: time:: Duration ;
1213
1314#[ cfg( not( feature = "lambda-web" ) ) ]
1415const DEFAULT_DATABASE_FILE : & str = "sqlpage.db" ;
@@ -73,6 +74,8 @@ impl AppConfig {
7374 . validate ( )
7475 . context ( "The provided configuration is invalid" ) ?;
7576
77+ config. resolve_timeouts ( ) ;
78+
7679 log:: debug!( "Loaded configuration: {config:#?}" ) ;
7780 log:: info!(
7881 "Configuration loaded from {}" ,
@@ -82,6 +85,26 @@ impl AppConfig {
8285 Ok ( config)
8386 }
8487
88+ fn resolve_timeouts ( & mut self ) {
89+ let is_sqlite = self . database_url . starts_with ( "sqlite:" ) ;
90+ self . database_connection_idle_timeout = resolve_timeout (
91+ self . database_connection_idle_timeout_seconds_raw ,
92+ if is_sqlite {
93+ None
94+ } else {
95+ Some ( Duration :: from_secs ( 30 * 60 ) )
96+ } ,
97+ ) ;
98+ self . database_connection_max_lifetime = resolve_timeout (
99+ self . database_connection_max_lifetime_seconds_raw ,
100+ if is_sqlite {
101+ None
102+ } else {
103+ Some ( Duration :: from_secs ( 60 * 60 ) )
104+ } ,
105+ ) ;
106+ }
107+
85108 fn validate ( & self ) -> anyhow:: Result < ( ) > {
86109 if !self . web_root . is_dir ( ) {
87110 return Err ( anyhow:: anyhow!(
@@ -107,12 +130,12 @@ impl AppConfig {
107130 ) ) ;
108131 }
109132 }
110- if let Some ( idle_timeout) = self . database_connection_idle_timeout_seconds {
133+ if let Some ( idle_timeout) = self . database_connection_idle_timeout_seconds_raw {
111134 if idle_timeout < 0.0 {
112135 log:: warn!( "Database connection idle timeout is negative, this will disable the timeout" ) ;
113136 }
114137 }
115- if let Some ( max_lifetime) = self . database_connection_max_lifetime_seconds {
138+ if let Some ( max_lifetime) = self . database_connection_max_lifetime_seconds_raw {
116139 if max_lifetime < 0.0 {
117140 log:: warn!( "Database connection max lifetime is negative, this will disable the timeout" ) ;
118141 }
@@ -142,8 +165,15 @@ pub struct AppConfig {
142165 #[ serde( default ) ]
143166 pub database_password : Option < String > ,
144167 pub max_database_pool_connections : Option < u32 > ,
145- pub database_connection_idle_timeout_seconds : Option < f64 > ,
146- pub database_connection_max_lifetime_seconds : Option < f64 > ,
168+ #[ serde( rename = "database_connection_idle_timeout_seconds" ) ]
169+ pub database_connection_idle_timeout_seconds_raw : Option < f64 > ,
170+ #[ serde( rename = "database_connection_max_lifetime_seconds" ) ]
171+ pub database_connection_max_lifetime_seconds_raw : Option < f64 > ,
172+
173+ #[ serde( skip) ]
174+ pub database_connection_idle_timeout : Option < Duration > ,
175+ #[ serde( skip) ]
176+ pub database_connection_max_lifetime : Option < Duration > ,
147177
148178 #[ serde( default ) ]
149179 pub sqlite_extensions : Vec < String > ,
@@ -607,6 +637,14 @@ impl DevOrProd {
607637 }
608638}
609639
640+ fn resolve_timeout ( config_val : Option < f64 > , default : Option < Duration > ) -> Option < Duration > {
641+ match config_val {
642+ Some ( v) if v <= 0.0 || !v. is_finite ( ) => None ,
643+ Some ( v) => Some ( Duration :: from_secs_f64 ( v) ) ,
644+ None => default,
645+ }
646+ }
647+
610648#[ must_use]
611649pub fn test_database_url ( ) -> String {
612650 std:: env:: var ( "DATABASE_URL" ) . unwrap_or_else ( |_| "sqlite::memory:" . to_string ( ) )
@@ -619,14 +657,16 @@ pub mod tests {
619657
620658 #[ must_use]
621659 pub fn test_config ( ) -> AppConfig {
622- serde_json:: from_str :: < AppConfig > (
660+ let mut config = serde_json:: from_str :: < AppConfig > (
623661 & serde_json:: json!( {
624662 "database_url" : test_database_url( ) ,
625663 "listen_on" : "localhost:8080"
626664 } )
627665 . to_string ( ) ,
628666 )
629- . unwrap ( )
667+ . unwrap ( ) ;
668+ config. resolve_timeouts ( ) ;
669+ config
630670 }
631671}
632672
0 commit comments