@@ -6,6 +6,7 @@ use crate::settings;
66use crate :: setup;
77use crate :: { builder:: AnalyzedFlow , execution:: query:: SimpleSemanticsQueryHandler } ;
88use axum:: http:: StatusCode ;
9+ use sqlx:: postgres:: PgConnectOptions ;
910use sqlx:: PgPool ;
1011use std:: collections:: BTreeMap ;
1112use tokio:: runtime:: Runtime ;
@@ -61,8 +62,40 @@ impl FlowContext {
6162static TOKIO_RUNTIME : LazyLock < Runtime > = LazyLock :: new ( || Runtime :: new ( ) . unwrap ( ) ) ;
6263static AUTH_REGISTRY : LazyLock < Arc < AuthRegistry > > = LazyLock :: new ( || Arc :: new ( AuthRegistry :: new ( ) ) ) ;
6364
65+ #[ derive( Default ) ]
66+ pub struct DbPools {
67+ pub pools : Mutex < HashMap < ( String , Option < String > ) , Arc < tokio:: sync:: OnceCell < PgPool > > > > ,
68+ }
69+
70+ impl DbPools {
71+ pub async fn get_pool ( & self , conn_spec : & settings:: DatabaseConnectionSpec ) -> Result < PgPool > {
72+ let db_pool_cell = {
73+ let key = ( conn_spec. uri . clone ( ) , conn_spec. user . clone ( ) ) ;
74+ let mut db_pools = self . pools . lock ( ) . unwrap ( ) ;
75+ db_pools. entry ( key) . or_default ( ) . clone ( )
76+ } ;
77+ let pool = db_pool_cell
78+ . get_or_try_init ( || async move {
79+ let mut pg_options: PgConnectOptions = conn_spec. uri . parse ( ) ?;
80+ if let Some ( user) = & conn_spec. user {
81+ pg_options = pg_options. username ( user) ;
82+ }
83+ if let Some ( password) = & conn_spec. password {
84+ pg_options = pg_options. password ( password) ;
85+ }
86+ let pool = PgPool :: connect_with ( pg_options)
87+ . await
88+ . context ( "Failed to connect to database" ) ?;
89+ anyhow:: Ok ( pool)
90+ } )
91+ . await ?;
92+ Ok ( pool. clone ( ) )
93+ }
94+ }
95+
6496pub struct LibContext {
65- pub pool : PgPool ,
97+ pub db_pools : DbPools ,
98+ pub builtin_db_pool : PgPool ,
6699 pub flows : Mutex < BTreeMap < String , Arc < FlowContext > > > ,
67100 pub all_setup_states : RwLock < setup:: AllSetupState < setup:: ExistingMode > > ,
68101}
@@ -100,13 +133,15 @@ pub fn create_lib_context(settings: settings::Settings) -> Result<LibContext> {
100133 pyo3_async_runtimes:: tokio:: init_with_runtime ( get_runtime ( ) ) . unwrap ( ) ;
101134 } ) ;
102135
136+ let db_pools = DbPools :: default ( ) ;
103137 let ( pool, all_setup_states) = get_runtime ( ) . block_on ( async {
104- let pool = PgPool :: connect ( & settings. database_url ) . await ?;
138+ let pool = db_pools . get_pool ( & settings. database ) . await ?;
105139 let existing_ss = setup:: get_existing_setup_state ( & pool) . await ?;
106140 anyhow:: Ok ( ( pool, existing_ss) )
107141 } ) ?;
108142 Ok ( LibContext {
109- pool,
143+ db_pools,
144+ builtin_db_pool : pool,
110145 all_setup_states : RwLock :: new ( all_setup_states) ,
111146 flows : Mutex :: new ( BTreeMap :: new ( ) ) ,
112147 } )
0 commit comments