@@ -77,11 +77,15 @@ impl DbPools {
7777 }
7878}
7979
80+ pub struct PersistenceContext {
81+ pub builtin_db_pool : PgPool ,
82+ pub all_setup_states : RwLock < setup:: AllSetupState < setup:: ExistingMode > > ,
83+ }
84+
8085pub struct LibContext {
8186 pub db_pools : DbPools ,
82- pub builtin_db_pool : Option < PgPool > ,
87+ pub persistence_ctx : Option < PersistenceContext > ,
8388 pub flows : Mutex < BTreeMap < String , Arc < FlowContext > > > ,
84- pub all_setup_states : RwLock < setup:: AllSetupState < setup:: ExistingMode > > ,
8589}
8690
8791impl LibContext {
@@ -100,8 +104,16 @@ impl LibContext {
100104 }
101105
102106 pub fn require_builtin_db_pool ( & self ) -> Result < & PgPool > {
103- self . builtin_db_pool
107+ self . persistence_ctx
108+ . as_ref ( )
109+ . map ( |ctx| & ctx. builtin_db_pool )
110+ . ok_or_else ( || anyhow ! ( "Database is required for this operation. Please set COCOINDEX_DATABASE_URL environment variable and call cocoindex.init() with database settings." ) )
111+ }
112+
113+ pub fn require_all_setup_states ( & self ) -> Result < & RwLock < setup:: AllSetupState < setup:: ExistingMode > > > {
114+ self . persistence_ctx
104115 . as_ref ( )
116+ . map ( |ctx| & ctx. all_setup_states )
105117 . ok_or_else ( || anyhow ! ( "Database is required for this operation. Please set COCOINDEX_DATABASE_URL environment variable and call cocoindex.init() with database settings." ) )
106118 }
107119}
@@ -123,22 +135,24 @@ pub fn create_lib_context(settings: settings::Settings) -> Result<LibContext> {
123135 } ) ;
124136
125137 let db_pools = DbPools :: default ( ) ;
126- let ( pool , all_setup_states ) = if let Some ( database_spec) = & settings. database {
138+ let persistence_ctx = if let Some ( database_spec) = & settings. database {
127139 let ( pool, all_setup_states) = get_runtime ( ) . block_on ( async {
128140 let pool = db_pools. get_pool ( database_spec) . await ?;
129141 let existing_ss = setup:: get_existing_setup_state ( & pool) . await ?;
130- anyhow:: Ok ( ( Some ( pool) , existing_ss) )
142+ anyhow:: Ok ( ( pool, existing_ss) )
131143 } ) ?;
132- ( pool, all_setup_states)
144+ Some ( PersistenceContext {
145+ builtin_db_pool : pool,
146+ all_setup_states : RwLock :: new ( all_setup_states) ,
147+ } )
133148 } else {
134- // No database configured - create empty setup states
135- ( None , setup :: AllSetupState :: default ( ) )
149+ // No database configured
150+ None
136151 } ;
137152
138153 Ok ( LibContext {
139154 db_pools,
140- builtin_db_pool : pool,
141- all_setup_states : RwLock :: new ( all_setup_states) ,
155+ persistence_ctx,
142156 flows : Mutex :: new ( BTreeMap :: new ( ) ) ,
143157 } )
144158}
@@ -185,4 +199,35 @@ mod tests {
185199 assert ! ( settings. database. is_none( ) ) ;
186200 assert_eq ! ( settings. app_namespace, "test" ) ;
187201 }
202+
203+ #[ test]
204+ fn test_lib_context_without_database ( ) {
205+ let settings = settings:: Settings {
206+ database : None ,
207+ app_namespace : "test" . to_string ( ) ,
208+ } ;
209+
210+ let lib_context = create_lib_context ( settings) . unwrap ( ) ;
211+ assert ! ( lib_context. persistence_ctx. is_none( ) ) ;
212+ assert ! ( lib_context. require_builtin_db_pool( ) . is_err( ) ) ;
213+ assert ! ( lib_context. require_all_setup_states( ) . is_err( ) ) ;
214+ }
215+
216+ #[ test]
217+ fn test_persistence_context_type_safety ( ) {
218+ // This test ensures that PersistenceContext groups related fields together
219+ let settings = settings:: Settings {
220+ database : Some ( settings:: DatabaseConnectionSpec {
221+ url : "postgresql://test" . to_string ( ) ,
222+ user : None ,
223+ password : None ,
224+ } ) ,
225+ app_namespace : "test" . to_string ( ) ,
226+ } ;
227+
228+ // This would fail at runtime due to invalid connection, but we're testing the structure
229+ let result = create_lib_context ( settings) ;
230+ // We expect this to fail due to invalid connection, but the structure should be correct
231+ assert ! ( result. is_err( ) ) ;
232+ }
188233}
0 commit comments